Home | History | Annotate | Download | only in browser
      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 
     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