1 // Copyright 2017 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "content/renderer/loader/web_worker_fetch_context_impl.h"
6
7 #include <utility>
8
9 #include "base/bind.h"
10 #include "base/single_thread_task_runner.h"
11 #include "base/task/post_task.h"
12 #include "base/task/thread_pool.h"
13 #include "base/threading/sequenced_task_runner_handle.h"
14 #include "content/child/child_thread_impl.h"
15 #include "content/child/thread_safe_sender.h"
16 #include "content/common/content_constants_internal.h"
17 #include "content/common/frame_messages.h"
18 #include "content/public/common/content_client.h"
19 #include "content/public/common/origin_util.h"
20 #include "content/public/common/service_names.mojom.h"
21 #include "content/public/renderer/content_renderer_client.h"
22 #include "content/public/renderer/url_loader_throttle_provider.h"
23 #include "content/public/renderer/websocket_handshake_throttle_provider.h"
24 #include "content/renderer/loader/child_url_loader_factory_bundle.h"
25 #include "content/renderer/loader/code_cache_loader_impl.h"
26 #include "content/renderer/loader/frame_request_blocker.h"
27 #include "content/renderer/loader/request_extra_data.h"
28 #include "content/renderer/loader/resource_dispatcher.h"
29 #include "content/renderer/loader/web_url_loader_impl.h"
30 #include "content/renderer/loader/web_url_request_util.h"
31 #include "content/renderer/service_worker/controller_service_worker_connector.h"
32 #include "content/renderer/service_worker/service_worker_provider_context.h"
33 #include "content/renderer/service_worker/service_worker_subresource_loader.h"
34 #include "services/network/public/cpp/wrapper_shared_url_loader_factory.h"
35 #include "third_party/blink/public/common/features.h"
36 #include "third_party/blink/public/mojom/service_worker/service_worker_object.mojom.h"
37 #include "third_party/blink/public/mojom/service_worker/service_worker_provider.mojom.h"
38 #include "third_party/blink/public/platform/web_security_origin.h"
39
40 namespace content {
41
42 WebWorkerFetchContextImpl::RewriteURLFunction g_rewrite_url = nullptr;
43
44 namespace {
45
46 // Runs on a background thread created in ResetServiceWorkerURLLoaderFactory().
CreateServiceWorkerSubresourceLoaderFactory(mojo::PendingRemote<blink::mojom::ServiceWorkerContainerHost> remote_container_host,const std::string & client_id,std::unique_ptr<network::PendingSharedURLLoaderFactory> fallback_factory,mojo::PendingReceiver<network::mojom::URLLoaderFactory> receiver,scoped_refptr<base::SequencedTaskRunner> task_runner,scoped_refptr<base::SequencedTaskRunner> worker_timing_callback_task_runner,base::RepeatingCallback<void (int,mojo::PendingReceiver<blink::mojom::WorkerTimingContainer>)> worker_timing_callback)47 void CreateServiceWorkerSubresourceLoaderFactory(
48 mojo::PendingRemote<blink::mojom::ServiceWorkerContainerHost>
49 remote_container_host,
50 const std::string& client_id,
51 std::unique_ptr<network::PendingSharedURLLoaderFactory> fallback_factory,
52 mojo::PendingReceiver<network::mojom::URLLoaderFactory> receiver,
53 scoped_refptr<base::SequencedTaskRunner> task_runner,
54 scoped_refptr<base::SequencedTaskRunner> worker_timing_callback_task_runner,
55 base::RepeatingCallback<
56 void(int, mojo::PendingReceiver<blink::mojom::WorkerTimingContainer>)>
57 worker_timing_callback) {
58 ServiceWorkerSubresourceLoaderFactory::Create(
59 base::MakeRefCounted<ControllerServiceWorkerConnector>(
60 std::move(remote_container_host),
61 mojo::NullRemote() /* remote_controller */, client_id),
62 network::SharedURLLoaderFactory::Create(std::move(fallback_factory)),
63 std::move(receiver), std::move(task_runner),
64 std::move(worker_timing_callback_task_runner),
65 std::move(worker_timing_callback));
66 }
67
68 } // namespace
69
70 // static
InstallRewriteURLFunction(RewriteURLFunction rewrite_url)71 void WebWorkerFetchContextImpl::InstallRewriteURLFunction(
72 RewriteURLFunction rewrite_url) {
73 CHECK(!g_rewrite_url);
74 g_rewrite_url = rewrite_url;
75 }
76
77 // An implementation of WebURLLoaderFactory that is aware of service workers. In
78 // the usual case, it creates a loader that uses |loader_factory_|. But if the
79 // worker fetch context is controlled by a service worker, it creates a loader
80 // that uses |service_worker_loader_factory_| for requests that should be
81 // intercepted by the service worker.
82 class WebWorkerFetchContextImpl::Factory : public blink::WebURLLoaderFactory {
83 public:
Factory(base::WeakPtr<ResourceDispatcher> resource_dispatcher,scoped_refptr<network::SharedURLLoaderFactory> loader_factory)84 Factory(base::WeakPtr<ResourceDispatcher> resource_dispatcher,
85 scoped_refptr<network::SharedURLLoaderFactory> loader_factory)
86 : resource_dispatcher_(std::move(resource_dispatcher)),
87 loader_factory_(std::move(loader_factory)) {}
88 ~Factory() override = default;
89
CreateURLLoader(const blink::WebURLRequest & request,std::unique_ptr<blink::scheduler::WebResourceLoadingTaskRunnerHandle> task_runner_handle)90 std::unique_ptr<blink::WebURLLoader> CreateURLLoader(
91 const blink::WebURLRequest& request,
92 std::unique_ptr<blink::scheduler::WebResourceLoadingTaskRunnerHandle>
93 task_runner_handle) override {
94 DCHECK(task_runner_handle);
95 DCHECK(resource_dispatcher_);
96
97 // KeepAlive is not yet supported in web workers.
98 mojo::PendingRemote<mojom::KeepAliveHandle> keep_alive_handle =
99 mojo::NullRemote();
100
101 if (CanCreateServiceWorkerURLLoader(request)) {
102 // Create our own URLLoader to route the request to the controller service
103 // worker.
104 return std::make_unique<WebURLLoaderImpl>(
105 resource_dispatcher_.get(), std::move(task_runner_handle),
106 service_worker_loader_factory_, std::move(keep_alive_handle));
107 }
108
109 return std::make_unique<WebURLLoaderImpl>(
110 resource_dispatcher_.get(), std::move(task_runner_handle),
111 loader_factory_, std::move(keep_alive_handle));
112 }
113
SetServiceWorkerURLLoaderFactory(mojo::PendingRemote<network::mojom::URLLoaderFactory> service_worker_loader_factory)114 void SetServiceWorkerURLLoaderFactory(
115 mojo::PendingRemote<network::mojom::URLLoaderFactory>
116 service_worker_loader_factory) {
117 if (!service_worker_loader_factory) {
118 service_worker_loader_factory_ = nullptr;
119 return;
120 }
121 service_worker_loader_factory_ =
122 base::MakeRefCounted<network::WrapperSharedURLLoaderFactory>(
123 std::move(service_worker_loader_factory));
124 }
125
GetWeakPtr()126 base::WeakPtr<Factory> GetWeakPtr() { return weak_ptr_factory_.GetWeakPtr(); }
127
128 private:
CanCreateServiceWorkerURLLoader(const blink::WebURLRequest & request)129 bool CanCreateServiceWorkerURLLoader(const blink::WebURLRequest& request) {
130 // TODO(horo): Unify this code path with
131 // ServiceWorkerNetworkProviderForFrame::CreateURLLoader that is used
132 // for document cases.
133
134 // We need the service worker loader factory populated in order to create
135 // our own URLLoader for subresource loading via a service worker.
136 if (!service_worker_loader_factory_)
137 return false;
138
139 // If the URL is not http(s) or otherwise whitelisted, do not intercept the
140 // request. Schemes like 'blob' and 'file' are not eligible to be
141 // intercepted by service workers.
142 // TODO(falken): Let ServiceWorkerSubresourceLoaderFactory handle the
143 // request and move this check there (i.e., for such URLs, it should use
144 // its fallback factory).
145 if (!GURL(request.Url()).SchemeIsHTTPOrHTTPS() &&
146 !OriginCanAccessServiceWorkers(request.Url())) {
147 return false;
148 }
149
150 // If GetSkipServiceWorker() returns true, no need to intercept the request.
151 if (request.GetSkipServiceWorker())
152 return false;
153
154 return true;
155 }
156
157 base::WeakPtr<ResourceDispatcher> resource_dispatcher_;
158 scoped_refptr<network::SharedURLLoaderFactory> loader_factory_;
159 scoped_refptr<network::SharedURLLoaderFactory> service_worker_loader_factory_;
160 base::WeakPtrFactory<Factory> weak_ptr_factory_{this};
161 DISALLOW_COPY_AND_ASSIGN(Factory);
162 };
163
Create(ServiceWorkerProviderContext * provider_context,blink::mojom::RendererPreferences renderer_preferences,mojo::PendingReceiver<blink::mojom::RendererPreferenceWatcher> watcher_receiver,std::unique_ptr<network::PendingSharedURLLoaderFactory> pending_loader_factory,std::unique_ptr<network::PendingSharedURLLoaderFactory> pending_fallback_factory,mojo::PendingReceiver<blink::mojom::SubresourceLoaderUpdater> pending_subresource_loader_updater)164 scoped_refptr<WebWorkerFetchContextImpl> WebWorkerFetchContextImpl::Create(
165 ServiceWorkerProviderContext* provider_context,
166 blink::mojom::RendererPreferences renderer_preferences,
167 mojo::PendingReceiver<blink::mojom::RendererPreferenceWatcher>
168 watcher_receiver,
169 std::unique_ptr<network::PendingSharedURLLoaderFactory>
170 pending_loader_factory,
171 std::unique_ptr<network::PendingSharedURLLoaderFactory>
172 pending_fallback_factory,
173 mojo::PendingReceiver<blink::mojom::SubresourceLoaderUpdater>
174 pending_subresource_loader_updater) {
175 mojo::PendingReceiver<blink::mojom::ServiceWorkerWorkerClient>
176 service_worker_client_receiver;
177 mojo::PendingRemote<blink::mojom::ServiceWorkerWorkerClientRegistry>
178 service_worker_worker_client_registry;
179 mojo::PendingRemote<blink::mojom::ServiceWorkerContainerHost>
180 service_worker_container_host;
181
182 // Some sandboxed iframes are not allowed to use service worker so don't have
183 // a real service worker provider, so the provider context is null.
184 if (provider_context) {
185 provider_context->CloneWorkerClientRegistry(
186 service_worker_worker_client_registry.InitWithNewPipeAndPassReceiver());
187
188 mojo::PendingRemote<blink::mojom::ServiceWorkerWorkerClient> worker_client;
189 service_worker_client_receiver =
190 worker_client.InitWithNewPipeAndPassReceiver();
191 provider_context->RegisterWorkerClient(std::move(worker_client));
192
193 service_worker_container_host =
194 provider_context->CloneRemoteContainerHost();
195 }
196
197 scoped_refptr<WebWorkerFetchContextImpl> worker_fetch_context =
198 base::AdoptRef(new WebWorkerFetchContextImpl(
199 std::move(renderer_preferences), std::move(watcher_receiver),
200 std::move(service_worker_client_receiver),
201 std::move(service_worker_worker_client_registry),
202 std::move(service_worker_container_host),
203 std::move(pending_loader_factory),
204 std::move(pending_fallback_factory),
205 std::move(pending_subresource_loader_updater),
206 GetContentClient()->renderer()->CreateURLLoaderThrottleProvider(
207 URLLoaderThrottleProviderType::kWorker),
208 GetContentClient()
209 ->renderer()
210 ->CreateWebSocketHandshakeThrottleProvider(),
211 ChildThreadImpl::current()->thread_safe_sender(),
212 ChildThreadImpl::current()->child_process_host()));
213 if (provider_context) {
214 worker_fetch_context->set_controller_service_worker_mode(
215 provider_context->GetControllerServiceWorkerMode());
216 worker_fetch_context->set_client_id(provider_context->client_id());
217 } else {
218 worker_fetch_context->set_controller_service_worker_mode(
219 blink::mojom::ControllerServiceWorkerMode::kNoController);
220 }
221 return worker_fetch_context;
222 }
223
WebWorkerFetchContextImpl(blink::mojom::RendererPreferences renderer_preferences,mojo::PendingReceiver<blink::mojom::RendererPreferenceWatcher> preference_watcher_receiver,mojo::PendingReceiver<blink::mojom::ServiceWorkerWorkerClient> service_worker_client_receiver,mojo::PendingRemote<blink::mojom::ServiceWorkerWorkerClientRegistry> pending_service_worker_worker_client_registry,mojo::PendingRemote<blink::mojom::ServiceWorkerContainerHost> service_worker_container_host,std::unique_ptr<network::PendingSharedURLLoaderFactory> pending_loader_factory,std::unique_ptr<network::PendingSharedURLLoaderFactory> pending_fallback_factory,mojo::PendingReceiver<blink::mojom::SubresourceLoaderUpdater> pending_subresource_loader_updater,std::unique_ptr<URLLoaderThrottleProvider> throttle_provider,std::unique_ptr<WebSocketHandshakeThrottleProvider> websocket_handshake_throttle_provider,ThreadSafeSender * thread_safe_sender,mojo::SharedRemote<mojom::ChildProcessHost> process_host)224 WebWorkerFetchContextImpl::WebWorkerFetchContextImpl(
225 blink::mojom::RendererPreferences renderer_preferences,
226 mojo::PendingReceiver<blink::mojom::RendererPreferenceWatcher>
227 preference_watcher_receiver,
228 mojo::PendingReceiver<blink::mojom::ServiceWorkerWorkerClient>
229 service_worker_client_receiver,
230 mojo::PendingRemote<blink::mojom::ServiceWorkerWorkerClientRegistry>
231 pending_service_worker_worker_client_registry,
232 mojo::PendingRemote<blink::mojom::ServiceWorkerContainerHost>
233 service_worker_container_host,
234 std::unique_ptr<network::PendingSharedURLLoaderFactory>
235 pending_loader_factory,
236 std::unique_ptr<network::PendingSharedURLLoaderFactory>
237 pending_fallback_factory,
238 mojo::PendingReceiver<blink::mojom::SubresourceLoaderUpdater>
239 pending_subresource_loader_updater,
240 std::unique_ptr<URLLoaderThrottleProvider> throttle_provider,
241 std::unique_ptr<WebSocketHandshakeThrottleProvider>
242 websocket_handshake_throttle_provider,
243 ThreadSafeSender* thread_safe_sender,
244 mojo::SharedRemote<mojom::ChildProcessHost> process_host)
245 : service_worker_client_receiver_(
246 std::move(service_worker_client_receiver)),
247 pending_service_worker_worker_client_registry_(
248 std::move(pending_service_worker_worker_client_registry)),
249 pending_service_worker_container_host_(
250 std::move(service_worker_container_host)),
251 pending_loader_factory_(std::move(pending_loader_factory)),
252 pending_fallback_factory_(std::move(pending_fallback_factory)),
253 pending_subresource_loader_updater_(
254 std::move(pending_subresource_loader_updater)),
255 thread_safe_sender_(thread_safe_sender),
256 renderer_preferences_(std::move(renderer_preferences)),
257 preference_watcher_pending_receiver_(
258 std::move(preference_watcher_receiver)),
259 throttle_provider_(std::move(throttle_provider)),
260 websocket_handshake_throttle_provider_(
261 std::move(websocket_handshake_throttle_provider)),
262 process_host_(std::move(process_host)) {}
263
~WebWorkerFetchContextImpl()264 WebWorkerFetchContextImpl::~WebWorkerFetchContextImpl() {}
265
SetTerminateSyncLoadEvent(base::WaitableEvent * terminate_sync_load_event)266 void WebWorkerFetchContextImpl::SetTerminateSyncLoadEvent(
267 base::WaitableEvent* terminate_sync_load_event) {
268 DCHECK(!terminate_sync_load_event_);
269 terminate_sync_load_event_ = terminate_sync_load_event;
270 }
271
272 scoped_refptr<WebWorkerFetchContextImpl>
CloneForNestedWorkerDeprecated(scoped_refptr<base::SingleThreadTaskRunner> task_runner)273 WebWorkerFetchContextImpl::CloneForNestedWorkerDeprecated(
274 scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
275 DCHECK(!base::FeatureList::IsEnabled(blink::features::kPlzDedicatedWorker));
276
277 mojo::PendingReceiver<blink::mojom::ServiceWorkerWorkerClient>
278 service_worker_client_receiver;
279 mojo::PendingRemote<blink::mojom::ServiceWorkerWorkerClientRegistry>
280 service_worker_worker_client_registry;
281 if (service_worker_worker_client_registry_) {
282 mojo::PendingRemote<blink::mojom::ServiceWorkerWorkerClient>
283 service_worker_client;
284 service_worker_client_receiver =
285 service_worker_client.InitWithNewPipeAndPassReceiver();
286 service_worker_worker_client_registry_->RegisterWorkerClient(
287 std::move(service_worker_client));
288 service_worker_worker_client_registry_->CloneWorkerClientRegistry(
289 service_worker_worker_client_registry.InitWithNewPipeAndPassReceiver());
290 }
291
292 mojo::PendingRemote<blink::mojom::ServiceWorkerContainerHost>
293 service_worker_container_host;
294 if (service_worker_container_host_) {
295 service_worker_container_host_->CloneContainerHost(
296 service_worker_container_host.InitWithNewPipeAndPassReceiver());
297 }
298
299 // |pending_subresource_loader_updater| is not used for
300 // non-PlzDedicatedWorker.
301 scoped_refptr<WebWorkerFetchContextImpl> new_context =
302 CloneForNestedWorkerInternal(
303 std::move(service_worker_client_receiver),
304 std::move(service_worker_worker_client_registry),
305 std::move(service_worker_container_host), loader_factory_->Clone(),
306 fallback_factory_->Clone(),
307 /*pending_subresource_loader_updater=*/mojo::NullReceiver(),
308 std::move(task_runner));
309 new_context->controller_service_worker_mode_ =
310 controller_service_worker_mode_;
311
312 return new_context;
313 }
314
315 scoped_refptr<WebWorkerFetchContextImpl>
CloneForNestedWorker(ServiceWorkerProviderContext * service_worker_provider_context,std::unique_ptr<network::PendingSharedURLLoaderFactory> pending_loader_factory,std::unique_ptr<network::PendingSharedURLLoaderFactory> pending_fallback_factory,mojo::PendingReceiver<blink::mojom::SubresourceLoaderUpdater> pending_subresource_loader_updater,scoped_refptr<base::SingleThreadTaskRunner> task_runner)316 WebWorkerFetchContextImpl::CloneForNestedWorker(
317 ServiceWorkerProviderContext* service_worker_provider_context,
318 std::unique_ptr<network::PendingSharedURLLoaderFactory>
319 pending_loader_factory,
320 std::unique_ptr<network::PendingSharedURLLoaderFactory>
321 pending_fallback_factory,
322 mojo::PendingReceiver<blink::mojom::SubresourceLoaderUpdater>
323 pending_subresource_loader_updater,
324 scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
325 DCHECK(base::FeatureList::IsEnabled(blink::features::kPlzDedicatedWorker));
326 DCHECK(pending_loader_factory);
327 DCHECK(pending_fallback_factory);
328 DCHECK(task_runner);
329
330 if (!service_worker_provider_context) {
331 return CloneForNestedWorkerInternal(
332 /*service_worker_client_receiver=*/mojo::NullReceiver(),
333 /*service_worker_worker_client_registry=*/mojo::NullRemote(),
334 /*container_host=*/mojo::NullRemote(),
335 std::move(pending_loader_factory), std::move(pending_fallback_factory),
336 std::move(pending_subresource_loader_updater), std::move(task_runner));
337 }
338
339 mojo::PendingRemote<blink::mojom::ServiceWorkerWorkerClientRegistry>
340 service_worker_worker_client_registry;
341 service_worker_provider_context->CloneWorkerClientRegistry(
342 service_worker_worker_client_registry.InitWithNewPipeAndPassReceiver());
343
344 mojo::PendingRemote<blink::mojom::ServiceWorkerWorkerClient> worker_client;
345 mojo::PendingReceiver<blink::mojom::ServiceWorkerWorkerClient>
346 service_worker_client_receiver =
347 worker_client.InitWithNewPipeAndPassReceiver();
348 service_worker_provider_context->RegisterWorkerClient(
349 std::move(worker_client));
350
351 mojo::PendingRemote<blink::mojom::ServiceWorkerContainerHost>
352 service_worker_container_host =
353 service_worker_provider_context->CloneRemoteContainerHost();
354
355 scoped_refptr<WebWorkerFetchContextImpl> new_context =
356 CloneForNestedWorkerInternal(
357 std::move(service_worker_client_receiver),
358 std::move(service_worker_worker_client_registry),
359 std::move(service_worker_container_host),
360 std::move(pending_loader_factory),
361 std::move(pending_fallback_factory),
362 std::move(pending_subresource_loader_updater),
363 std::move(task_runner));
364 new_context->controller_service_worker_mode_ =
365 service_worker_provider_context->GetControllerServiceWorkerMode();
366
367 return new_context;
368 }
369
InitializeOnWorkerThread(blink::AcceptLanguagesWatcher * watcher)370 void WebWorkerFetchContextImpl::InitializeOnWorkerThread(
371 blink::AcceptLanguagesWatcher* watcher) {
372 DCHECK(!resource_dispatcher_);
373 DCHECK(!receiver_.is_bound());
374 DCHECK(!preference_watcher_receiver_.is_bound());
375 resource_dispatcher_ = std::make_unique<ResourceDispatcher>();
376 resource_dispatcher_->set_terminate_sync_load_event(
377 terminate_sync_load_event_);
378
379 loader_factory_ = network::SharedURLLoaderFactory::Create(
380 std::move(pending_loader_factory_));
381 fallback_factory_ = network::SharedURLLoaderFactory::Create(
382 std::move(pending_fallback_factory_));
383 subresource_loader_updater_.Bind(
384 std::move(pending_subresource_loader_updater_));
385
386 if (service_worker_client_receiver_.is_valid())
387 receiver_.Bind(std::move(service_worker_client_receiver_));
388
389 if (pending_service_worker_worker_client_registry_) {
390 service_worker_worker_client_registry_.Bind(
391 std::move(pending_service_worker_worker_client_registry_));
392 }
393
394 if (preference_watcher_pending_receiver_.is_valid()) {
395 preference_watcher_receiver_.Bind(
396 std::move(preference_watcher_pending_receiver_));
397 }
398
399 if (pending_service_worker_container_host_) {
400 service_worker_container_host_.Bind(
401 std::move(pending_service_worker_container_host_));
402 }
403
404 mojo::Remote<blink::mojom::BlobRegistry> blob_registry_remote;
405 process_host_->BindHostReceiver(
406 blob_registry_remote.BindNewPipeAndPassReceiver());
407 blob_registry_ = base::MakeRefCounted<
408 base::RefCountedData<mojo::Remote<blink::mojom::BlobRegistry>>>(
409 std::move(blob_registry_remote));
410
411 accept_languages_watcher_ = watcher;
412
413 DCHECK(loader_factory_);
414 DCHECK(!web_loader_factory_);
415 web_loader_factory_ = std::make_unique<Factory>(
416 resource_dispatcher_->GetWeakPtr(), loader_factory_);
417
418 ResetServiceWorkerURLLoaderFactory();
419 }
420
GetURLLoaderFactory()421 blink::WebURLLoaderFactory* WebWorkerFetchContextImpl::GetURLLoaderFactory() {
422 return web_loader_factory_.get();
423 }
424
425 std::unique_ptr<blink::WebURLLoaderFactory>
WrapURLLoaderFactory(mojo::ScopedMessagePipeHandle url_loader_factory_handle)426 WebWorkerFetchContextImpl::WrapURLLoaderFactory(
427 mojo::ScopedMessagePipeHandle url_loader_factory_handle) {
428 return std::make_unique<WebURLLoaderFactoryImpl>(
429 resource_dispatcher_->GetWeakPtr(),
430 base::MakeRefCounted<network::WrapperSharedURLLoaderFactory>(
431 mojo::PendingRemote<network::mojom::URLLoaderFactory>(
432 std::move(url_loader_factory_handle),
433 network::mojom::URLLoaderFactory::Version_)));
434 }
435
436 std::unique_ptr<blink::CodeCacheLoader>
CreateCodeCacheLoader()437 WebWorkerFetchContextImpl::CreateCodeCacheLoader() {
438 return std::make_unique<CodeCacheLoaderImpl>(terminate_sync_load_event_);
439 }
440
WillSendRequest(blink::WebURLRequest & request)441 void WebWorkerFetchContextImpl::WillSendRequest(blink::WebURLRequest& request) {
442 if (renderer_preferences_.enable_do_not_track) {
443 request.SetHttpHeaderField(blink::WebString::FromUTF8(kDoNotTrackHeader),
444 "1");
445 }
446
447 auto extra_data = base::MakeRefCounted<RequestExtraData>();
448 extra_data->set_render_frame_id(ancestor_frame_id_);
449 extra_data->set_frame_request_blocker(frame_request_blocker_);
450 if (throttle_provider_) {
451 extra_data->set_url_loader_throttles(
452 throttle_provider_->CreateThrottles(ancestor_frame_id_, request));
453 }
454 if (response_override_) {
455 using RequestContextType = blink::mojom::RequestContextType;
456 DCHECK(
457 (base::FeatureList::IsEnabled(blink::features::kPlzDedicatedWorker) &&
458 request.GetRequestContext() == RequestContextType::WORKER) ||
459 request.GetRequestContext() == RequestContextType::SHARED_WORKER)
460 << request.GetRequestContext();
461 extra_data->set_navigation_response_override(std::move(response_override_));
462 }
463 request.SetExtraData(std::move(extra_data));
464
465 if (g_rewrite_url)
466 request.SetUrl(g_rewrite_url(request.Url().GetString().Utf8(), false));
467
468 if (!renderer_preferences_.enable_referrers) {
469 request.SetReferrerString(blink::WebString());
470 request.SetReferrerPolicy(network::mojom::ReferrerPolicy::kNever);
471 }
472 }
473
474 blink::mojom::ControllerServiceWorkerMode
GetControllerServiceWorkerMode() const475 WebWorkerFetchContextImpl::GetControllerServiceWorkerMode() const {
476 return controller_service_worker_mode_;
477 }
478
SetIsOnSubframe(bool is_on_sub_frame)479 void WebWorkerFetchContextImpl::SetIsOnSubframe(bool is_on_sub_frame) {
480 is_on_sub_frame_ = is_on_sub_frame;
481 }
482
IsOnSubframe() const483 bool WebWorkerFetchContextImpl::IsOnSubframe() const {
484 return is_on_sub_frame_;
485 }
486
SiteForCookies() const487 net::SiteForCookies WebWorkerFetchContextImpl::SiteForCookies() const {
488 return site_for_cookies_;
489 }
490
491 base::Optional<blink::WebSecurityOrigin>
TopFrameOrigin() const492 WebWorkerFetchContextImpl::TopFrameOrigin() const {
493 // TODO(jkarlin): set_top_frame_origin is only called for dedicated workers.
494 // Determine the top-frame-origin of a shared worker as well. See
495 // https://crbug.com/918868.
496 return top_frame_origin_;
497 }
498
DidRunContentWithCertificateErrors()499 void WebWorkerFetchContextImpl::DidRunContentWithCertificateErrors() {
500 Send(new FrameHostMsg_DidRunContentWithCertificateErrors(ancestor_frame_id_));
501 }
502
DidDisplayContentWithCertificateErrors()503 void WebWorkerFetchContextImpl::DidDisplayContentWithCertificateErrors() {
504 Send(new FrameHostMsg_DidDisplayContentWithCertificateErrors(
505 ancestor_frame_id_));
506 }
507
DidRunInsecureContent(const blink::WebSecurityOrigin & origin,const blink::WebURL & url)508 void WebWorkerFetchContextImpl::DidRunInsecureContent(
509 const blink::WebSecurityOrigin& origin,
510 const blink::WebURL& url) {
511 Send(new FrameHostMsg_DidRunInsecureContent(
512 ancestor_frame_id_, GURL(origin.ToString().Utf8()), url));
513 }
514
SetSubresourceFilterBuilder(std::unique_ptr<blink::WebDocumentSubresourceFilter::Builder> subresource_filter_builder)515 void WebWorkerFetchContextImpl::SetSubresourceFilterBuilder(
516 std::unique_ptr<blink::WebDocumentSubresourceFilter::Builder>
517 subresource_filter_builder) {
518 subresource_filter_builder_ = std::move(subresource_filter_builder);
519 }
520
521 std::unique_ptr<blink::WebDocumentSubresourceFilter>
TakeSubresourceFilter()522 WebWorkerFetchContextImpl::TakeSubresourceFilter() {
523 if (!subresource_filter_builder_)
524 return nullptr;
525 return std::move(subresource_filter_builder_)->Build();
526 }
527
528 std::unique_ptr<blink::WebSocketHandshakeThrottle>
CreateWebSocketHandshakeThrottle(scoped_refptr<base::SingleThreadTaskRunner> task_runner)529 WebWorkerFetchContextImpl::CreateWebSocketHandshakeThrottle(
530 scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
531 if (!websocket_handshake_throttle_provider_)
532 return nullptr;
533 return websocket_handshake_throttle_provider_->CreateThrottle(
534 ancestor_frame_id_, std::move(task_runner));
535 }
536
537 mojo::ScopedMessagePipeHandle
TakePendingWorkerTimingReceiver(int request_id)538 WebWorkerFetchContextImpl::TakePendingWorkerTimingReceiver(int request_id) {
539 auto iter = worker_timing_container_receivers_.find(request_id);
540 if (iter == worker_timing_container_receivers_.end()) {
541 return {};
542 }
543 auto receiver = std::move(iter->second);
544 worker_timing_container_receivers_.erase(iter);
545 return receiver.PassPipe();
546 }
547
SetIsOfflineMode(bool is_offline_mode)548 void WebWorkerFetchContextImpl::SetIsOfflineMode(bool is_offline_mode) {
549 // Worker doesn't support offline mode. There should be no callers.
550 NOTREACHED();
551 }
552
set_controller_service_worker_mode(blink::mojom::ControllerServiceWorkerMode mode)553 void WebWorkerFetchContextImpl::set_controller_service_worker_mode(
554 blink::mojom::ControllerServiceWorkerMode mode) {
555 controller_service_worker_mode_ = mode;
556 }
557
set_ancestor_frame_id(int id)558 void WebWorkerFetchContextImpl::set_ancestor_frame_id(int id) {
559 ancestor_frame_id_ = id;
560 }
561
set_frame_request_blocker(scoped_refptr<FrameRequestBlocker> frame_request_blocker)562 void WebWorkerFetchContextImpl::set_frame_request_blocker(
563 scoped_refptr<FrameRequestBlocker> frame_request_blocker) {
564 frame_request_blocker_ = frame_request_blocker;
565 }
566
set_site_for_cookies(const net::SiteForCookies & site_for_cookies)567 void WebWorkerFetchContextImpl::set_site_for_cookies(
568 const net::SiteForCookies& site_for_cookies) {
569 site_for_cookies_ = site_for_cookies;
570 }
571
set_top_frame_origin(const blink::WebSecurityOrigin & top_frame_origin)572 void WebWorkerFetchContextImpl::set_top_frame_origin(
573 const blink::WebSecurityOrigin& top_frame_origin) {
574 top_frame_origin_ = top_frame_origin;
575 }
576
set_origin_url(const GURL & origin_url)577 void WebWorkerFetchContextImpl::set_origin_url(const GURL& origin_url) {
578 origin_url_ = origin_url;
579 }
580
set_client_id(const std::string & client_id)581 void WebWorkerFetchContextImpl::set_client_id(const std::string& client_id) {
582 client_id_ = client_id;
583 }
584
SetResponseOverrideForMainScript(std::unique_ptr<NavigationResponseOverrideParameters> response_override)585 void WebWorkerFetchContextImpl::SetResponseOverrideForMainScript(
586 std::unique_ptr<NavigationResponseOverrideParameters> response_override) {
587 DCHECK(!response_override_);
588 response_override_ = std::move(response_override);
589 }
590
OnControllerChanged(blink::mojom::ControllerServiceWorkerMode mode)591 void WebWorkerFetchContextImpl::OnControllerChanged(
592 blink::mojom::ControllerServiceWorkerMode mode) {
593 set_controller_service_worker_mode(mode);
594 ResetServiceWorkerURLLoaderFactory();
595 }
596
597 scoped_refptr<WebWorkerFetchContextImpl>
CloneForNestedWorkerInternal(mojo::PendingReceiver<blink::mojom::ServiceWorkerWorkerClient> service_worker_client_receiver,mojo::PendingRemote<blink::mojom::ServiceWorkerWorkerClientRegistry> service_worker_worker_client_registry,mojo::PendingRemote<blink::mojom::ServiceWorkerContainerHost> service_worker_container_host,std::unique_ptr<network::PendingSharedURLLoaderFactory> pending_loader_factory,std::unique_ptr<network::PendingSharedURLLoaderFactory> pending_fallback_factory,mojo::PendingReceiver<blink::mojom::SubresourceLoaderUpdater> pending_subresource_loader_updater,scoped_refptr<base::SingleThreadTaskRunner> task_runner)598 WebWorkerFetchContextImpl::CloneForNestedWorkerInternal(
599 mojo::PendingReceiver<blink::mojom::ServiceWorkerWorkerClient>
600 service_worker_client_receiver,
601 mojo::PendingRemote<blink::mojom::ServiceWorkerWorkerClientRegistry>
602 service_worker_worker_client_registry,
603 mojo::PendingRemote<blink::mojom::ServiceWorkerContainerHost>
604 service_worker_container_host,
605 std::unique_ptr<network::PendingSharedURLLoaderFactory>
606 pending_loader_factory,
607 std::unique_ptr<network::PendingSharedURLLoaderFactory>
608 pending_fallback_factory,
609 mojo::PendingReceiver<blink::mojom::SubresourceLoaderUpdater>
610 pending_subresource_loader_updater,
611 scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
612 mojo::PendingRemote<blink::mojom::RendererPreferenceWatcher>
613 preference_watcher;
614 auto new_context = base::AdoptRef(new WebWorkerFetchContextImpl(
615 renderer_preferences_,
616 preference_watcher.InitWithNewPipeAndPassReceiver(),
617 std::move(service_worker_client_receiver),
618 std::move(service_worker_worker_client_registry),
619 std::move(service_worker_container_host),
620 std::move(pending_loader_factory), std::move(pending_fallback_factory),
621 std::move(pending_subresource_loader_updater),
622 throttle_provider_ ? throttle_provider_->Clone() : nullptr,
623 websocket_handshake_throttle_provider_
624 ? websocket_handshake_throttle_provider_->Clone(
625 std::move(task_runner))
626 : nullptr,
627 thread_safe_sender_.get(), process_host_));
628 new_context->is_on_sub_frame_ = is_on_sub_frame_;
629 new_context->ancestor_frame_id_ = ancestor_frame_id_;
630 new_context->frame_request_blocker_ = frame_request_blocker_;
631 new_context->site_for_cookies_ = site_for_cookies_;
632 new_context->top_frame_origin_ = top_frame_origin_;
633 child_preference_watchers_.Add(std::move(preference_watcher));
634 return new_context;
635 }
636
Send(IPC::Message * message)637 bool WebWorkerFetchContextImpl::Send(IPC::Message* message) {
638 return thread_safe_sender_->Send(message);
639 }
640
ResetServiceWorkerURLLoaderFactory()641 void WebWorkerFetchContextImpl::ResetServiceWorkerURLLoaderFactory() {
642 if (!web_loader_factory_)
643 return;
644 if (GetControllerServiceWorkerMode() !=
645 blink::mojom::ControllerServiceWorkerMode::kControlled) {
646 web_loader_factory_->SetServiceWorkerURLLoaderFactory(mojo::NullRemote());
647 return;
648 }
649 if (!service_worker_container_host_)
650 return;
651
652 mojo::PendingRemote<network::mojom::URLLoaderFactory>
653 service_worker_url_loader_factory;
654 mojo::PendingRemote<blink::mojom::ServiceWorkerContainerHost>
655 service_worker_container_host;
656 service_worker_container_host_->CloneContainerHost(
657 service_worker_container_host.InitWithNewPipeAndPassReceiver());
658 // To avoid potential dead-lock while synchronous loading, create the
659 // SubresourceLoaderFactory on a background thread.
660 auto task_runner = base::ThreadPool::CreateSequencedTaskRunner(
661 {base::MayBlock(), base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN});
662 task_runner->PostTask(
663 FROM_HERE,
664 base::BindOnce(
665 &CreateServiceWorkerSubresourceLoaderFactory,
666 std::move(service_worker_container_host), client_id_,
667 fallback_factory_->Clone(),
668 service_worker_url_loader_factory.InitWithNewPipeAndPassReceiver(),
669 task_runner, base::SequencedTaskRunnerHandle::Get(),
670 base::BindRepeating(
671 &WebWorkerFetchContextImpl::AddPendingWorkerTimingReceiver,
672 weak_factory_.GetWeakPtr())));
673 web_loader_factory_->SetServiceWorkerURLLoaderFactory(
674 std::move(service_worker_url_loader_factory));
675 }
676
UpdateSubresourceLoaderFactories(std::unique_ptr<blink::PendingURLLoaderFactoryBundle> subresource_loader_factories)677 void WebWorkerFetchContextImpl::UpdateSubresourceLoaderFactories(
678 std::unique_ptr<blink::PendingURLLoaderFactoryBundle>
679 subresource_loader_factories) {
680 auto subresource_loader_factory_bundle =
681 base::MakeRefCounted<ChildURLLoaderFactoryBundle>(
682 std::make_unique<ChildPendingURLLoaderFactoryBundle>(
683 std::move(subresource_loader_factories)));
684 loader_factory_ = network::SharedURLLoaderFactory::Create(
685 subresource_loader_factory_bundle->Clone());
686 fallback_factory_ = network::SharedURLLoaderFactory::Create(
687 subresource_loader_factory_bundle->CloneWithoutAppCacheFactory());
688 web_loader_factory_ = std::make_unique<Factory>(
689 resource_dispatcher_->GetWeakPtr(), loader_factory_);
690 ResetServiceWorkerURLLoaderFactory();
691 }
692
NotifyUpdate(blink::mojom::RendererPreferencesPtr new_prefs)693 void WebWorkerFetchContextImpl::NotifyUpdate(
694 blink::mojom::RendererPreferencesPtr new_prefs) {
695 if (accept_languages_watcher_ &&
696 renderer_preferences_.accept_languages != new_prefs->accept_languages)
697 accept_languages_watcher_->NotifyUpdate();
698 renderer_preferences_ = *new_prefs;
699 for (auto& watcher : child_preference_watchers_)
700 watcher->NotifyUpdate(new_prefs.Clone());
701 }
702
GetAcceptLanguages() const703 blink::WebString WebWorkerFetchContextImpl::GetAcceptLanguages() const {
704 return blink::WebString::FromUTF8(renderer_preferences_.accept_languages);
705 }
706
AddPendingWorkerTimingReceiver(int request_id,mojo::PendingReceiver<blink::mojom::WorkerTimingContainer> receiver)707 void WebWorkerFetchContextImpl::AddPendingWorkerTimingReceiver(
708 int request_id,
709 mojo::PendingReceiver<blink::mojom::WorkerTimingContainer> receiver) {
710 // TODO(https://crbug.com/900700): Handle redirects properly. Currently on
711 // redirect, the receiver is replaced with a new one, discarding the timings
712 // before the redirect.
713 worker_timing_container_receivers_[request_id] = std::move(receiver);
714 }
715
716 } // namespace content
717