blob: 7eada9bf2d9fd6042a488ee2df7be565c287bcba [file] [log] [blame]
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <map>
#include <memory>
#include <vector>
#include "base/callback.h"
#include "base/gtest_prod_util.h"
#include "base/memory/weak_ptr.h"
#include "base/synchronization/lock.h"
#include "content/browser/service_worker/service_worker_metrics.h"
#include "third_party/blink/public/common/service_worker/service_worker_status_code.h"
class GURL;
namespace content {
class BrowserContext;
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.
class CONTENT_EXPORT ServiceWorkerProcessManager {
// The return value for AllocateWorkerProcess().
struct AllocatedProcessInfo {
// Same as RenderProcessHost::GetID().
int process_id;
ServiceWorkerMetrics::StartSituation start_situation;
// |*this| must be owned by a ServiceWorkerContextWrapper in a
// StoragePartition within |browser_context|.
explicit ServiceWorkerProcessManager(BrowserContext* browser_context);
// Shutdown must be called before the ProcessManager is destroyed.
// Called on the UI thread.
BrowserContext* browser_context();
// Synchronously prevents new processes from being allocated
// and drops references to RenderProcessHosts. Called on the UI thread.
void Shutdown();
// Returns true if Shutdown() has been called. May be called by any thread.
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.
// Called on the UI thread.
blink::ServiceWorkerStatusCode AllocateWorkerProcess(
int embedded_worker_id,
const GURL& script_url,
bool can_use_existing_process,
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().
// Called on the UI thread.
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;
// AsWeakPtr() can be called from any thread, but the WeakPtr must be
// dereferenced on the UI thread only.
base::WeakPtr<ServiceWorkerProcessManager> AsWeakPtr() { return weak_this_; }
void set_storage_partition(StoragePartitionImpl* storage_partition) {
storage_partition_ = storage_partition;
SiteInstance* GetSiteInstanceForWorker(int embedded_worker_id);
friend class ServiceWorkerProcessManagerTest;
// Guarded by |browser_context_lock_|.
// Written only on the UI thread, so the UI thread doesn't need to acquire the
// lock when reading. Can be read from other threads with the lock.
BrowserContext* browser_context_;
// Protects |browser_context_|.
base::Lock browser_context_lock_;
// All fields below are only accessed on the UI thread.
// May be null during initialization and in unit tests.
StoragePartitionImpl* 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_;
// Used to double-check that we don't access *this after it's destroyed.
base::WeakPtr<ServiceWorkerProcessManager> weak_this_;
base::WeakPtrFactory<ServiceWorkerProcessManager> weak_this_factory_;
} // 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