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

content / browser / service_worker / service_worker_process_manager.h [blame]

// 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::GetID().
    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_