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 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378
|
// 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_WORKER_HOST_SHARED_WORKER_HOST_H_
#define CONTENT_BROWSER_WORKER_HOST_SHARED_WORKER_HOST_H_
#include <list>
#include <memory>
#include <set>
#include <string>
#include <vector>
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/scoped_observation.h"
#include "base/supports_user_data.h"
#include "base/unguessable_token.h"
#include "content/browser/browser_interface_broker_impl.h"
#include "content/browser/buckets/bucket_context.h"
#include "content/browser/renderer_host/code_cache_host_impl.h"
#include "content/browser/renderer_host/policy_container_host.h"
#include "content/common/content_export.h"
#include "content/public/browser/global_routing_id.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/render_process_host_observer.h"
#include "content/public/browser/shared_worker_instance.h"
#include "media/mojo/mojom/video_decode_perf_history.mojom.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/receiver.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "mojo/public/cpp/bindings/unique_receiver_set.h"
#include "net/base/network_isolation_key.h"
#include "services/device/public/cpp/compute_pressure/buildflags.h"
#include "services/metrics/public/cpp/ukm_source_id.h"
#include "services/network/public/cpp/cross_origin_embedder_policy.h"
#include "services/network/public/mojom/url_loader_factory.mojom-forward.h"
#include "third_party/blink/public/common/tokens/tokens.h"
#include "third_party/blink/public/mojom/blob/blob_url_store.mojom-forward.h"
#include "third_party/blink/public/mojom/broadcastchannel/broadcast_channel.mojom.h"
#include "third_party/blink/public/mojom/buckets/bucket_manager_host.mojom.h"
#include "third_party/blink/public/mojom/devtools/devtools_agent.mojom.h"
#include "third_party/blink/public/mojom/loader/code_cache.mojom.h"
#include "third_party/blink/public/mojom/loader/fetch_client_settings_object.mojom-forward.h"
#include "third_party/blink/public/mojom/payments/payment_app.mojom-forward.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_provider.mojom.h"
#include "third_party/blink/public/mojom/webtransport/web_transport_connector.mojom.h"
#include "third_party/blink/public/mojom/worker/shared_worker.mojom.h"
#include "third_party/blink/public/mojom/worker/shared_worker_client.mojom.h"
#include "third_party/blink/public/mojom/worker/shared_worker_factory.mojom.h"
#include "third_party/blink/public/mojom/worker/shared_worker_host.mojom.h"
#include "third_party/blink/public/mojom/worker/worker_main_script_load_params.mojom.h"
#if BUILDFLAG(ENABLE_COMPUTE_PRESSURE)
#include "content/browser/compute_pressure/pressure_service_for_shared_worker.h"
#include "third_party/blink/public/mojom/compute_pressure/web_pressure_manager.mojom.h"
#endif // BUILDFLAG(ENABLE_COMPUTE_PRESSURE)
class GURL;
namespace blink {
class MessagePortChannel;
class StorageKey;
} // namespace blink
namespace content {
class ContentBrowserClient;
class CrossOriginEmbedderPolicyReporter;
class DocumentIsolationPolicyReporter;
class ServiceWorkerMainResourceHandle;
class SharedWorkerContentSettingsProxyImpl;
class SharedWorkerServiceImpl;
class SiteInstanceImpl;
struct WorkerScriptFetcherResult;
// SharedWorkerHost is the browser-side host of a single shared worker running
// in the renderer. This class is owned by the SharedWorkerServiceImpl of the
// current BrowserContext.
class CONTENT_EXPORT SharedWorkerHost : public blink::mojom::SharedWorkerHost,
public RenderProcessHostObserver,
public BucketContext,
public base::SupportsUserData {
public:
SharedWorkerHost(
SharedWorkerServiceImpl* service,
const SharedWorkerInstance& instance,
scoped_refptr<SiteInstanceImpl> site_instance,
std::vector<network::mojom::ContentSecurityPolicyPtr>
content_security_policies,
scoped_refptr<PolicyContainerHost> creator_policy_container_host);
SharedWorkerHost(const SharedWorkerHost&) = delete;
SharedWorkerHost& operator=(const SharedWorkerHost&) = delete;
~SharedWorkerHost() override;
// Returns the RenderProcessHost where this shared worker lives.
// SharedWorkerHost can't outlive the RenderProcessHost so this can't be null.
RenderProcessHost* GetProcessHost() const;
// Starts the SharedWorker in the renderer process.
//
// |outside_fetch_client_settings_object| is used for loading the shared
// worker main script by the browser process, sent to the renderer process,
// and then used to load the script.
//
// |client| is used to determine the IP address space of the worker if the
// script is fetched from a URL with a special scheme known only to the
// embedder.
//
// `result` contains the worker main script fetch result.
void Start(mojo::PendingRemote<blink::mojom::SharedWorkerFactory> factory,
blink::mojom::FetchClientSettingsObjectPtr
outside_fetch_client_settings_object,
ContentBrowserClient* client,
WorkerScriptFetcherResult result);
void AllowFileSystem(const GURL& url,
base::OnceCallback<void(bool)> callback);
void AllowIndexedDB(const GURL& url, base::OnceCallback<void(bool)> callback);
void AllowCacheStorage(const GURL& url,
base::OnceCallback<void(bool)> callback);
void AllowWebLocks(const GURL& url, base::OnceCallback<void(bool)> callback);
void CreateWebTransportConnector(
mojo::PendingReceiver<blink::mojom::WebTransportConnector> receiver);
void BindCacheStorage(
mojo::PendingReceiver<blink::mojom::CacheStorage> receiver);
void CreateBroadcastChannelProvider(
mojo::PendingReceiver<blink::mojom::BroadcastChannelProvider> receiver);
void CreateBlobUrlStoreProvider(
mojo::PendingReceiver<blink::mojom::BlobURLStore> receiver);
void CreateBucketManagerHost(
mojo::PendingReceiver<blink::mojom::BucketManagerHost> receiver);
#if BUILDFLAG(ENABLE_COMPUTE_PRESSURE)
void BindPressureService(
mojo::PendingReceiver<blink::mojom::WebPressureManager> receiver);
#endif // BUILDFLAG(ENABLE_COMPUTE_PRESSURE)
// Causes this instance to be deleted, which will terminate the worker. May
// be done based on a UI action.
void Destruct();
void DestructIfNoClients();
void AddClient(mojo::PendingRemote<blink::mojom::SharedWorkerClient> client,
GlobalRenderFrameHostId client_render_frame_host_id,
const blink::MessagePortChannel& port,
ukm::SourceId client_ukm_source_id);
void SetServiceWorkerHandle(
std::unique_ptr<ServiceWorkerMainResourceHandle> service_worker_handle);
// Removes all clients whose RenderFrameHost has been destroyed before the
// shared worker was started.
void PruneNonExistentClients();
// Returns true if this worker is connected to at least one client.
bool HasClients() const;
// Returns the frame ids of this worker's clients.
std::vector<GlobalRenderFrameHostId> GetRenderFrameIDsForWorker();
SiteInstanceImpl* site_instance() { return site_instance_.get(); }
bool started() const { return started_; }
const GURL& final_response_url() const { return final_response_url_; }
const blink::SharedWorkerToken& token() const { return token_; }
const SharedWorkerInstance& instance() const { return instance_; }
const network::CrossOriginEmbedderPolicy& cross_origin_embedder_policy()
const {
return worker_client_security_state_->cross_origin_embedder_policy;
}
const network::mojom::ClientSecurityStatePtr& client_security_state() const {
return worker_client_security_state_;
}
const std::vector<network::mojom::ContentSecurityPolicyPtr>&
content_security_policies() const {
return content_security_policies_;
}
#if BUILDFLAG(ENABLE_COMPUTE_PRESSURE)
PressureServiceForSharedWorker* pressure_service() {
return pressure_service_.get();
}
#endif // BUILDFLAG(ENABLE_COMPUTE_PRESSURE)
// Exposed so that tests can swap the implementation and intercept calls.
mojo::Receiver<blink::mojom::BrowserInterfaceBroker>&
browser_interface_broker_receiver_for_testing() {
return broker_receiver_;
}
ukm::SourceId ukm_source_id() const { return ukm_source_id_; }
const base::UnguessableToken& GetDevToolsToken() const;
// Signals the remote worker to terminate and returns the mojo::Remote
// instance so the caller can be notified when the connection is lost. Should
// be called right before deleting this instance.
mojo::Remote<blink::mojom::SharedWorker> TerminateRemoteWorkerForTesting();
base::WeakPtr<SharedWorkerHost> AsWeakPtr();
net::NetworkIsolationKey GetNetworkIsolationKey() const;
net::NetworkAnonymizationKey GetNetworkAnonymizationKey() const;
const blink::StorageKey& GetStorageKey() const;
const base::UnguessableToken& GetReportingSource() const {
return reporting_source_;
}
void ReportNoBinderForInterface(const std::string& error);
void CreateCodeCacheHost(
mojo::PendingReceiver<blink::mojom::CodeCacheHost> receiver);
// Creates a network factory params for subresource requests from this worker.
network::mojom::URLLoaderFactoryParamsPtr
CreateNetworkFactoryParamsForSubresources();
// BucketContext:
blink::StorageKey GetBucketStorageKey() override;
blink::mojom::PermissionStatus GetPermissionStatus(
blink::PermissionType permission_type) override;
void BindCacheStorageForBucket(
const storage::BucketInfo& bucket,
mojo::PendingReceiver<blink::mojom::CacheStorage> receiver) override;
void GetSandboxedFileSystemForBucket(
const storage::BucketInfo& bucket,
const std::vector<std::string>& directory_path_components,
blink::mojom::BucketHost::GetDirectoryCallback callback) override;
storage::BucketClientInfo GetBucketClientInfo() const override;
private:
friend class SharedWorkerHostTest;
class ScopedDevToolsHandle;
class ScopedProcessHostRef;
// Contains information about a client connecting to this shared worker.
struct ClientInfo {
ClientInfo(mojo::Remote<blink::mojom::SharedWorkerClient> client,
int connection_request_id,
GlobalRenderFrameHostId render_frame_host_id);
~ClientInfo();
mojo::Remote<blink::mojom::SharedWorkerClient> client;
const int connection_request_id;
const GlobalRenderFrameHostId render_frame_host_id;
};
using ClientList = std::list<ClientInfo>;
// Returns true if the COEP policy of the worker and the creator are
// compatible.
bool CheckCrossOriginEmbedderPolicy(
network::CrossOriginEmbedderPolicy creator_cross_origin_embedder_policy,
network::CrossOriginEmbedderPolicy worker_cross_origin_embedder_policy);
// blink::mojom::SharedWorkerHost methods:
void OnConnected(int connection_request_id) override;
void OnContextClosed() override;
void OnReadyForInspection(
mojo::PendingRemote<blink::mojom::DevToolsAgent>,
mojo::PendingReceiver<blink::mojom::DevToolsAgentHost>) override;
void OnScriptLoadFailed(const std::string& error_message) override;
void OnFeatureUsed(blink::mojom::WebFeature feature) override;
// RenderProcessHostObserver methods:
void RenderProcessHostDestroyed(RenderProcessHost* host) override;
void AllowFileSystemResponse(base::OnceCallback<void(bool)> callback,
bool allowed);
void OnClientConnectionLost();
void OnWorkerConnectionLost();
void BindCacheStorageInternal(
mojo::PendingReceiver<blink::mojom::CacheStorage> receiver,
const storage::BucketLocator& bucket_locator);
// Creates a network factory for subresource requests from this worker. The
// network factory is meant to be passed to the renderer.
mojo::PendingRemote<network::mojom::URLLoaderFactory>
CreateNetworkFactoryForSubresources(bool* bypass_redirect_checks);
mojo::Receiver<blink::mojom::SharedWorkerHost> receiver_{this};
// |service_| owns |this|.
const raw_ptr<SharedWorkerServiceImpl> service_;
// An identifier for this worker that is unique across all workers. This is
// generated by this object in the browser process.
const blink::SharedWorkerToken token_;
// This holds information used to match a shared worker connection request to
// this shared worker.
SharedWorkerInstance instance_;
ClientList clients_;
std::vector<network::mojom::ContentSecurityPolicyPtr>
content_security_policies_;
mojo::PendingReceiver<blink::mojom::SharedWorker> worker_receiver_;
mojo::Remote<blink::mojom::SharedWorker> worker_;
// A SiteInstance whose process the shared worker runs in.
const scoped_refptr<SiteInstanceImpl> site_instance_;
// Keep alive the renderer process that will be hosting the shared worker.
std::unique_ptr<ScopedProcessHostRef> scoped_process_host_ref_;
int next_connection_request_id_;
std::unique_ptr<ScopedDevToolsHandle> devtools_handle_;
// This is the set of features that this worker has used.
std::set<blink::mojom::WebFeature> used_features_;
std::unique_ptr<SharedWorkerContentSettingsProxyImpl> content_settings_;
#if BUILDFLAG(ENABLE_COMPUTE_PRESSURE)
std::unique_ptr<PressureServiceForSharedWorker> pressure_service_;
#endif // BUILDFLAG(ENABLE_COMPUTE_PRESSURE)
// This is kept alive during the lifetime of the shared worker, since it's
// associated with Mojo interfaces (ServiceWorkerContainer and
// URLLoaderFactory) that are needed to stay alive while the worker is
// starting or running.
mojo::Remote<blink::mojom::SharedWorkerFactory> factory_;
BrowserInterfaceBrokerImpl<SharedWorkerHost, const url::Origin&> broker_{
this};
mojo::Receiver<blink::mojom::BrowserInterfaceBroker> broker_receiver_{
&broker_};
std::unique_ptr<ServiceWorkerMainResourceHandle> service_worker_handle_;
// CodeCacheHost processes requests to fetch / write generated code for
// JavaScript / WebAssembly resources.
CodeCacheHostImpl::ReceiverSet code_cache_host_receivers_;
// Indicates if Start() was invoked on this instance.
bool started_ = false;
GURL final_response_url_;
const ukm::SourceId ukm_source_id_;
const base::UnguessableToken reporting_source_;
// Set at construction time and should not change afterwards.
const scoped_refptr<PolicyContainerHost> creator_policy_container_host_;
// The worker's own client security state, applied to subresource fetches.
// This is nullptr until it is computed in `DidStartScriptLoad()`.
network::mojom::ClientSecurityStatePtr worker_client_security_state_;
std::unique_ptr<CrossOriginEmbedderPolicyReporter> coep_reporter_;
std::unique_ptr<DocumentIsolationPolicyReporter> dip_reporter_;
base::WeakPtrFactory<SharedWorkerHost> weak_factory_{this};
};
} // namespace content
#endif // CONTENT_BROWSER_WORKER_HOST_SHARED_WORKER_HOST_H_
|