Popular sites on the NTP: re-download popular suggestions once per Chrome run
[chromium-blink-merge.git] / chrome / browser / background / background_mode_manager.h
blob8ced6a73742b85153f7d02ce4f2202564bc21cc3
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>
9 #include <set>
10 #include <vector>
12 #include "base/callback_forward.h"
13 #include "base/gtest_prod_util.h"
14 #include "base/memory/scoped_vector.h"
15 #include "base/memory/weak_ptr.h"
16 #include "base/prefs/pref_change_registrar.h"
17 #include "chrome/browser/background/background_application_list_model.h"
18 #include "chrome/browser/profiles/profile_info_cache_observer.h"
19 #include "chrome/browser/status_icons/status_icon.h"
20 #include "chrome/browser/status_icons/status_icon_menu_model.h"
21 #include "chrome/browser/ui/browser_list_observer.h"
22 #include "components/keyed_service/core/keyed_service.h"
23 #include "content/public/browser/notification_observer.h"
24 #include "content/public/browser/notification_registrar.h"
25 #include "extensions/common/extension.h"
27 class BackgroundTrigger;
28 class Browser;
29 class PrefRegistrySimple;
30 class Profile;
31 class ProfileInfoCache;
32 class StatusIcon;
33 class StatusTray;
35 namespace base {
36 class CommandLine;
39 typedef std::vector<base::Closure> CommandIdHandlerVector;
41 // BackgroundModeManager is responsible for switching Chrome into and out of
42 // "background mode" and for providing UI for the user to exit Chrome when there
43 // are no open browser windows.
45 // Chrome enters background mode whenever there is an application with the
46 // "background" permission installed, or a "trigger" that requires Chrome to be
47 // running. This class monitors the set of installed/loaded extensions to ensure
48 // that Chrome enters/exits background mode at the appropriate time.
50 // When Chrome is in background mode, it will continue running even after the
51 // last browser window is closed, until the user explicitly exits the app.
52 // Additionally, when in background mode, Chrome will launch on OS login with
53 // no open windows to allow apps with the "background" permission to run in the
54 // background.
55 class BackgroundModeManager
56 : public content::NotificationObserver,
57 public chrome::BrowserListObserver,
58 public BackgroundApplicationListModel::Observer,
59 public ProfileInfoCacheObserver,
60 public StatusIconMenuModel::Delegate {
61 public:
62 BackgroundModeManager(const base::CommandLine& command_line,
63 ProfileInfoCache* profile_cache);
64 ~BackgroundModeManager() override;
66 static void RegisterPrefs(PrefRegistrySimple* registry);
68 virtual void RegisterProfile(Profile* profile);
70 static void LaunchBackgroundApplication(Profile* profile,
71 const extensions::Extension* extension);
73 // Gets a browser window for |profile| associated with the active desktop.
74 // Opens a new browser window if there isn't one for the active desktop.
75 static Browser* GetBrowserWindowForProfile(Profile* profile);
77 // Returns true if background mode is active.
78 virtual bool IsBackgroundModeActive();
80 // Suspends background mode until either ResumeBackgroundMode is called or
81 // Chrome is restarted. This has the same effect as ending background mode
82 // for the current browser session.
83 virtual void SuspendBackgroundMode();
85 // Resumes background mode. This ends a suspension of background mode, but
86 // will not start it if it is not enabled.
87 virtual void ResumeBackgroundMode();
89 // For testing purposes.
90 int NumberOfBackgroundModeData();
92 // Registers |trigger| as a reason for enabling background mode. Does not
93 // take ownership of |profile| or |trigger|.
94 void RegisterTrigger(Profile* profile,
95 BackgroundTrigger* trigger,
96 bool should_notify_user);
98 // Unregisters |trigger| as a reason for enabling background mode.
99 void UnregisterTrigger(Profile* profile, BackgroundTrigger* trigger);
101 private:
102 friend class AppBackgroundPageApiTest;
103 friend class BackgroundModeManagerTest;
104 friend class BackgroundModeManagerWithExtensionsTest;
105 friend class AdvancedTestBackgroundModeManager;
106 FRIEND_TEST_ALL_PREFIXES(BackgroundModeManagerTest,
107 BackgroundAppLoadUnload);
108 FRIEND_TEST_ALL_PREFIXES(BackgroundModeManagerTest,
109 BackgroundLaunchOnStartup);
110 FRIEND_TEST_ALL_PREFIXES(BackgroundModeManagerTest,
111 BackgroundAppInstallWhileDisabled);
112 FRIEND_TEST_ALL_PREFIXES(BackgroundModeManagerTest,
113 BackgroundAppInstallUninstallWhileDisabled);
114 FRIEND_TEST_ALL_PREFIXES(BackgroundModeManagerTest,
115 BackgroundModeDisabledPreventsKeepAliveOnStartup);
116 FRIEND_TEST_ALL_PREFIXES(BackgroundModeManagerTest,
117 DisableBackgroundModeUnderTestFlag);
118 FRIEND_TEST_ALL_PREFIXES(BackgroundModeManagerTest,
119 EnableAfterBackgroundAppInstall);
120 FRIEND_TEST_ALL_PREFIXES(BackgroundModeManagerTest,
121 MultiProfile);
122 FRIEND_TEST_ALL_PREFIXES(BackgroundModeManagerTest,
123 ProfileInfoCacheStorage);
124 FRIEND_TEST_ALL_PREFIXES(BackgroundModeManagerTest,
125 ProfileInfoCacheObserver);
126 FRIEND_TEST_ALL_PREFIXES(BackgroundModeManagerTest,
127 DeleteBackgroundProfile);
128 FRIEND_TEST_ALL_PREFIXES(BackgroundModeManagerTest,
129 TriggerRegisterUnregister);
130 FRIEND_TEST_ALL_PREFIXES(BackgroundModeManagerTest,
131 TriggerRegisterWhileDisabled);
132 FRIEND_TEST_ALL_PREFIXES(BackgroundModeManagerWithExtensionsTest,
133 BackgroundMenuGeneration);
134 FRIEND_TEST_ALL_PREFIXES(BackgroundModeManagerWithExtensionsTest,
135 BackgroundMenuGenerationMultipleProfile);
136 FRIEND_TEST_ALL_PREFIXES(BackgroundModeManagerWithExtensionsTest,
137 BalloonDisplay);
138 FRIEND_TEST_ALL_PREFIXES(BackgroundAppBrowserTest,
139 ReloadBackgroundApp);
141 // A pending trigger may be registered later. The boolean indicates whether
142 // the user should be notified when it is registered.
143 using PendingTriggerData = std::map<BackgroundTrigger*, bool>;
145 // Manages the background clients and menu items for a single profile. A
146 // client can be a trigger or an extension.
147 class BackgroundModeData : public StatusIconMenuModel::Delegate {
148 public:
149 BackgroundModeData(Profile* profile,
150 CommandIdHandlerVector* command_id_handler_vector);
151 ~BackgroundModeData() override;
153 // The cached list of BackgroundApplications.
154 scoped_ptr<BackgroundApplicationListModel> applications_;
156 // Overrides from StatusIconMenuModel::Delegate implementation.
157 void ExecuteCommand(int command_id, int event_flags) override;
159 // Returns a browser window, or creates one if none are open. Used by
160 // operations (like displaying the preferences dialog) that require a
161 // Browser window.
162 Browser* GetBrowserWindow();
164 // Returns the number of background clients for this profile. A client can
165 // be a trigger or an extension.
166 int GetBackgroundClientCount() const;
168 // Builds the profile specific parts of the menu. The menu passed in may
169 // be a submenu in the case of multi-profiles or the main menu in the case
170 // of the single profile case. If containing_menu is valid, we will add
171 // menu as a submenu to it.
172 void BuildProfileMenu(StatusIconMenuModel* menu,
173 StatusIconMenuModel* containing_menu);
175 // Set the name associated with this background mode data for displaying in
176 // the status tray.
177 void SetName(const base::string16& new_profile_name);
179 // The name associated with this background mode data. This should match
180 // the name in the ProfileInfoCache for this profile.
181 base::string16 name();
183 // Used for sorting BackgroundModeData*s.
184 static bool BackgroundModeDataCompare(const BackgroundModeData* bmd1,
185 const BackgroundModeData* bmd2);
187 // Returns the set of new background apps (apps that have been loaded since
188 // the last call to GetNewBackgroundApps()).
189 std::set<const extensions::Extension*> GetNewBackgroundApps();
191 // Adds a pending |trigger| as a reason to enable background mode. A pending
192 // trigger does not activate background mode, but may be registered later by
193 // RegisterPendingTriggers. Does not take ownership of |trigger|.
194 void AddPendingTrigger(BackgroundTrigger* trigger, bool should_notify_user);
196 // The pending trigger data.
197 PendingTriggerData GetPendingTriggerData() const;
199 // Clears the pending trigger data.
200 void ClearPendingTriggerData();
202 // Counts the number of pending triggers.
203 int GetPendingTriggerCount() const;
205 // Registers |trigger| as a reason to enable background mode. Does not take
206 // ownership of |trigger|. Idempotent.
207 void RegisterTrigger(BackgroundTrigger* trigger);
209 // Removes |trigger| from the registered and pending triggers. Idempotent.
210 void UnregisterTrigger(BackgroundTrigger* trigger);
212 // Checks whether |trigger| is already registered or stored as a pending
213 // trigger.
214 bool HasTrigger(BackgroundTrigger* trigger);
216 private:
217 // Name associated with this profile which is used to label its submenu.
218 base::string16 name_;
220 // The profile associated with this background app data.
221 Profile* profile_;
223 // Weak ref vector owned by BackgroundModeManager where the indices
224 // correspond to Command IDs and values correspond to their handlers.
225 CommandIdHandlerVector* command_id_handler_vector_;
227 // The list of notified extensions for this profile. We track this to ensure
228 // that we never notify the user about the same extension twice in a single
229 // browsing session - this is done because the extension subsystem is not
230 // good about tracking changes to the background permission around
231 // extension reloads, and will sometimes report spurious permission changes.
232 std::set<extensions::ExtensionId> current_extensions_;
234 // This class does not own the triggers. If a trigger does not outlive this
235 // class it must be unregistered before destruction.
236 PendingTriggerData pending_trigger_data_;
238 // This class does not own the triggers. If a trigger does not outlive this
239 // class it must be unregistered before destruction.
240 std::set<BackgroundTrigger*> registered_triggers_;
243 // Ideally we would want our BackgroundModeData to be scoped_ptrs,
244 // but since maps copy their entries, we can't used scoped_ptrs.
245 // Similarly, we can't just have a map of BackgroundModeData objects,
246 // since BackgroundModeData contains a scoped_ptr which once again
247 // can't be copied. So rather than using BackgroundModeData* which
248 // we'd have to remember to delete, we use the ref-counted linked_ptr
249 // which is similar to a shared_ptr.
250 typedef linked_ptr<BackgroundModeData> BackgroundModeInfo;
252 typedef std::map<Profile*, BackgroundModeInfo> BackgroundModeInfoMap;
254 // content::NotificationObserver implementation.
255 void Observe(int type,
256 const content::NotificationSource& source,
257 const content::NotificationDetails& details) override;
259 // Called when ExtensionSystem is ready.
260 void OnExtensionsReady(Profile* profile);
262 // Called when the kBackgroundModeEnabled preference changes.
263 void OnBackgroundModeEnabledPrefChanged();
265 // BackgroundApplicationListModel::Observer implementation.
266 void OnApplicationDataChanged(const extensions::Extension* extension,
267 Profile* profile) override;
268 void OnApplicationListChanged(Profile* profile) override;
270 // Overrides from ProfileInfoCacheObserver
271 void OnProfileAdded(const base::FilePath& profile_path) override;
272 void OnProfileWillBeRemoved(const base::FilePath& profile_path) override;
273 void OnProfileNameChanged(const base::FilePath& profile_path,
274 const base::string16& old_profile_name) override;
276 // Overrides from StatusIconMenuModel::Delegate implementation.
277 void ExecuteCommand(int command_id, int event_flags) override;
279 // chrome::BrowserListObserver implementation.
280 void OnBrowserAdded(Browser* browser) override;
282 // Enables or disables background mode as needed, taking into account the
283 // number of background clients. Updates the background status of |profile| in
284 // the ProfileInfoCache if needed. If |new_client_names| is not empty the
285 // user will be notified about the added client(s).
286 void OnClientsChanged(Profile* profile,
287 const std::vector<base::string16>& new_client_names);
289 // Invoked when a background client is installed so we can ensure that
290 // launch-on-startup is enabled if appropriate.
291 void OnBackgroundClientInstalled(const base::string16& name);
293 // Walk the list of profiles and see if an extension or app is being
294 // currently upgraded or reloaded by any profile. If so, update the
295 // output variables appropriately.
296 void CheckReloadStatus(
297 const extensions::Extension* extension,
298 bool* is_being_reloaded);
300 // Called to make sure that our launch-on-startup mode is properly set.
301 // (virtual so it can be mocked in tests).
302 virtual void EnableLaunchOnStartup(bool should_launch);
304 // Invoked when a client is installed so we can display a platform-specific
305 // notification.
306 virtual void DisplayClientInstalledNotification(const base::string16& name);
308 // Invoked to put Chrome in KeepAlive mode - chrome runs in the background
309 // and has a status bar icon.
310 void StartBackgroundMode();
312 // Invoked to take Chrome out of KeepAlive mode - chrome stops running in
313 // the background and removes its status bar icon.
314 void EndBackgroundMode();
316 // Enables keep alive and the status tray icon if and only if background mode
317 // is active and not suspended.
318 virtual void UpdateKeepAliveAndTrayIcon();
320 // If --no-startup-window is passed, BackgroundModeManager will manually keep
321 // chrome running while waiting for apps to load. This is called when we no
322 // longer need to do this (either because the user has chosen to exit chrome
323 // manually, or all apps have been loaded).
324 void DecrementKeepAliveCountForStartup();
326 // Return an appropriate name for a Preferences menu entry. Preferences is
327 // sometimes called Options or Settings.
328 base::string16 GetPreferencesMenuLabel();
330 // Create a status tray icon to allow the user to shutdown Chrome when running
331 // in background mode. Virtual to enable testing.
332 virtual void CreateStatusTrayIcon();
334 // Removes the status tray icon because we are exiting background mode.
335 // Virtual to enable testing.
336 virtual void RemoveStatusTrayIcon();
338 // Create a context menu, or replace/update an existing context menu, for the
339 // status tray icon which, among other things, allows the user to shutdown
340 // Chrome when running in background mode. All profiles are listed under
341 // the one context menu.
342 virtual void UpdateStatusTrayIconContextMenu();
344 // Returns the BackgroundModeData associated with this profile. If it does
345 // not exist, returns NULL.
346 BackgroundModeData* GetBackgroundModeData(Profile* const profile) const;
348 // Returns the iterator associated with a particular profile name.
349 // This should not be used to iterate over the background mode data. It is
350 // used to efficiently delete an item from the background mode data map.
351 BackgroundModeInfoMap::iterator GetBackgroundModeIterator(
352 const base::string16& profile_name);
354 // Returns true if the "Let chrome run in the background" pref is checked.
355 // (virtual to allow overriding in tests).
356 virtual bool IsBackgroundModePrefEnabled() const;
358 // Turns off background mode if it's currently enabled.
359 void DisableBackgroundMode();
361 // Turns on background mode if it's currently disabled.
362 void EnableBackgroundMode();
364 // Returns the number of background clients in the system, for all profiles.
365 // A client can be a trigger or an extension.
366 // (virtual to allow overriding in unit tests)
367 virtual int GetBackgroundClientCount() const;
369 // Returns the number of background clients for a profile. A client can be a
370 // trigger or an extension.
371 virtual int GetBackgroundClientCountForProfile(Profile* const profile) const;
373 // Returns the number of pending triggers in the system, for all profiles.
374 int GetPendingTriggerCount() const;
376 // Returns true if we should be in background mode.
377 bool ShouldBeInBackgroundMode() const;
379 // Finds the BackgroundModeData associated with the last active profile,
380 // if the profile isn't locked. Returns NULL otherwise.
381 BackgroundModeData* GetBackgroundModeDataForLastProfile() const;
383 // Reference to the profile info cache. It is used to update the background
384 // app status of profiles when they open/close background apps.
385 ProfileInfoCache* profile_cache_;
387 // Registrars for managing our change observers.
388 content::NotificationRegistrar registrar_;
389 PrefChangeRegistrar pref_registrar_;
391 // The profile-keyed data for this background mode manager. Keyed on profile.
392 BackgroundModeInfoMap background_mode_data_;
394 // Indexes the command ids for the entire background menu to their handlers.
395 CommandIdHandlerVector command_id_handler_vector_;
397 // Maintains submenu lifetime for the multiple profile context menu.
398 ScopedVector<StatusIconMenuModel> submenus;
400 // Reference to our status tray. If null, the platform doesn't support status
401 // icons.
402 StatusTray* status_tray_;
404 // Reference to our status icon (if any) - owned by the StatusTray.
405 StatusIcon* status_icon_;
407 // Reference to our status icon's context menu (if any) - owned by the
408 // status_icon_.
409 StatusIconMenuModel* context_menu_;
411 // Set to true when we are running in background mode. Allows us to track our
412 // current background state so we can take the appropriate action when the
413 // user disables/enables background mode via preferences.
414 bool in_background_mode_;
416 // Set when we are keeping chrome running during the startup process - this
417 // is required when running with the --no-startup-window flag, as otherwise
418 // chrome would immediately exit due to having no open windows.
419 bool keep_alive_for_startup_;
421 // Set to true when Chrome is running with the --keep-alive-for-test flag
422 // (used for testing background mode without having to install a background
423 // app).
424 bool keep_alive_for_test_;
426 // Set to true when background mode is suspended.
427 bool background_mode_suspended_;
429 // Set to true when background mode is keeping Chrome alive.
430 bool keeping_alive_;
432 base::WeakPtrFactory<BackgroundModeManager> weak_factory_;
434 DISALLOW_COPY_AND_ASSIGN(BackgroundModeManager);
437 #endif // CHROME_BROWSER_BACKGROUND_BACKGROUND_MODE_MANAGER_H_