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
22class GURL;
23
24namespace content {
25class BrowserContext;
26class DevToolsAgentHost;
27class RenderViewHost;
28class RenderFrameHost;
29class SiteInstance;
30};
31
32namespace extensions {
33
34class Extension;
35class ExtensionHost;
36class ExtensionRegistry;
37class ProcessManagerDelegate;
38class 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.
43class 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
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
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