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