Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / background / background_mode_manager.h
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.
4
5 #ifndef CHROME_BROWSER_BACKGROUND_BACKGROUND_MODE_MANAGER_H_
6 #define CHROME_BROWSER_BACKGROUND_BACKGROUND_MODE_MANAGER_H_
7
8 #include <map>
9
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"
22
23 class Browser;
24 class PrefRegistrySimple;
25 class Profile;
26 class ProfileInfoCache;
27 class StatusIcon;
28 class StatusTray;
29
30 namespace base {
31 class CommandLine;
32 }
33
34 typedef std::vector<int> CommandIdExtensionVector;
35
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.
39 //
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.
44 //
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
49 // background.
50 class BackgroundModeManager
51     : public content::NotificationObserver,
52       public chrome::BrowserListObserver,
53       public BackgroundApplicationListModel::Observer,
54       public ProfileInfoCacheObserver,
55       public StatusIconMenuModel::Delegate {
56  public:
57   BackgroundModeManager(base::CommandLine* command_line,
58                         ProfileInfoCache* profile_cache);
59   ~BackgroundModeManager() override;
60
61   static void RegisterPrefs(PrefRegistrySimple* registry);
62
63   virtual void RegisterProfile(Profile* profile);
64
65   static void LaunchBackgroundApplication(Profile* profile,
66       const extensions::Extension* extension);
67
68   // Returns true if background mode is active.
69   virtual bool IsBackgroundModeActive();
70
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();
75
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();
79
80   // For testing purposes.
81   int NumberOfBackgroundModeData();
82
83  private:
84   friend class AppBackgroundPageApiTest;
85   friend class BackgroundModeManagerTest;
86   friend class BackgroundModeManagerWithExtensionsTest;
87   friend class TestBackgroundModeManager;
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,
101                            MultiProfile);
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,
113                            BalloonDisplay);
114   FRIEND_TEST_ALL_PREFIXES(BackgroundAppBrowserTest,
115                            ReloadBackgroundApp);
116
117   class BackgroundModeData : public StatusIconMenuModel::Delegate {
118    public:
119     explicit BackgroundModeData(
120         Profile* profile,
121         CommandIdExtensionVector* command_id_extension_vector);
122     ~BackgroundModeData() override;
123
124     // The cached list of BackgroundApplications.
125     scoped_ptr<BackgroundApplicationListModel> applications_;
126
127     // Overrides from StatusIconMenuModel::Delegate implementation.
128     void ExecuteCommand(int command_id, int event_flags) override;
129
130     // Returns a browser window, or creates one if none are open. Used by
131     // operations (like displaying the preferences dialog) that require a
132     // Browser window.
133     Browser* GetBrowserWindow();
134
135     // Returns the number of background apps for this profile.
136     int GetBackgroundAppCount() const;
137
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);
144
145     // Set the name associated with this background mode data for displaying in
146     // the status tray.
147     void SetName(const base::string16& new_profile_name);
148
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();
152
153     // Used for sorting BackgroundModeData*s.
154     static bool BackgroundModeDataCompare(const BackgroundModeData* bmd1,
155                                           const BackgroundModeData* bmd2);
156
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();
160
161    private:
162     // Name associated with this profile which is used to label its submenu.
163     base::string16 name_;
164
165     // The profile associated with this background app data.
166     Profile* profile_;
167
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
171     // with the index.
172     CommandIdExtensionVector* command_id_extension_vector_;
173
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_;
180   };
181
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;
190
191   typedef std::map<Profile*, BackgroundModeInfo> BackgroundModeInfoMap;
192
193   // content::NotificationObserver implementation.
194   void Observe(int type,
195                const content::NotificationSource& source,
196                const content::NotificationDetails& details) override;
197
198   // Called when the kBackgroundModeEnabled preference changes.
199   void OnBackgroundModeEnabledPrefChanged();
200
201   // BackgroundApplicationListModel::Observer implementation.
202   void OnApplicationDataChanged(const extensions::Extension* extension,
203                                 Profile* profile) override;
204   void OnApplicationListChanged(Profile* profile) override;
205
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;
211
212   // Overrides from StatusIconMenuModel::Delegate implementation.
213   void ExecuteCommand(int command_id, int event_flags) override;
214
215   // chrome::BrowserListObserver implementation.
216   void OnBrowserAdded(Browser* browser) override;
217
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);
223
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);
230
231   // Called to make sure that our launch-on-startup mode is properly set.
232   // (virtual so we can override for tests).
233   virtual void EnableLaunchOnStartup(bool should_launch);
234
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);
239
240   // Invoked to put Chrome in KeepAlive mode - chrome runs in the background
241   // and has a status bar icon.
242   void StartBackgroundMode();
243
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();
247
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();
251
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();
257
258   // Return an appropriate name for a Preferences menu entry.  Preferences is
259   // sometimes called Options or Settings.
260   base::string16 GetPreferencesMenuLabel();
261
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();
265
266   // Removes the status tray icon because we are exiting background mode.
267   // Virtual to enable testing.
268   virtual void RemoveStatusTrayIcon();
269
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();
275
276   // Returns the BackgroundModeData associated with this profile. If it does
277   // not exist, returns NULL.
278   BackgroundModeManager::BackgroundModeData* GetBackgroundModeData(
279       Profile* const profile) const;
280
281   // Returns the iterator associated with a particular profile name.
282   // This should not be used to iterate over the background mode data. It is
283   // used to efficiently delete an item from the background mode data map.
284   BackgroundModeInfoMap::iterator GetBackgroundModeIterator(
285       const base::string16& profile_name);
286
287   // Returns true if the "Let chrome run in the background" pref is checked.
288   // (virtual to allow overriding in tests).
289   virtual bool IsBackgroundModePrefEnabled() const;
290
291   // Turns off background mode if it's currently enabled.
292   void DisableBackgroundMode();
293
294   // Turns on background mode if it's currently disabled.
295   void EnableBackgroundMode();
296
297   // Returns the number of background apps in the system (virtual to allow
298   // overriding in unit tests).
299   virtual int GetBackgroundAppCount() const;
300
301   // Returns the number of background apps for a profile.
302   virtual int GetBackgroundAppCountForProfile(Profile* const profile) const;
303
304   // Returns true if we should be in background mode.
305   bool ShouldBeInBackgroundMode() const;
306
307   // Finds the BackgroundModeData associated with the last active profile,
308   // if the profile isn't locked. Returns NULL otherwise.
309   BackgroundModeManager::BackgroundModeData*
310       GetBackgroundModeDataForLastProfile() const;
311
312   // Reference to the profile info cache. It is used to update the background
313   // app status of profiles when they open/close background apps.
314   ProfileInfoCache* profile_cache_;
315
316   // Registrars for managing our change observers.
317   content::NotificationRegistrar registrar_;
318   PrefChangeRegistrar pref_registrar_;
319
320   // The profile-keyed data for this background mode manager. Keyed on profile.
321   BackgroundModeInfoMap background_mode_data_;
322
323   // Contains the dynamic Command IDs for the entire background menu.
324   CommandIdExtensionVector command_id_extension_vector_;
325
326   // Maintains submenu lifetime for the multiple profile context menu.
327   ScopedVector<StatusIconMenuModel> submenus;
328
329   // Reference to our status tray. If null, the platform doesn't support status
330   // icons.
331   StatusTray* status_tray_;
332
333   // Reference to our status icon (if any) - owned by the StatusTray.
334   StatusIcon* status_icon_;
335
336   // Reference to our status icon's context menu (if any) - owned by the
337   // status_icon_.
338   StatusIconMenuModel* context_menu_;
339
340   // Set to true when we are running in background mode. Allows us to track our
341   // current background state so we can take the appropriate action when the
342   // user disables/enables background mode via preferences.
343   bool in_background_mode_;
344
345   // Set when we are keeping chrome running during the startup process - this
346   // is required when running with the --no-startup-window flag, as otherwise
347   // chrome would immediately exit due to having no open windows.
348   bool keep_alive_for_startup_;
349
350   // Set to true when Chrome is running with the --keep-alive-for-test flag
351   // (used for testing background mode without having to install a background
352   // app).
353   bool keep_alive_for_test_;
354
355   // Set to true when background mode is suspended.
356   bool background_mode_suspended_;
357
358   // Set to true when background mode is keeping Chrome alive.
359   bool keeping_alive_;
360
361   DISALLOW_COPY_AND_ASSIGN(BackgroundModeManager);
362 };
363
364 #endif  // CHROME_BROWSER_BACKGROUND_BACKGROUND_MODE_MANAGER_H_