1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148
|
// Copyright 2014 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_PROCESS_MANAGER_H_
#define CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_PROCESS_MANAGER_H_
#include <map>
#include <memory>
#include <vector>
#include "base/functional/callback.h"
#include "base/gtest_prod_util.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "content/browser/service_worker/service_worker_metrics.h"
#include "content/common/content_export.h"
#include "services/network/public/mojom/cross_origin_embedder_policy.mojom-forward.h"
#include "third_party/blink/public/common/service_worker/service_worker_status_code.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_ancestor_frame_type.mojom.h"
class GURL;
namespace content {
class SiteInstance;
class StoragePartitionImpl;
// Interacts with the UI thread to keep RenderProcessHosts alive while the
// ServiceWorker system is using them. There is one process manager per
// ServiceWorkerContextWrapper. Each instance of ServiceWorkerProcessManager is
// destroyed on the UI thread shortly after its ServiceWorkerContextWrapper is
// destroyed. All the methods must be called on the UI thread.
class CONTENT_EXPORT ServiceWorkerProcessManager {
public:
// The return value for AllocateWorkerProcess().
struct AllocatedProcessInfo {
// Same as RenderProcessHost::GetDeprecatedID().
int process_id;
// This must be one of NEW_PROCESS, EXISTING_UNREADY_PROCESS or
// EXISTING_READY_PROCESS.
ServiceWorkerMetrics::StartSituation start_situation;
};
// |*this| must be owned by a ServiceWorkerContextWrapper.
ServiceWorkerProcessManager();
// Shutdown must be called before the ProcessManager is destroyed.
~ServiceWorkerProcessManager();
// Synchronously prevents new processes from being allocated
// and drops references to RenderProcessHosts.
void Shutdown();
// Returns true if Shutdown() has been called.
bool IsShutdown();
// Returns a reference to a renderer process suitable for starting the service
// worker described by |emdedded_worker_id|, and |script_url|. The process
// will be kept alive until ReleaseWorkerProcess() is called.
//
// An existing process is used when possible. If |can_use_existing_process| is
// false, or a suitable existing process is not found, a new process may be
// created.
//
// If blink::ServiceWorkerStatusCode::kOk is returned,
// |out_info| contains information about the process.
blink::ServiceWorkerStatusCode AllocateWorkerProcess(
int embedded_worker_id,
const GURL& script_url,
network::mojom::CrossOriginEmbedderPolicyValue coep_value,
bool can_use_existing_process,
blink::mojom::AncestorFrameType ancestor_frame_type,
AllocatedProcessInfo* out_info);
// Drops a reference to a process that was running a Service Worker, and its
// SiteInstance. This must match a call to AllocateWorkerProcess().
void ReleaseWorkerProcess(int embedded_worker_id);
// Sets a single process ID that will be used for all embedded workers. This
// bypasses the work of creating a process and managing its worker refcount so
// that unittests can run without a BrowserContext. The test is in charge of
// making sure this is only called on the same thread as runs the UI message
// loop.
void SetProcessIdForTest(int process_id) {
process_id_for_test_ = process_id;
}
// Sets the process ID to be used for tests that force creating a new process.
void SetNewProcessIdForTest(int process_id) {
new_process_id_for_test_ = process_id;
}
// Forces AllocateWorkerProcess to create a new process instead of reusing an
// existing one.
void ForceNewProcessForTest(bool force_new_process) {
force_new_process_for_test_ = force_new_process;
}
base::WeakPtr<ServiceWorkerProcessManager> GetWeakPtr();
void set_storage_partition(StoragePartitionImpl* storage_partition) {
storage_partition_ = storage_partition;
}
SiteInstance* GetSiteInstanceForWorker(int embedded_worker_id);
private:
friend class ServiceWorkerProcessManagerTest;
//////////////////////////////////////////////////////////////////////////////
// All fields below are only accessed on the UI thread.
// May be null during initialization and in unit tests.
raw_ptr<StoragePartitionImpl, DanglingUntriaged> storage_partition_;
// Maps the ID of a running EmbeddedWorkerInstance to the SiteInstance whose
// renderer process it's running inside. Since the embedded workers themselves
// live on the IO thread, this can be slightly out of date:
// * The map is populated while a worker is STARTING and before it's RUNNING.
// * The map is depopulated in a message sent as the worker becomes STOPPED.
std::map<int, scoped_refptr<SiteInstance>> worker_process_map_;
// In unit tests, this will be returned as the process for all
// EmbeddedWorkerInstances.
int process_id_for_test_;
int new_process_id_for_test_;
bool force_new_process_for_test_;
// If it has been shut down.
bool is_shutdown_ = false;
base::WeakPtrFactory<ServiceWorkerProcessManager> weak_ptr_factory_{this};
};
} // namespace content
namespace std {
// Specialized to post the deletion to the UI thread.
template <>
struct CONTENT_EXPORT default_delete<content::ServiceWorkerProcessManager> {
void operator()(content::ServiceWorkerProcessManager* ptr) const;
};
} // namespace std
#endif // CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_PROCESS_MANAGER_H_
|