No dual_mode on Win10+ shortcuts.
[chromium-blink-merge.git] / chrome / browser / background / background_mode_manager.h
blob11e1fcd6b0ed27bd3cb4d9be562e1e20f3826271
1 // Copyright (c) 2012 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.
5 #ifndef CHROME_BROWSER_BACKGROUND_BACKGROUND_MODE_MANAGER_H_
6 #define CHROME_BROWSER_BACKGROUND_BACKGROUND_MODE_MANAGER_H_
8 #include <map>
10 #include "base/gtest_prod_util.h"
11 #include "base/memory/scoped_vector.h"
12 #include "base/memory/weak_ptr.h"
13 #include "base/prefs/pref_change_registrar.h"
14 #include "chrome/browser/background/background_application_list_model.h"
15 #include "chrome/browser/profiles/profile_info_cache_observer.h"
16 #include "chrome/browser/status_icons/status_icon.h"
17 #include "chrome/browser/status_icons/status_icon_menu_model.h"
18 #include "chrome/browser/ui/browser_list_observer.h"
19 #include "components/keyed_service/core/keyed_service.h"
20 #include "content/public/browser/notification_observer.h"
21 #include "content/public/browser/notification_registrar.h"
22 #include "extensions/common/extension.h"
24 class Browser;
25 class PrefRegistrySimple;
26 class Profile;
27 class ProfileInfoCache;
28 class StatusIcon;
29 class StatusTray;
31 namespace base {
32 class CommandLine;
35 typedef std::vector<int> CommandIdExtensionVector;
37 // BackgroundModeManager is responsible for switching Chrome into and out of
38 // "background mode" and for providing UI for the user to exit Chrome when there
39 // are no open browser windows.
41 // Chrome enters background mode whenever there is an application with the
42 // "background" permission installed. This class monitors the set of
43 // installed/loaded extensions to ensure that Chrome enters/exits background
44 // mode at the appropriate time.
46 // When Chrome is in background mode, it will continue running even after the
47 // last browser window is closed, until the user explicitly exits the app.
48 // Additionally, when in background mode, Chrome will launch on OS login with
49 // no open windows to allow apps with the "background" permission to run in the
50 // background.
51 class BackgroundModeManager
52 : public content::NotificationObserver,
53 public chrome::BrowserListObserver,
54 public BackgroundApplicationListModel::Observer,
55 public ProfileInfoCacheObserver,
56 public StatusIconMenuModel::Delegate {
57 public:
58 BackgroundModeManager(const base::CommandLine& command_line,
59 ProfileInfoCache* profile_cache);
60 ~BackgroundModeManager() override;
62 static void RegisterPrefs(PrefRegistrySimple* registry);
64 virtual void RegisterProfile(Profile* profile);
66 static void LaunchBackgroundApplication(Profile* profile,
67 const extensions::Extension* extension);
69 // Returns true if background mode is active.
70 virtual bool IsBackgroundModeActive();
72 // Suspends background mode until either ResumeBackgroundMode is called or
73 // Chrome is restarted. This has the same effect as ending background mode
74 // for the current browser session.
75 virtual void SuspendBackgroundMode();
77 // Resumes background mode. This ends a suspension of background mode, but
78 // will not start it if it is not enabled.
79 virtual void ResumeBackgroundMode();
81 // For testing purposes.
82 int NumberOfBackgroundModeData();
84 private:
85 friend class AppBackgroundPageApiTest;
86 friend class BackgroundModeManagerTest;
87 friend class BackgroundModeManagerWithExtensionsTest;
88 friend class AdvancedTestBackgroundModeManager;
89 FRIEND_TEST_ALL_PREFIXES(BackgroundModeManagerTest,
90 BackgroundAppLoadUnload);
91 FRIEND_TEST_ALL_PREFIXES(BackgroundModeManagerTest,
92 BackgroundLaunchOnStartup);
93 FRIEND_TEST_ALL_PREFIXES(BackgroundModeManagerTest,
94 BackgroundAppInstallUninstallWhileDisabled);
95 FRIEND_TEST_ALL_PREFIXES(BackgroundModeManagerTest,
96 BackgroundModeDisabledPreventsKeepAliveOnStartup);
97 FRIEND_TEST_ALL_PREFIXES(BackgroundModeManagerTest,
98 DisableBackgroundModeUnderTestFlag);
99 FRIEND_TEST_ALL_PREFIXES(BackgroundModeManagerTest,
100 EnableAfterBackgroundAppInstall);
101 FRIEND_TEST_ALL_PREFIXES(BackgroundModeManagerTest,
102 MultiProfile);
103 FRIEND_TEST_ALL_PREFIXES(BackgroundModeManagerTest,
104 ProfileInfoCacheStorage);
105 FRIEND_TEST_ALL_PREFIXES(BackgroundModeManagerTest,
106 ProfileInfoCacheObserver);
107 FRIEND_TEST_ALL_PREFIXES(BackgroundModeManagerTest,
108 DeleteBackgroundProfile);
109 FRIEND_TEST_ALL_PREFIXES(BackgroundModeManagerWithExtensionsTest,
110 BackgroundMenuGeneration);
111 FRIEND_TEST_ALL_PREFIXES(BackgroundModeManagerWithExtensionsTest,
112 BackgroundMenuGenerationMultipleProfile);
113 FRIEND_TEST_ALL_PREFIXES(BackgroundModeManagerWithExtensionsTest,
114 BalloonDisplay);
115 FRIEND_TEST_ALL_PREFIXES(BackgroundAppBrowserTest,
116 ReloadBackgroundApp);
118 class BackgroundModeData : public StatusIconMenuModel::Delegate {
119 public:
120 explicit BackgroundModeData(
121 Profile* profile,
122 CommandIdExtensionVector* command_id_extension_vector);
123 ~BackgroundModeData() override;
125 // The cached list of BackgroundApplications.
126 scoped_ptr<BackgroundApplicationListModel> applications_;
128 // Overrides from StatusIconMenuModel::Delegate implementation.
129 void ExecuteCommand(int command_id, int event_flags) override;
131 // Returns a browser window, or creates one if none are open. Used by
132 // operations (like displaying the preferences dialog) that require a
133 // Browser window.
134 Browser* GetBrowserWindow();
136 // Returns the number of background apps for this profile.
137 int GetBackgroundAppCount() const;
139 // Builds the profile specific parts of the menu. The menu passed in may
140 // be a submenu in the case of multi-profiles or the main menu in the case
141 // of the single profile case. If containing_menu is valid, we will add
142 // menu as a submenu to it.
143 void BuildProfileMenu(StatusIconMenuModel* menu,
144 StatusIconMenuModel* containing_menu);
146 // Set the name associated with this background mode data for displaying in
147 // the status tray.
148 void SetName(const base::string16& new_profile_name);
150 // The name associated with this background mode data. This should match
151 // the name in the ProfileInfoCache for this profile.
152 base::string16 name();
154 // Used for sorting BackgroundModeData*s.
155 static bool BackgroundModeDataCompare(const BackgroundModeData* bmd1,
156 const BackgroundModeData* bmd2);
158 // Returns the set of new background apps (apps that have been loaded since
159 // the last call to GetNewBackgroundApps()).
160 std::set<const extensions::Extension*> GetNewBackgroundApps();
162 private:
163 // Name associated with this profile which is used to label its submenu.
164 base::string16 name_;
166 // The profile associated with this background app data.
167 Profile* profile_;
169 // Weak ref vector owned by BackgroundModeManager where the
170 // indices correspond to Command IDs and values correspond to
171 // extension indices. A value of -1 indicates no extension is associated
172 // with the index.
173 CommandIdExtensionVector* command_id_extension_vector_;
175 // The list of notified extensions for this profile. We track this to ensure
176 // that we never notify the user about the same extension twice in a single
177 // browsing session - this is done because the extension subsystem is not
178 // good about tracking changes to the background permission around
179 // extension reloads, and will sometimes report spurious permission changes.
180 std::set<extensions::ExtensionId> current_extensions_;
183 // Ideally we would want our BackgroundModeData to be scoped_ptrs,
184 // but since maps copy their entries, we can't used scoped_ptrs.
185 // Similarly, we can't just have a map of BackgroundModeData objects,
186 // since BackgroundModeData contains a scoped_ptr which once again
187 // can't be copied. So rather than using BackgroundModeData* which
188 // we'd have to remember to delete, we use the ref-counted linked_ptr
189 // which is similar to a shared_ptr.
190 typedef linked_ptr<BackgroundModeData> BackgroundModeInfo;
192 typedef std::map<Profile*, BackgroundModeInfo> BackgroundModeInfoMap;
194 // content::NotificationObserver implementation.
195 void Observe(int type,
196 const content::NotificationSource& source,
197 const content::NotificationDetails& details) override;
199 // Called when ExtensionSystem is ready.
200 void OnExtensionsReady();
202 // Called when the kBackgroundModeEnabled preference changes.
203 void OnBackgroundModeEnabledPrefChanged();
205 // BackgroundApplicationListModel::Observer implementation.
206 void OnApplicationDataChanged(const extensions::Extension* extension,
207 Profile* profile) override;
208 void OnApplicationListChanged(Profile* profile) override;
210 // Overrides from ProfileInfoCacheObserver
211 void OnProfileAdded(const base::FilePath& profile_path) override;
212 void OnProfileWillBeRemoved(const base::FilePath& profile_path) override;
213 void OnProfileNameChanged(const base::FilePath& profile_path,
214 const base::string16& old_profile_name) override;
216 // Overrides from StatusIconMenuModel::Delegate implementation.
217 void ExecuteCommand(int command_id, int event_flags) override;
219 // chrome::BrowserListObserver implementation.
220 void OnBrowserAdded(Browser* browser) override;
222 // Invoked when an extension is installed so we can ensure that
223 // launch-on-startup is enabled if appropriate. |extension| can be NULL when
224 // called from unit tests.
225 void OnBackgroundAppInstalled(
226 const extensions::Extension* extension);
228 // Walk the list of profiles and see if an extension or app is being
229 // currently upgraded or reloaded by any profile. If so, update the
230 // output variables appropriately.
231 void CheckReloadStatus(
232 const extensions::Extension* extension,
233 bool* is_being_reloaded);
235 // Called to make sure that our launch-on-startup mode is properly set.
236 // (virtual so it can be mocked in tests).
237 virtual void EnableLaunchOnStartup(bool should_launch);
239 // Invoked when a background app is installed so we can display a
240 // platform-specific notification to the user.
241 virtual void DisplayAppInstalledNotification(
242 const extensions::Extension* extension);
244 // Invoked to put Chrome in KeepAlive mode - chrome runs in the background
245 // and has a status bar icon.
246 void StartBackgroundMode();
248 // Invoked to take Chrome out of KeepAlive mode - chrome stops running in
249 // the background and removes its status bar icon.
250 void EndBackgroundMode();
252 // Enables keep alive and the status tray icon if and only if background mode
253 // is active and not suspended.
254 virtual void UpdateKeepAliveAndTrayIcon();
256 // If --no-startup-window is passed, BackgroundModeManager will manually keep
257 // chrome running while waiting for apps to load. This is called when we no
258 // longer need to do this (either because the user has chosen to exit chrome
259 // manually, or all apps have been loaded).
260 void DecrementKeepAliveCountForStartup();
262 // Return an appropriate name for a Preferences menu entry. Preferences is
263 // sometimes called Options or Settings.
264 base::string16 GetPreferencesMenuLabel();
266 // Create a status tray icon to allow the user to shutdown Chrome when running
267 // in background mode. Virtual to enable testing.
268 virtual void CreateStatusTrayIcon();
270 // Removes the status tray icon because we are exiting background mode.
271 // Virtual to enable testing.
272 virtual void RemoveStatusTrayIcon();
274 // Create a context menu, or replace/update an existing context menu, for the
275 // status tray icon which, among other things, allows the user to shutdown
276 // Chrome when running in background mode. All profiles are listed under
277 // the one context menu.
278 virtual void UpdateStatusTrayIconContextMenu();
280 // Returns the BackgroundModeData associated with this profile. If it does
281 // not exist, returns NULL.
282 BackgroundModeData* GetBackgroundModeData(Profile* const profile) const;
284 // Returns the iterator associated with a particular profile name.
285 // This should not be used to iterate over the background mode data. It is
286 // used to efficiently delete an item from the background mode data map.
287 BackgroundModeInfoMap::iterator GetBackgroundModeIterator(
288 const base::string16& profile_name);
290 // Returns true if the "Let chrome run in the background" pref is checked.
291 // (virtual to allow overriding in tests).
292 virtual bool IsBackgroundModePrefEnabled() const;
294 // Turns off background mode if it's currently enabled.
295 void DisableBackgroundMode();
297 // Turns on background mode if it's currently disabled.
298 void EnableBackgroundMode();
300 // Returns the number of background apps in the system (virtual to allow
301 // overriding in unit tests).
302 virtual int GetBackgroundAppCount() const;
304 // Returns the number of background apps for a profile.
305 virtual int GetBackgroundAppCountForProfile(Profile* const profile) const;
307 // Returns true if we should be in background mode.
308 bool ShouldBeInBackgroundMode() const;
310 // Finds the BackgroundModeData associated with the last active profile,
311 // if the profile isn't locked. Returns NULL otherwise.
312 BackgroundModeData* GetBackgroundModeDataForLastProfile() const;
314 // Reference to the profile info cache. It is used to update the background
315 // app status of profiles when they open/close background apps.
316 ProfileInfoCache* profile_cache_;
318 // Registrars for managing our change observers.
319 content::NotificationRegistrar registrar_;
320 PrefChangeRegistrar pref_registrar_;
322 // The profile-keyed data for this background mode manager. Keyed on profile.
323 BackgroundModeInfoMap background_mode_data_;
325 // Contains the dynamic Command IDs for the entire background menu.
326 CommandIdExtensionVector command_id_extension_vector_;
328 // Maintains submenu lifetime for the multiple profile context menu.
329 ScopedVector<StatusIconMenuModel> submenus;
331 // Reference to our status tray. If null, the platform doesn't support status
332 // icons.
333 StatusTray* status_tray_;
335 // Reference to our status icon (if any) - owned by the StatusTray.
336 StatusIcon* status_icon_;
338 // Reference to our status icon's context menu (if any) - owned by the
339 // status_icon_.
340 StatusIconMenuModel* context_menu_;
342 // Set to true when we are running in background mode. Allows us to track our
343 // current background state so we can take the appropriate action when the
344 // user disables/enables background mode via preferences.
345 bool in_background_mode_;
347 // Set when we are keeping chrome running during the startup process - this
348 // is required when running with the --no-startup-window flag, as otherwise
349 // chrome would immediately exit due to having no open windows.
350 bool keep_alive_for_startup_;
352 // Set to true when Chrome is running with the --keep-alive-for-test flag
353 // (used for testing background mode without having to install a background
354 // app).
355 bool keep_alive_for_test_;
357 // Set to true when background mode is suspended.
358 bool background_mode_suspended_;
360 // Set to true when background mode is keeping Chrome alive.
361 bool keeping_alive_;
363 base::WeakPtrFactory<BackgroundModeManager> weak_factory_;
365 DISALLOW_COPY_AND_ASSIGN(BackgroundModeManager);
368 #endif // CHROME_BROWSER_BACKGROUND_BACKGROUND_MODE_MANAGER_H_