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