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
content / renderer / service_worker / service_worker_context_client.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_RENDERER_SERVICE_WORKER_SERVICE_WORKER_CONTEXT_CLIENT_H_
#define CONTENT_RENDERER_SERVICE_WORKER_SERVICE_WORKER_CONTEXT_CLIENT_H_
#include <stddef.h>
#include <stdint.h>
#include <map>
#include <memory>
#include <string>
#include "base/containers/id_map.h"
#include "base/functional/callback.h"
#include "base/gtest_prod_util.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/scoped_refptr.h"
#include "base/time/time.h"
#include "ipc/ipc_listener.h"
#include "mojo/public/cpp/bindings/pending_associated_remote.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/receiver.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "mojo/public/cpp/bindings/shared_associated_remote.h"
#include "services/service_manager/public/cpp/binder_registry.h"
#include "services/service_manager/public/mojom/interface_provider.mojom.h"
#include "third_party/blink/public/common/service_worker/service_worker_status_code.h"
#include "third_party/blink/public/common/storage_key/storage_key.h"
#include "third_party/blink/public/common/tokens/tokens.h"
#include "third_party/blink/public/mojom/background_fetch/background_fetch.mojom-forward.h"
#include "third_party/blink/public/mojom/payments/payment_app.mojom-forward.h"
#include "third_party/blink/public/mojom/service_worker/controller_service_worker.mojom-forward.h"
#include "third_party/blink/public/mojom/service_worker/embedded_worker.mojom.h"
#include "third_party/blink/public/mojom/service_worker/service_worker.mojom-forward.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_client.mojom-forward.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_event_status.mojom-forward.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_provider.mojom-forward.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_registration.mojom-forward.h"
#include "third_party/blink/public/mojom/worker/subresource_loader_updater.mojom-forward.h"
#include "third_party/blink/public/mojom/worker/worker_content_settings_proxy.mojom-forward.h"
#include "third_party/blink/public/mojom/worker/worker_content_settings_proxy.mojom.h"
#include "third_party/blink/public/platform/modules/service_worker/web_service_worker_error.h"
#include "third_party/blink/public/web/modules/service_worker/web_service_worker_context_client.h"
#include "third_party/blink/public/web/modules/service_worker/web_service_worker_context_proxy.h"
#include "third_party/blink/public/web/web_embedded_worker.h"
#include "v8/include/v8-forward.h"
namespace base {
class SequencedTaskRunner;
class SingleThreadTaskRunner;
}
namespace blink {
class ChildURLLoaderFactoryBundle;
class WebServiceWorkerContextProxy;
class WebURLResponse;
struct WebServiceWorkerInstalledScriptsManagerParams;
}
namespace content {
class BlinkInterfaceRegistryImpl;
class EmbeddedWorkerInstanceClientImpl;
// ServiceWorkerContextClient is a "client" of a service worker execution
// context. It enables communication between the embedder and Blink's
// ServiceWorkerGlobalScope. It is created when the service worker begins
// starting up, and destroyed when the service worker stops. It is owned by
// WebEmbeddedWorkerImpl (which is owned by EmbeddedWorkerInstanceClientImpl).
//
// This class is created and destroyed on the "initiator" thread. The initiator
// thread is the thread that constructs this class. Currently it's the main
// thread but could be the IO thread in the future. https://crbug.com/692909
//
// Unless otherwise noted (here or in base class documentation), all methods
// are called on the worker thread.
class ServiceWorkerContextClient
: public blink::WebServiceWorkerContextClient,
public service_manager::mojom::InterfaceProvider {
public:
// Called on the initiator thread.
// - |is_starting_installed_worker| is true if the script is already installed
// and will be streamed from the browser process.
// - |owner| must outlive this new instance.
// - |start_timing| should be initially populated with
// |start_worker_received_time|. This instance will fill in the rest during
// startup.
// - |subresource_loader_updater| is a mojo receiver that will be bound to
// ServiceWorkerFetchContextImpl. This interface is used to update
// subresource loader factories.
// - |script_url_to_skip_throttling| is the URL of the service worker script
// that already started being loaded by the browser process due to the
// update check, or the empty URL if there is no such script. See also
// comments in EmbeddedWorkerStartParams::script_url_to_skip_throttling.
ServiceWorkerContextClient(
int64_t service_worker_version_id,
const GURL& service_worker_scope,
const GURL& script_url,
bool is_starting_installed_worker,
const blink::RendererPreferences& renderer_preferences,
mojo::PendingReceiver<blink::mojom::ServiceWorker>
service_worker_receiver,
mojo::PendingReceiver<blink::mojom::ControllerServiceWorker>
controller_receiver,
mojo::PendingAssociatedRemote<blink::mojom::EmbeddedWorkerInstanceHost>
instance_host,
mojo::PendingReceiver<service_manager::mojom::InterfaceProvider>
interface_provider,
blink::mojom::ServiceWorkerProviderInfoForStartWorkerPtr provider_info,
EmbeddedWorkerInstanceClientImpl* owner,
blink::mojom::EmbeddedWorkerStartTimingPtr start_timing,
mojo::PendingReceiver<blink::mojom::RendererPreferenceWatcher>
preference_watcher_receiver,
std::unique_ptr<blink::PendingURLLoaderFactoryBundle> subresource_loaders,
mojo::PendingReceiver<blink::mojom::SubresourceLoaderUpdater>
subresource_loader_updater,
const GURL& script_url_to_skip_throttling,
scoped_refptr<base::SingleThreadTaskRunner> initiator_thread_task_runner,
int32_t service_worker_route_id,
const std::vector<std::string>& cors_exempt_header_list,
const blink::StorageKey& storage_key,
const blink::ServiceWorkerToken& service_worker_token);
ServiceWorkerContextClient(const ServiceWorkerContextClient&) = delete;
ServiceWorkerContextClient& operator=(const ServiceWorkerContextClient&) =
delete;
// Called on the initiator thread.
~ServiceWorkerContextClient() override;
// Called on the initiator thread.
void StartWorkerContextOnInitiatorThread(
std::unique_ptr<blink::WebEmbeddedWorker> worker,
std::unique_ptr<blink::WebEmbeddedWorkerStartData> start_data,
std::unique_ptr<blink::WebServiceWorkerInstalledScriptsManagerParams>,
mojo::PendingRemote<blink::mojom::WorkerContentSettingsProxy>
content_settings,
mojo::PendingRemote<blink::mojom::CacheStorage> cache_storage,
mojo::PendingRemote<blink::mojom::BrowserInterfaceBroker>
browser_interface_broker);
// Called on the initiator thread.
blink::WebEmbeddedWorker& worker();
// service_manager::mojom::InterfaceProvider:
void GetInterface(const std::string& interface_name,
mojo::ScopedMessagePipeHandle interface_pipe) override;
// WebServiceWorkerContextClient overrides.
void WorkerReadyForInspectionOnInitiatorThread(
blink::CrossVariantMojoRemote<blink::mojom::DevToolsAgentInterfaceBase>
devtools_agent_remote,
blink::CrossVariantMojoReceiver<
blink::mojom::DevToolsAgentHostInterfaceBase>
devtools_agent_host_receiver) override;
void FailedToFetchClassicScript() override;
void FailedToFetchModuleScript() override;
void WorkerScriptLoadedOnWorkerThread() override;
void WorkerContextStarted(
blink::WebServiceWorkerContextProxy* proxy,
scoped_refptr<base::SequencedTaskRunner> worker_task_runner) override;
void WillEvaluateScript(v8::Local<v8::Context> v8_context) override;
void DidEvaluateScript(bool success) override;
void WillInitializeWorkerContext() override;
void WillDestroyWorkerContext(v8::Local<v8::Context> context) override;
void WorkerContextDestroyed() override;
void CountFeature(blink::mojom::WebFeature feature) override;
void ReportException(const blink::WebString& error_message,
int line_number,
int column_number,
const blink::WebString& source_url) override;
void ReportConsoleMessage(blink::mojom::ConsoleMessageSource source,
blink::mojom::ConsoleMessageLevel level,
const blink::WebString& message,
int line_number,
const blink::WebString& source_url) override;
void SetupNavigationPreload(int fetch_event_id,
const blink::WebURL& url,
blink::CrossVariantMojoReceiver<
network::mojom::URLLoaderClientInterfaceBase>
preload_url_loader_client_receiver) override;
void RequestTermination(RequestTerminationCallback callback) override;
bool ShouldNotifyServiceWorkerOnWebSocketActivity(
v8::Local<v8::Context> context) override;
scoped_refptr<blink::WebServiceWorkerFetchContext>
CreateWorkerFetchContextOnInitiatorThread() override;
void OnNavigationPreloadResponse(
int fetch_event_id,
std::unique_ptr<blink::WebURLResponse> response,
mojo::ScopedDataPipeConsumerHandle data_pipe) override;
void OnNavigationPreloadComplete(int fetch_event_id,
base::TimeTicks completion_time,
int64_t encoded_data_length,
int64_t encoded_body_length,
int64_t decoded_body_length) override;
void OnNavigationPreloadError(
int fetch_event_id,
std::unique_ptr<blink::WebServiceWorkerError> error) override;
private:
struct WorkerContextData;
friend class ControllerServiceWorkerImpl;
friend class ServiceWorkerContextClientTest;
FRIEND_TEST_ALL_PREFIXES(
ServiceWorkerContextClientTest,
DispatchOrQueueFetchEvent_RequestedTerminationAndDie);
FRIEND_TEST_ALL_PREFIXES(
ServiceWorkerContextClientTest,
DispatchOrQueueFetchEvent_RequestedTerminationAndWakeUp);
FRIEND_TEST_ALL_PREFIXES(ServiceWorkerContextClientTest,
DispatchOrQueueFetchEvent_NotRequestedTermination);
FRIEND_TEST_ALL_PREFIXES(ServiceWorkerContextClientTest, TaskInServiceWorker);
void SendWorkerStarted(blink::mojom::ServiceWorkerStartStatus status);
// Stops the worker context. Called on the initiator thread.
void StopWorkerOnInitiatorThread();
base::WeakPtr<ServiceWorkerContextClient> GetWeakPtr();
const int64_t service_worker_version_id_;
const GURL service_worker_scope_;
const GURL script_url_;
// True if this service worker was already installed at worker
// startup time.
const bool is_starting_installed_worker_;
// See comments in EmbeddedWorkerStartParams::script_url_to_skip_throttling.
const GURL script_url_to_skip_throttling_;
blink::RendererPreferences renderer_preferences_;
// Passed on creation of ServiceWorkerFetchContext.
mojo::PendingReceiver<blink::mojom::RendererPreferenceWatcher>
preference_watcher_receiver_;
scoped_refptr<base::SingleThreadTaskRunner> initiator_thread_task_runner_;
scoped_refptr<base::SequencedTaskRunner> worker_task_runner_;
// Not owned; |this| is destroyed when |proxy_| becomes invalid.
raw_ptr<blink::WebServiceWorkerContextProxy> proxy_;
// These Mojo objects are bound on the worker thread.
mojo::PendingReceiver<blink::mojom::ServiceWorker>
pending_service_worker_receiver_;
mojo::PendingReceiver<blink::mojom::ControllerServiceWorker>
controller_receiver_;
mojo::PendingReceiver<service_manager::mojom::InterfaceProvider>
pending_interface_provider_receiver_;
mojo::PendingReceiver<blink::mojom::SubresourceLoaderUpdater>
pending_subresource_loader_updater_;
// Holds renderer interfaces exposed to the browser.
service_manager::BinderRegistry registry_;
std::unique_ptr<BlinkInterfaceRegistryImpl> blink_interface_registry_;
// Receiver for the InterfaceProvider interface which is used by the browser
// to request interfaces that are exposed by the renderer. Bound and destroyed
// on the worker task runner.
mojo::Receiver<service_manager::mojom::InterfaceProvider>
interface_provider_receiver_{this};
// This is bound on the initiator thread.
mojo::SharedAssociatedRemote<blink::mojom::EmbeddedWorkerInstanceHost>
instance_host_;
// This holds blink.mojom.ServiceWorkerContainer(Host) connections to the
// browser-side ServiceWorkerHost to keep it alive there.
// Note: |service_worker_provider_info_->script_loader_factory_remote| is
// moved to WebServiceWorkerNetworkProviderImpl when
// CreateServiceWorkerNetworkProvider is called.
blink::mojom::ServiceWorkerProviderInfoForStartWorkerPtr
service_worker_provider_info_;
// Must be accessed on the initiator thread only.
raw_ptr<EmbeddedWorkerInstanceClientImpl> owner_;
// Initialized on the worker thread in WorkerContextStarted and
// destructed on the worker thread in WillDestroyWorkerContext.
//
// WARNING: This can be cleared at nearly any time, since WillDestroyContext
// is called by Blink when it decides to terminate the worker thread. This
// includes during event dispatch if a JavaScript debugger breakpoint pauses
// execution (see issue 934622). It should be safe to assume |context_| is
// valid at the start of a task that was posted to |worker_task_runner_|, as
// that is from WorkerThread::GetTaskRunner() which safely drops the task on
// worker termination.
std::unique_ptr<WorkerContextData> context_;
// Accessed on the worker thread. Passed to the browser process after worker
// startup completes.
blink::mojom::EmbeddedWorkerStartTimingPtr start_timing_;
// A URLLoaderFactory instance used for subresource loading.
scoped_refptr<blink::ChildURLLoaderFactoryBundle> loader_factories_;
// Out-of-process NetworkService:
// Detects disconnection from the network service.
mojo::Remote<network::mojom::URLLoaderFactory>
network_service_disconnect_handler_holder_;
std::unique_ptr<blink::WebEmbeddedWorker> worker_;
int32_t service_worker_route_id_;
std::vector<std::string> cors_exempt_header_list_;
base::TimeTicks top_level_script_loading_start_time_ = base::TimeTicks::Now();
blink::StorageKey storage_key_;
blink::ServiceWorkerToken service_worker_token_;
};
} // namespace content
#endif // CONTENT_RENDERER_SERVICE_WORKER_SERVICE_WORKER_CONTEXT_CLIENT_H_