Home | History | Annotate | Download | only in service_worker
      1 // Copyright 2014 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 CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_PROCESS_MANAGER_H_
      6 #define CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_PROCESS_MANAGER_H_
      7 
      8 #include <map>
      9 #include <vector>
     10 
     11 #include "base/callback.h"
     12 #include "base/gtest_prod_util.h"
     13 #include "base/memory/scoped_ptr.h"
     14 #include "base/memory/weak_ptr.h"
     15 #include "content/common/service_worker/service_worker_status_code.h"
     16 
     17 class GURL;
     18 
     19 namespace content {
     20 
     21 class BrowserContext;
     22 class SiteInstance;
     23 
     24 // Interacts with the UI thread to keep RenderProcessHosts alive while the
     25 // ServiceWorker system is using them. It also tracks candidate processes
     26 // for each pattern. Each instance of ServiceWorkerProcessManager is destroyed
     27 // on the UI thread shortly after its ServiceWorkerContextWrapper is destroyed.
     28 class CONTENT_EXPORT ServiceWorkerProcessManager {
     29  public:
     30   // |*this| must be owned by a ServiceWorkerContextWrapper in a
     31   // StoragePartition within |browser_context|.
     32   explicit ServiceWorkerProcessManager(BrowserContext* browser_context);
     33 
     34   // Shutdown must be called before the ProcessManager is destroyed.
     35   ~ServiceWorkerProcessManager();
     36 
     37   // Synchronously prevents new processes from being allocated.
     38   // TODO(jyasskin): Drop references to RenderProcessHosts too.
     39   void Shutdown();
     40 
     41   // Returns a reference to a running process suitable for starting the Service
     42   // Worker at |script_url|. Posts |callback| to the IO thread to indicate
     43   // whether creation succeeded and the process ID that has a new reference.
     44   //
     45   // Allocation can fail with SERVICE_WORKER_ERROR_START_WORKER_FAILED if
     46   // RenderProcessHost::Init fails.
     47   void AllocateWorkerProcess(
     48       int embedded_worker_id,
     49       const GURL& pattern,
     50       const GURL& script_url,
     51       const base::Callback<void(ServiceWorkerStatusCode, int process_id)>&
     52           callback);
     53 
     54   // Drops a reference to a process that was running a Service Worker, and its
     55   // SiteInstance.  This must match a call to AllocateWorkerProcess.
     56   void ReleaseWorkerProcess(int embedded_worker_id);
     57 
     58   // Sets a single process ID that will be used for all embedded workers.  This
     59   // bypasses the work of creating a process and managing its worker refcount so
     60   // that unittests can run without a BrowserContext.  The test is in charge of
     61   // making sure this is only called on the same thread as runs the UI message
     62   // loop.
     63   void SetProcessIdForTest(int process_id) {
     64     process_id_for_test_ = process_id;
     65   }
     66 
     67   // Adds/removes process reference for the |pattern|, the process with highest
     68   // references count will be chosen to start a worker.
     69   void AddProcessReferenceToPattern(const GURL& pattern, int process_id);
     70   void RemoveProcessReferenceFromPattern(const GURL& pattern, int process_id);
     71 
     72   // Returns true if the |pattern| has at least one process to run.
     73   bool PatternHasProcessToRun(const GURL& pattern) const;
     74 
     75  private:
     76   FRIEND_TEST_ALL_PREFIXES(ServiceWorkerProcessManagerTest, SortProcess);
     77 
     78   // Information about the process for an EmbeddedWorkerInstance.
     79   struct ProcessInfo {
     80     explicit ProcessInfo(const scoped_refptr<SiteInstance>& site_instance);
     81     explicit ProcessInfo(int process_id);
     82     ~ProcessInfo();
     83 
     84     // Stores the SiteInstance the Worker lives inside. This needs to outlive
     85     // the instance's use of its RPH to uphold assumptions in the
     86     // ContentBrowserClient interface.
     87     scoped_refptr<SiteInstance> site_instance;
     88 
     89     // In case the process was allocated without using a SiteInstance, we need
     90     // to store a process ID to decrement a worker reference on shutdown.
     91     // TODO(jyasskin): Implement http://crbug.com/372045 or thread a frame_id in
     92     // so all processes can be allocated with a SiteInstance.
     93     int process_id;
     94   };
     95 
     96   // Maps the process ID to its reference count.
     97   typedef std::map<int, int> ProcessRefMap;
     98 
     99   // Maps registration scope pattern to ProcessRefMap.
    100   typedef std::map<const GURL, ProcessRefMap> PatternProcessRefMap;
    101 
    102   // Returns a process vector sorted by the reference count for the |pattern|.
    103   std::vector<int> SortProcessesForPattern(const GURL& pattern) const;
    104 
    105   // These fields are only accessed on the UI thread.
    106   BrowserContext* browser_context_;
    107 
    108   // Maps the ID of a running EmbeddedWorkerInstance to information about the
    109   // process it's running inside. Since the Instances themselves live on the IO
    110   // thread, this can be slightly out of date:
    111   //  * instance_info_ is populated while an Instance is STARTING and before
    112   //    it's RUNNING.
    113   //  * instance_info_ is depopulated in a message sent as the Instance becomes
    114   //    STOPPED.
    115   std::map<int, ProcessInfo> instance_info_;
    116 
    117   // In unit tests, this will be returned as the process for all
    118   // EmbeddedWorkerInstances.
    119   int process_id_for_test_;
    120 
    121   // Candidate processes info for each pattern, should be accessed on the
    122   // UI thread.
    123   PatternProcessRefMap pattern_processes_;
    124 
    125   // Used to double-check that we don't access *this after it's destroyed.
    126   base::WeakPtrFactory<ServiceWorkerProcessManager> weak_this_factory_;
    127   const base::WeakPtr<ServiceWorkerProcessManager> weak_this_;
    128 };
    129 
    130 }  // namespace content
    131 
    132 namespace base {
    133 // Specialized to post the deletion to the UI thread.
    134 template <>
    135 struct CONTENT_EXPORT DefaultDeleter<content::ServiceWorkerProcessManager> {
    136   void operator()(content::ServiceWorkerProcessManager* ptr) const;
    137 };
    138 }  // namespace base
    139 
    140 #endif  // CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_PROCESS_MANAGER_H_
    141