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 17class GURL; 18 19namespace content { 20 21class BrowserContext; 22class 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. 28class 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 132namespace base { 133// Specialized to post the deletion to the UI thread. 134template <> 135struct 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