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
content / browser / worker_host / shared_worker_host.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_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 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 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_;
base::WeakPtrFactory<SharedWorkerHost> weak_factory_{this};
};
} // namespace content
#endif // CONTENT_BROWSER_WORKER_HOST_SHARED_WORKER_HOST_H_