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_CONTENTS_SERVICE_H_ 6 #define CHROME_BROWSER_BACKGROUND_BACKGROUND_CONTENTS_SERVICE_H_ 7 8 #include <map> 9 #include <string> 10 #include <vector> 11 12 #include "base/gtest_prod_util.h" 13 #include "base/memory/ref_counted.h" 14 #include "base/scoped_observer.h" 15 #include "chrome/browser/tab_contents/background_contents.h" 16 #include "components/keyed_service/core/keyed_service.h" 17 #include "content/public/browser/notification_observer.h" 18 #include "content/public/browser/notification_registrar.h" 19 #include "content/public/common/window_container_type.h" 20 #include "extensions/browser/extension_registry_observer.h" 21 #include "ui/base/window_open_disposition.h" 22 #include "url/gurl.h" 23 24 class PrefService; 25 class Profile; 26 27 namespace base { 28 class CommandLine; 29 class DictionaryValue; 30 } 31 32 namespace content { 33 class SessionStorageNamespace; 34 } 35 36 namespace extensions { 37 class Extension; 38 class ExtensionRegistry; 39 } 40 41 namespace gfx { 42 class Rect; 43 } 44 45 struct BackgroundContentsOpenedDetails; 46 47 // BackgroundContentsService is owned by the profile, and is responsible for 48 // managing the lifetime of BackgroundContents (tracking the set of background 49 // urls, loading them at startup, and keeping the browser process alive as long 50 // as there are BackgroundContents loaded). 51 // 52 // It is also responsible for tracking the association between 53 // BackgroundContents and their parent app, and shutting them down when the 54 // parent app is unloaded. 55 class BackgroundContentsService : private content::NotificationObserver, 56 public extensions::ExtensionRegistryObserver, 57 public BackgroundContents::Delegate, 58 public KeyedService { 59 public: 60 BackgroundContentsService(Profile* profile, 61 const base::CommandLine* command_line); 62 virtual ~BackgroundContentsService(); 63 64 // Allows tests to reduce the time between a force-installed app/extension 65 // crashing and when we reload it. 66 static void SetRestartDelayForForceInstalledAppsAndExtensionsForTesting( 67 int restart_delay_in_ms); 68 69 // Get the crash notification's id for the extension. 70 static std::string GetNotificationIdForExtensionForTesting( 71 const std::string& extension_id); 72 73 // Show a popup notification balloon with a crash message for a given app/ 74 // extension. 75 static void ShowBalloonForTesting(const extensions::Extension* extension, 76 Profile* profile); 77 78 // Returns the BackgroundContents associated with the passed application id, 79 // or NULL if none. 80 BackgroundContents* GetAppBackgroundContents(const base::string16& appid); 81 82 // Returns true if there's a registered BackgroundContents for this app. It 83 // is possible for this routine to return true when GetAppBackgroundContents() 84 // returns false, if the BackgroundContents closed due to the render process 85 // crashing. 86 bool HasRegisteredBackgroundContents(const base::string16& appid); 87 88 // Returns all currently opened BackgroundContents (used by the task manager). 89 std::vector<BackgroundContents*> GetBackgroundContents() const; 90 91 // BackgroundContents::Delegate implementation. 92 virtual void AddWebContents(content::WebContents* new_contents, 93 WindowOpenDisposition disposition, 94 const gfx::Rect& initial_pos, 95 bool user_gesture, 96 bool* was_blocked) OVERRIDE; 97 98 // Gets the parent application id for the passed BackgroundContents. Returns 99 // an empty string if no parent application found (e.g. passed 100 // BackgroundContents has already shut down). 101 const base::string16& GetParentApplicationId(BackgroundContents* contents) const; 102 103 // Creates a new BackgroundContents using the passed |site| and 104 // the |route_id| and begins tracking the object internally so it can be 105 // shutdown if the parent application is uninstalled. 106 // A BACKGROUND_CONTENTS_OPENED notification will be generated with the passed 107 // |frame_name| and |application_id| values, using the passed |profile| as the 108 // Source.. 109 BackgroundContents* CreateBackgroundContents( 110 content::SiteInstance* site, 111 int route_id, 112 Profile* profile, 113 const base::string16& frame_name, 114 const base::string16& application_id, 115 const std::string& partition_id, 116 content::SessionStorageNamespace* session_storage_namespace); 117 118 // Load the manifest-specified background page for the specified hosted app. 119 // If the manifest doesn't specify one, then load the BackgroundContents 120 // registered in the pref. This is typically used to reload a crashed 121 // background page. 122 void LoadBackgroundContentsForExtension(Profile* profile, 123 const std::string& extension_id); 124 125 private: 126 friend class BackgroundContentsServiceTest; 127 friend class MockBackgroundContents; 128 friend class TaskManagerNoShowBrowserTest; 129 130 FRIEND_TEST_ALL_PREFIXES(BackgroundContentsServiceTest, 131 BackgroundContentsCreateDestroy); 132 FRIEND_TEST_ALL_PREFIXES(BackgroundContentsServiceTest, 133 TestApplicationIDLinkage); 134 FRIEND_TEST_ALL_PREFIXES(TaskManagerNoShowBrowserTest, 135 NoticeBGContentsChanges); 136 FRIEND_TEST_ALL_PREFIXES(TaskManagerNoShowBrowserTest, 137 KillBGContents); 138 139 // Registers for various notifications. 140 void StartObserving(Profile* profile); 141 142 // content::NotificationObserver implementation. 143 virtual void Observe(int type, 144 const content::NotificationSource& source, 145 const content::NotificationDetails& details) OVERRIDE; 146 147 // extensions::ExtensionRegistryObserver implementation. 148 virtual void OnExtensionLoaded( 149 content::BrowserContext* browser_context, 150 const extensions::Extension* extension) OVERRIDE; 151 virtual void OnExtensionUnloaded( 152 content::BrowserContext* browser_context, 153 const extensions::Extension* extension, 154 extensions::UnloadedExtensionInfo::Reason reason) OVERRIDE; 155 virtual void OnExtensionUninstalled( 156 content::BrowserContext* browser_context, 157 const extensions::Extension* extension, 158 extensions::UninstallReason reason) OVERRIDE; 159 160 // Restarts a force-installed app/extension after a crash. 161 void RestartForceInstalledExtensionOnCrash( 162 const extensions::Extension* extension, 163 Profile* profile); 164 165 // Loads all registered BackgroundContents at startup. 166 void LoadBackgroundContentsFromPrefs(Profile* profile); 167 168 // Load a BackgroundContent; the settings are read from the provided 169 // dictionary. 170 void LoadBackgroundContentsFromDictionary( 171 Profile* profile, 172 const std::string& extension_id, 173 const base::DictionaryValue* contents); 174 175 // Load the manifest-specified BackgroundContents for all apps for the 176 // profile. 177 void LoadBackgroundContentsFromManifests(Profile* profile); 178 179 // Creates a single BackgroundContents associated with the specified |appid|, 180 // creates an associated RenderView with the name specified by |frame_name|, 181 // and navigates to the passed |url|. 182 void LoadBackgroundContents(Profile* profile, 183 const GURL& url, 184 const base::string16& frame_name, 185 const base::string16& appid); 186 187 // Invoked when a new BackgroundContents is opened. 188 void BackgroundContentsOpened(BackgroundContentsOpenedDetails* details); 189 190 // Invoked when a BackgroundContents object is destroyed. 191 void BackgroundContentsShutdown(BackgroundContents* contents); 192 193 // Registers the |contents->GetURL()| to be run at startup. Only happens for 194 // the first navigation after window.open() (future calls to 195 // RegisterBackgroundContents() for the same BackgroundContents will do 196 // nothing). 197 void RegisterBackgroundContents(BackgroundContents* contents); 198 199 // Stops loading the passed BackgroundContents on startup. 200 void UnregisterBackgroundContents(BackgroundContents* contents); 201 202 // Unregisters and deletes the BackgroundContents associated with the 203 // passed extension. 204 void ShutdownAssociatedBackgroundContents(const base::string16& appid); 205 206 // Returns true if this BackgroundContents is in the contents_list_. 207 bool IsTracked(BackgroundContents* contents) const; 208 209 // Sends out a notification when our association of background contents with 210 // apps may have changed (used by BackgroundApplicationListModel to update the 211 // set of background apps as new background contents are opened/closed). 212 void SendChangeNotification(Profile* profile); 213 214 // Delay (in ms) before restarting a force-installed extension that crashed. 215 static int restart_delay_in_ms_; 216 217 // PrefService used to store list of background pages (or NULL if this is 218 // running under an incognito profile). 219 PrefService* prefs_; 220 content::NotificationRegistrar registrar_; 221 222 // Information we track about each BackgroundContents. 223 struct BackgroundContentsInfo { 224 // The BackgroundContents whose information we are tracking. 225 BackgroundContents* contents; 226 // The name of the top level frame for this BackgroundContents. 227 base::string16 frame_name; 228 }; 229 230 // Map associating currently loaded BackgroundContents with their parent 231 // applications. 232 // Key: application id 233 // Value: BackgroundContentsInfo for the BC associated with that application 234 typedef std::map<base::string16, BackgroundContentsInfo> 235 BackgroundContentsMap; 236 BackgroundContentsMap contents_map_; 237 238 ScopedObserver<extensions::ExtensionRegistry, 239 extensions::ExtensionRegistryObserver> 240 extension_registry_observer_; 241 242 DISALLOW_COPY_AND_ASSIGN(BackgroundContentsService); 243 }; 244 245 #endif // CHROME_BROWSER_BACKGROUND_BACKGROUND_CONTENTS_SERVICE_H_ 246