1 // Copyright 2013 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 EXTENSIONS_BROWSER_PROCESS_MANAGER_H_ 6 #define EXTENSIONS_BROWSER_PROCESS_MANAGER_H_ 7 8 #include <map> 9 #include <set> 10 #include <string> 11 12 #include "base/callback.h" 13 #include "base/compiler_specific.h" 14 #include "base/memory/ref_counted.h" 15 #include "base/memory/weak_ptr.h" 16 #include "base/observer_list.h" 17 #include "base/time/time.h" 18 #include "content/public/browser/notification_observer.h" 19 #include "content/public/browser/notification_registrar.h" 20 #include "extensions/common/view_type.h" 21 22 class GURL; 23 24 namespace content { 25 class BrowserContext; 26 class DevToolsAgentHost; 27 class RenderViewHost; 28 class RenderFrameHost; 29 class SiteInstance; 30 }; 31 32 namespace extensions { 33 34 class Extension; 35 class ExtensionHost; 36 class ExtensionRegistry; 37 class ProcessManagerDelegate; 38 class ProcessManagerObserver; 39 40 // Manages dynamic state of running Chromium extensions. There is one instance 41 // of this class per Profile. OTR Profiles have a separate instance that keeps 42 // track of split-mode extensions only. 43 class ProcessManager : public content::NotificationObserver { 44 public: 45 typedef std::set<extensions::ExtensionHost*> ExtensionHostSet; 46 typedef ExtensionHostSet::const_iterator const_iterator; 47 48 static ProcessManager* Create(content::BrowserContext* context); 49 virtual ~ProcessManager(); 50 background_hosts()51 const ExtensionHostSet& background_hosts() const { 52 return background_hosts_; 53 } 54 55 typedef std::set<content::RenderViewHost*> ViewSet; 56 const ViewSet GetAllViews() const; 57 58 // The typical observer interface. 59 void AddObserver(ProcessManagerObserver* observer); 60 void RemoveObserver(ProcessManagerObserver* observer); 61 62 // Creates a new UI-less extension instance. Like CreateViewHost, but not 63 // displayed anywhere. Returns false if no background host can be created, 64 // for example for hosted apps and extensions that aren't enabled in 65 // Incognito. 66 virtual bool CreateBackgroundHost(const Extension* extension, 67 const GURL& url); 68 69 // Gets the ExtensionHost for the background page for an extension, or NULL if 70 // the extension isn't running or doesn't have a background page. 71 ExtensionHost* GetBackgroundHostForExtension(const std::string& extension_id); 72 73 // Returns the SiteInstance that the given URL belongs to. 74 // TODO(aa): This only returns correct results for extensions and packaged 75 // apps, not hosted apps. 76 virtual content::SiteInstance* GetSiteInstanceForURL(const GURL& url); 77 78 // Unregisters a RenderViewHost as hosting any extension. 79 void UnregisterRenderViewHost(content::RenderViewHost* render_view_host); 80 81 // Returns all RenderViewHosts that are registered for the specified 82 // extension. 83 std::set<content::RenderViewHost*> GetRenderViewHostsForExtension( 84 const std::string& extension_id); 85 86 // Returns the extension associated with the specified RenderViewHost, or 87 // NULL. 88 const Extension* GetExtensionForRenderViewHost( 89 content::RenderViewHost* render_view_host); 90 91 // Returns true if the (lazy) background host for the given extension has 92 // already been sent the unload event and is shutting down. 93 bool IsBackgroundHostClosing(const std::string& extension_id); 94 95 // Getter and setter for the lazy background page's keepalive count. This is 96 // the count of how many outstanding "things" are keeping the page alive. 97 // When this reaches 0, we will begin the process of shutting down the page. 98 // "Things" include pending events, resource loads, and API calls. 99 int GetLazyKeepaliveCount(const Extension* extension); 100 void IncrementLazyKeepaliveCount(const Extension* extension); 101 void DecrementLazyKeepaliveCount(const Extension* extension); 102 103 void IncrementLazyKeepaliveCountForView( 104 content::RenderViewHost* render_view_host); 105 106 // Keeps a background page alive. Unlike IncrementLazyKeepaliveCount, these 107 // impulses will only keep the page alive for a limited amount of time unless 108 // called regularly. 109 void KeepaliveImpulse(const Extension* extension); 110 111 // Triggers a keepalive impulse for a plug-in (e.g NaCl). 112 static void OnKeepaliveFromPlugin(int render_process_id, 113 int render_frame_id, 114 const std::string& extension_id); 115 116 // Handles a response to the ShouldSuspend message, used for lazy background 117 // pages. 118 void OnShouldSuspendAck(const std::string& extension_id, uint64 sequence_id); 119 120 // Same as above, for the Suspend message. 121 void OnSuspendAck(const std::string& extension_id); 122 123 // Tracks network requests for a given RenderFrameHost, used to know 124 // when network activity is idle for lazy background pages. 125 void OnNetworkRequestStarted(content::RenderFrameHost* render_frame_host); 126 void OnNetworkRequestDone(content::RenderFrameHost* render_frame_host); 127 128 // Prevents |extension|'s background page from being closed and sends the 129 // onSuspendCanceled() event to it. 130 void CancelSuspend(const Extension* extension); 131 132 // Creates background hosts if the embedder is ready and they are not already 133 // loaded. 134 void MaybeCreateStartupBackgroundHosts(); 135 136 // Called on shutdown to close our extension hosts. 137 void CloseBackgroundHosts(); 138 139 // Gets the BrowserContext associated with site_instance_ and all other 140 // related SiteInstances. 141 content::BrowserContext* GetBrowserContext() const; 142 143 // Sets callbacks for testing keepalive impulse behavior. 144 typedef base::Callback<void(const std::string& extension_id)> 145 ImpulseCallbackForTesting; 146 void SetKeepaliveImpulseCallbackForTesting( 147 const ImpulseCallbackForTesting& callback); 148 void SetKeepaliveImpulseDecrementCallbackForTesting( 149 const ImpulseCallbackForTesting& callback); 150 151 // Sets the time in milliseconds that an extension event page can 152 // be idle before it is shut down; must be > 0. 153 static void SetEventPageIdleTimeForTesting(unsigned idle_time_msec); 154 155 // Sets the time in milliseconds that an extension event page has 156 // between being notified of its impending unload and that unload 157 // happening. 158 static void SetEventPageSuspendingTimeForTesting( 159 unsigned suspending_time_msec); 160 161 // Creates a non-incognito instance for tests. |registry| allows unit tests 162 // to inject an ExtensionRegistry that is not managed by the usual 163 // BrowserContextKeyedServiceFactory system. 164 static ProcessManager* CreateForTesting(content::BrowserContext* context, 165 ExtensionRegistry* registry); 166 167 // Creates an incognito-context instance for tests. 168 static ProcessManager* CreateIncognitoForTesting( 169 content::BrowserContext* incognito_context, 170 content::BrowserContext* original_context, 171 ProcessManager* original_manager, 172 ExtensionRegistry* registry); 173 startup_background_hosts_created_for_test()174 bool startup_background_hosts_created_for_test() const { 175 return startup_background_hosts_created_; 176 } 177 178 protected: 179 // If |context| is incognito pass the master context as |original_context|. 180 // Otherwise pass the same context for both. Pass the ExtensionRegistry for 181 // |context| as |registry|, or override it for testing. 182 ProcessManager(content::BrowserContext* context, 183 content::BrowserContext* original_context, 184 ExtensionRegistry* registry); 185 186 // content::NotificationObserver: 187 virtual void Observe(int type, 188 const content::NotificationSource& source, 189 const content::NotificationDetails& details) OVERRIDE; 190 191 content::NotificationRegistrar registrar_; 192 193 // The set of ExtensionHosts running viewless background extensions. 194 ExtensionHostSet background_hosts_; 195 196 // A SiteInstance related to the SiteInstance for all extensions in 197 // this profile. We create it in such a way that a new 198 // browsing instance is created. This controls process grouping. 199 scoped_refptr<content::SiteInstance> site_instance_; 200 201 // Not owned. Also used by IncognitoProcessManager. 202 ExtensionRegistry* extension_registry_; 203 204 private: 205 friend class ProcessManagerTest; 206 207 // Extra information we keep for each extension's background page. 208 struct BackgroundPageData; 209 typedef std::string ExtensionId; 210 typedef std::map<ExtensionId, BackgroundPageData> BackgroundPageDataMap; 211 typedef std::map<content::RenderViewHost*, 212 extensions::ViewType> ExtensionRenderViews; 213 214 // Load all background pages once the profile data is ready and the pages 215 // should be loaded. 216 void CreateStartupBackgroundHosts(); 217 218 // Called just after |host| is created so it can be registered in our lists. 219 void OnBackgroundHostCreated(ExtensionHost* host); 220 221 // Close the given |host| iff it's a background page. 222 void CloseBackgroundHost(ExtensionHost* host); 223 224 // Internal implementation of DecrementLazyKeepaliveCount with an 225 // |extension_id| known to have a lazy background page. 226 void DecrementLazyKeepaliveCount(const std::string& extension_id); 227 228 // Checks if keepalive impulses have occured, and adjusts keep alive count. 229 void OnKeepaliveImpulseCheck(); 230 231 // These are called when the extension transitions between idle and active. 232 // They control the process of closing the background page when idle. 233 void OnLazyBackgroundPageIdle(const std::string& extension_id, 234 uint64 sequence_id); 235 void OnLazyBackgroundPageActive(const std::string& extension_id); 236 void CloseLazyBackgroundPageNow(const std::string& extension_id, 237 uint64 sequence_id); 238 239 // Potentially registers a RenderViewHost, if it is associated with an 240 // extension. Does nothing if this is not an extension renderer. 241 // Returns true, if render_view_host was registered (it is associated 242 // with an extension). 243 bool RegisterRenderViewHost(content::RenderViewHost* render_view_host); 244 245 // Unregister RenderViewHosts and clear background page data for an extension 246 // which has been unloaded. 247 void UnregisterExtension(const std::string& extension_id); 248 249 // Clears background page data for this extension. 250 void ClearBackgroundPageData(const std::string& extension_id); 251 252 void OnDevToolsStateChanged(content::DevToolsAgentHost*, bool attached); 253 254 // Contains all active extension-related RenderViewHost instances for all 255 // extensions. We also keep a cache of the host's view type, because that 256 // information is not accessible at registration/deregistration time. 257 ExtensionRenderViews all_extension_views_; 258 259 BackgroundPageDataMap background_page_data_; 260 261 // True if we have created the startup set of background hosts. 262 bool startup_background_hosts_created_; 263 264 base::Callback<void(content::DevToolsAgentHost*, bool)> devtools_callback_; 265 266 ImpulseCallbackForTesting keepalive_impulse_callback_for_testing_; 267 ImpulseCallbackForTesting keepalive_impulse_decrement_callback_for_testing_; 268 269 ObserverList<ProcessManagerObserver> observer_list_; 270 271 // ID Counter used to set ProcessManager::BackgroundPageData close_sequence_id 272 // members. These IDs are tracked per extension in background_page_data_ and 273 // are used to verify that nothing has interrupted the process of closing a 274 // lazy background process. 275 // 276 // Any interruption obtains a new ID by incrementing 277 // last_background_close_sequence_id_ and storing it in background_page_data_ 278 // for a particular extension. Callbacks and round-trip IPC messages store the 279 // value of the extension's close_sequence_id at the beginning of the process. 280 // Thus comparisons can be done to halt when IDs no longer match. 281 // 282 // This counter provides unique IDs even when BackgroundPageData objects are 283 // reset. 284 uint64 last_background_close_sequence_id_; 285 286 // Must be last member, see doc on WeakPtrFactory. 287 base::WeakPtrFactory<ProcessManager> weak_ptr_factory_; 288 289 DISALLOW_COPY_AND_ASSIGN(ProcessManager); 290 }; 291 292 } // namespace extensions 293 294 #endif // EXTENSIONS_BROWSER_PROCESS_MANAGER_H_ 295