1 // Copyright 2018 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef CHROME_BROWSER_CHROMEOS_LOGIN_DEMO_MODE_DEMO_SESSION_H_
6 #define CHROME_BROWSER_CHROMEOS_LOGIN_DEMO_MODE_DEMO_SESSION_H_
7 
8 #include <memory>
9 #include <string>
10 #include <vector>
11 
12 #include "base/callback_forward.h"
13 #include "base/macros.h"
14 #include "base/memory/scoped_refptr.h"
15 #include "base/memory/weak_ptr.h"
16 #include "base/scoped_observer.h"
17 #include "chrome/browser/chromeos/login/demo_mode/demo_extensions_external_loader.h"
18 #include "components/session_manager/core/session_manager.h"
19 #include "components/session_manager/core/session_manager_observer.h"
20 #include "components/user_manager/user_manager.h"
21 #include "extensions/browser/app_window/app_window_registry.h"
22 #include "extensions/browser/extension_registry.h"
23 #include "extensions/browser/extension_registry_observer.h"
24 
25 class PrefRegistrySimple;
26 
27 namespace base {
28 class OneShotTimer;
29 }
30 
31 namespace chromeos {
32 
33 class DemoResources;
34 
35 // Tracks global demo session state, such as whether the demo session has
36 // started and the state of demo mode resources.
37 class DemoSession : public session_manager::SessionManagerObserver,
38                     public extensions::ExtensionRegistryObserver,
39                     public user_manager::UserManager::UserSessionStateObserver,
40                     public extensions::AppWindowRegistry::Observer {
41  public:
42   // Type of demo mode configuration.
43   // Warning: DemoModeConfig is stored in local state. Existing entries should
44   // not be reordered and new values should be added at the end.
45   enum class DemoModeConfig : int {
46     // No demo mode configuration or configuration unknown.
47     kNone = 0,
48     // Online enrollment into demo mode was established with DMServer.
49     // Policies are applied from the cloud.
50     kOnline = 1,
51     // Offline enrollment into demo mode was established locally.
52     // Offline policy set is applied to the device.
53     kOffline = 2,
54     // Add new entries above this line and make sure to update kLast value.
55     kLast = kOffline,
56   };
57 
58   // Indicates the source of an app launch when in Demo mode for UMA
59   // stat reporting purposes.  Because they are used for a UMA stat,
60   // these values should not be changed or moved.
61   enum class AppLaunchSource {
62     // Logged when apps are launched from the Shelf in Demo Mode.
63     kShelf = 0,
64     // Logged when apps are launched from the App List in Demo Mode.
65     kAppList = 1,
66     // Logged by any Extension APIs used by the Highlights App to launch apps in
67     // Demo Mode.
68     kExtensionApi = 2,
69     // Add future entries above this comment, in sync with enums.xml.
70     // Update kMaxValue to the last value.
71     kMaxValue = kExtensionApi
72   };
73 
74   // The list of countries that Demo Mode supports, ie the countries we have
75   // created OUs and admin users for in the admin console.
76   // Sorted by the English name of the country (not the country code), except US
77   // is first.
78   // TODO(crbug.com/983359): Sort these by country name in the current locale
79   // instead of using this hard-coded US-centric order.
80   static constexpr char kSupportedCountries[][3] = {
81       "us", "be", "ca", "dk", "fi", "fr", "de", "ie",
82       "it", "jp", "lu", "nl", "no", "es", "se", "gb"};
83 
84   static std::string DemoConfigToString(DemoModeConfig config);
85 
86   // Whether the device is set up to run demo sessions.
87   static bool IsDeviceInDemoMode();
88 
89   // Whether the device is set up to enroll Demo Mode offline.
90   // The device needs to be set up for Demo Mode in order to return true.
91   // TODO(b/154290639): Move into anonymous namespace when fixed.
92   static bool IsDemoModeOfflineEnrolled();
93 
94   // Returns current demo mode configuration.
95   static DemoModeConfig GetDemoConfig();
96 
97   // Sets demo mode configuration for tests. Should be cleared by calling
98   // ResetDemoConfigForTesting().
99   static void SetDemoConfigForTesting(DemoModeConfig demo_config);
100 
101   // Resets demo mode configuration that was used for tests.
102   static void ResetDemoConfigForTesting();
103 
104   // If the device is set up to run in demo mode, marks demo session as started,
105   // and requests load of demo session resources.
106   // Creates global DemoSession instance if required.
107   static DemoSession* StartIfInDemoMode();
108 
109   // Requests load of demo session resources, without marking the demo session
110   // as started. Creates global DemoSession instance if required.
111   static void PreloadOfflineResourcesIfInDemoMode();
112 
113   // Deletes the global DemoSession instance if it was previously created.
114   static void ShutDownIfInitialized();
115 
116   // Gets the global demo session instance. Returns nullptr if the DemoSession
117   // instance has not yet been initialized (either by calling
118   // StartIfInDemoMode() or PreloadOfflineResourcesIfInDemoMode()).
119   static DemoSession* Get();
120 
121   // Returns the id of the screensaver app based on the board name.
122   static std::string GetScreensaverAppId();
123 
124   // Returns whether the app with `app_id` should be displayed in app launcher
125   // in demo mode. Returns true for all apps in non-demo mode.
126   static bool ShouldDisplayInAppLauncher(const std::string& app_id);
127 
128   // Returns the list of countries that Demo Mode supports. Each country is
129   // denoted by:
130   // `value`: The ISO country code.
131   // `title`: The display name of the country in the current locale.
132   // `selected`: Whether the country is currently selected.
133   static base::Value GetCountryList();
134 
135   static void RegisterLocalStatePrefs(PrefRegistrySimple* registry);
136 
137   // Records the launch of an app in Demo mode from the specified source.
138   static void RecordAppLaunchSourceIfInDemoMode(AppLaunchSource source);
139 
140   // Ensures that the load of offline demo session resources is requested.
141   // `load_callback` will be run once the offline resource load finishes.
142   void EnsureOfflineResourcesLoaded(base::OnceClosure load_callback);
143 
144   // Returns true if the Chrome app or ARC++ package, which is normally pinned
145   // by policy, should actually not be force-pinned because the device is
146   // in Demo Mode and offline.
147   bool ShouldIgnorePinPolicy(const std::string& app_id_or_package);
148 
149   // Sets `extensions_external_loader_` and starts installing the screensaver.
150   void SetExtensionsExternalLoader(
151       scoped_refptr<DemoExtensionsExternalLoader> extensions_external_loader);
152 
153   // Sets app IDs and package names that shouldn't be pinned by policy when the
154   // device is offline in Demo Mode.
155   void OverrideIgnorePinPolicyAppsForTesting(std::vector<std::string> apps);
156 
157   void SetTimerForTesting(std::unique_ptr<base::OneShotTimer> timer);
158   base::OneShotTimer* GetTimerForTesting();
159 
160   // user_manager::UserManager::UserSessionStateObserver:
161   void ActiveUserChanged(user_manager::User* active_user) override;
162 
163   // extensions::AppWindowRegistry::Observer:
164   void OnAppWindowActivated(extensions::AppWindow* app_window) override;
165 
offline_enrolled()166   bool offline_enrolled() const { return offline_enrolled_; }
167 
started()168   bool started() const { return started_; }
169 
resources()170   const DemoResources* resources() const { return demo_resources_.get(); }
171 
172  private:
173   DemoSession();
174   ~DemoSession() override;
175 
176   // Installs resources for Demo Mode from the offline demo mode resources, such
177   // as apps and media.
178   void InstallDemoResources();
179 
180   // Loads the highlights app from offline resources and launches it upon
181   // success.
182   void LoadAndLaunchHighlightsApp();
183 
184   // Installs the CRX file from an update URL. Observes `ExtensionRegistry` to
185   // launch the app upon installation.
186   void InstallAppFromUpdateUrl(const std::string& id);
187 
188   // Shows the splash screen after demo mode resources are installed.
189   void ShowSplashScreen();
190 
191   // Removes the splash screen.
192   void RemoveSplashScreen();
193 
194   // Returns whether splash screen should be removed. The splash screen should
195   // be removed when both active session starts (i.e. login screen is destroyed)
196   // and screensaver is shown, to ensure a smooth transition.
197   bool ShouldRemoveSplashScreen();
198 
199   // session_manager::SessionManagerObserver:
200   void OnSessionStateChanged() override;
201 
202   // extensions::ExtensionRegistryObserver:
203   void OnExtensionInstalled(content::BrowserContext* browser_context,
204                             const extensions::Extension* extension,
205                             bool is_update) override;
206 
207   // Whether the device was offline-enrolled into demo mode, i.e. enrolled using
208   // pre-built policies. Offline enrolled demo sessions do not have working
209   // robot account associated with them.
210   bool offline_enrolled_ = false;
211 
212   // Whether demo session has been started.
213   bool started_ = false;
214 
215   // Apps that ShouldIgnorePinPolicy() will check for if the device is offline.
216   std::vector<std::string> ignore_pin_policy_offline_apps_;
217 
218   std::unique_ptr<DemoResources> demo_resources_;
219 
220   ScopedObserver<session_manager::SessionManager,
221                  session_manager::SessionManagerObserver>
222       session_manager_observer_{this};
223 
224   ScopedObserver<extensions::ExtensionRegistry,
225                  extensions::ExtensionRegistryObserver>
226       extension_registry_observer_{this};
227 
228   ScopedObserver<extensions::AppWindowRegistry,
229                  extensions::AppWindowRegistry::Observer>
230       app_window_registry_observer_{this};
231 
232   scoped_refptr<DemoExtensionsExternalLoader> extensions_external_loader_;
233 
234   // The fallback timer that ensures the splash screen is removed in case the
235   // screensaver app takes an extra long time to be shown.
236   std::unique_ptr<base::OneShotTimer> remove_splash_screen_fallback_timer_;
237 
238   bool splash_screen_removed_ = false;
239   bool screensaver_activated_ = false;
240 
241   base::WeakPtrFactory<DemoSession> weak_ptr_factory_{this};
242 
243   DISALLOW_COPY_AND_ASSIGN(DemoSession);
244 };
245 
246 }  // namespace chromeos
247 
248 #endif  // CHROME_BROWSER_CHROMEOS_LOGIN_DEMO_MODE_DEMO_SESSION_H_
249