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 #ifndef CONTENT_RENDERER_LOADER_WEB_WORKER_FETCH_CONTEXT_IMPL_H_
6 #define CONTENT_RENDERER_LOADER_WEB_WORKER_FETCH_CONTEXT_IMPL_H_
7 
8 #include <memory>
9 #include <string>
10 
11 #include "base/strings/string_piece.h"
12 #include "base/synchronization/waitable_event.h"
13 #include "content/common/content_export.h"
14 #include "mojo/public/cpp/bindings/pending_receiver.h"
15 #include "mojo/public/cpp/bindings/pending_remote.h"
16 #include "mojo/public/cpp/bindings/receiver.h"
17 #include "mojo/public/cpp/bindings/remote.h"
18 #include "mojo/public/cpp/bindings/remote_set.h"
19 #include "services/network/public/cpp/shared_url_loader_factory.h"
20 #include "services/network/public/mojom/url_loader_factory.mojom-forward.h"
21 #include "third_party/blink/public/common/renderer_preferences/renderer_preferences.h"
22 #include "third_party/blink/public/mojom/loader/resource_load_info_notifier.mojom.h"
23 #include "third_party/blink/public/mojom/renderer_preference_watcher.mojom.h"
24 #include "third_party/blink/public/mojom/service_worker/service_worker_container.mojom.h"
25 #include "third_party/blink/public/mojom/service_worker/service_worker_object.mojom-forward.h"
26 #include "third_party/blink/public/mojom/service_worker/service_worker_provider.mojom.h"
27 #include "third_party/blink/public/mojom/timing/worker_timing_container.mojom-forward.h"
28 #include "third_party/blink/public/mojom/worker/subresource_loader_updater.mojom.h"
29 #include "third_party/blink/public/platform/web_string.h"
30 #include "third_party/blink/public/platform/web_worker_fetch_context.h"
31 #include "url/gurl.h"
32 
33 namespace blink {
34 class ResourceLoadInfoNotifierWrapper;
35 class WeakWrapperResourceLoadInfoNotifier;
36 class WebFrameRequestBlocker;
37 }  // namespace blink
38 
39 namespace content {
40 
41 class ResourceDispatcher;
42 class ServiceWorkerProviderContext;
43 class URLLoaderThrottleProvider;
44 class WebSocketHandshakeThrottleProvider;
45 
46 // This class is used for fetching resource requests from workers (dedicated
47 // worker and shared worker). This class is created on the main thread and
48 // passed to the worker thread. This class is not used for service workers. For
49 // service workers, ServiceWorkerFetchContextImpl class is used instead.
50 class CONTENT_EXPORT WebWorkerFetchContextImpl
51     : public blink::WebWorkerFetchContext,
52       public blink::mojom::SubresourceLoaderUpdater,
53       public blink::mojom::ServiceWorkerWorkerClient,
54       public blink::mojom::RendererPreferenceWatcher {
55  public:
56   // Creates a new fetch context for a worker.
57   //
58   // |provider_context| is used to set up information for using service workers.
59   // It can be null if the worker is not allowed to use service workers due to
60   // security reasons like sandboxed iframes, insecure origins etc.
61   // |pending_loader_factory| is used for regular loading by the worker.
62   //
63   // If the worker is controlled by a service worker, this class makes another
64   // loader factory which sends requests to the service worker, and passes
65   // |pending_fallback_factory| to that factory to use for network fallback.
66   //
67   // |pending_loader_factory| and |pending_fallback_factory| are different
68   // because |pending_loader_factory| can possibly include a default factory
69   // like AppCache, while |pending_fallback_factory| should not have such a
70   // default factory and instead go directly to network for http(s) requests.
71   // |pending_fallback_factory| might not be simply the direct network factory,
72   // because it might additionally support non-NetworkService schemes (e.g.,
73   // chrome-extension://).
74   static scoped_refptr<WebWorkerFetchContextImpl> Create(
75       ServiceWorkerProviderContext* provider_context,
76       const blink::RendererPreferences& renderer_preferences,
77       mojo::PendingReceiver<blink::mojom::RendererPreferenceWatcher>
78           watcher_receiver,
79       std::unique_ptr<network::PendingSharedURLLoaderFactory>
80           pending_loader_factory,
81       std::unique_ptr<network::PendingSharedURLLoaderFactory>
82           pending_fallback_factory,
83       mojo::PendingReceiver<blink::mojom::SubresourceLoaderUpdater>
84           pending_subresource_loader_updater,
85       const std::vector<std::string>& cors_exempt_header_list,
86       mojo::PendingRemote<blink::mojom::ResourceLoadInfoNotifier>
87           pending_resource_load_info_notifier);
88 
89   // Clones this fetch context for a nested worker.
90   // For non-PlzDedicatedWorker. This will be removed once PlzDedicatedWorker is
91   // enabled by default.
92   scoped_refptr<WebWorkerFetchContextImpl> CloneForNestedWorkerDeprecated(
93       scoped_refptr<base::SingleThreadTaskRunner> task_runner);
94   // For PlzDedicatedWorker. The cloned fetch context does not inherit some
95   // fields (e.g., ServiceWorkerProviderContext) from this fetch context, and
96   // instead that takes values passed from the browser process.
97   scoped_refptr<WebWorkerFetchContextImpl> CloneForNestedWorker(
98       ServiceWorkerProviderContext* service_worker_provider_context,
99       std::unique_ptr<network::PendingSharedURLLoaderFactory>
100           pending_loader_factory,
101       std::unique_ptr<network::PendingSharedURLLoaderFactory>
102           pending_fallback_factory,
103       mojo::PendingReceiver<blink::mojom::SubresourceLoaderUpdater>
104           pending_subresource_loader_updater,
105       scoped_refptr<base::SingleThreadTaskRunner> task_runner);
106 
107   // blink::WebWorkerFetchContext implementation:
108   void SetTerminateSyncLoadEvent(base::WaitableEvent*) override;
109   void InitializeOnWorkerThread(blink::AcceptLanguagesWatcher*) override;
110   blink::WebURLLoaderFactory* GetURLLoaderFactory() override;
111   std::unique_ptr<blink::WebURLLoaderFactory> WrapURLLoaderFactory(
112       blink::CrossVariantMojoRemote<
113           network::mojom::URLLoaderFactoryInterfaceBase> url_loader_factory)
114       override;
115   std::unique_ptr<blink::WebCodeCacheLoader> CreateCodeCacheLoader() override;
116   void WillSendRequest(blink::WebURLRequest&) override;
117   blink::mojom::ControllerServiceWorkerMode GetControllerServiceWorkerMode()
118       const override;
119   void SetIsOnSubframe(bool) override;
120   bool IsOnSubframe() const override;
121   net::SiteForCookies SiteForCookies() const override;
122   base::Optional<blink::WebSecurityOrigin> TopFrameOrigin() const override;
123   void SetSubresourceFilterBuilder(
124       std::unique_ptr<blink::WebDocumentSubresourceFilter::Builder>) override;
125   std::unique_ptr<blink::WebDocumentSubresourceFilter> TakeSubresourceFilter()
126       override;
127   std::unique_ptr<blink::WebSocketHandshakeThrottle>
128   CreateWebSocketHandshakeThrottle(
129       scoped_refptr<base::SingleThreadTaskRunner> task_runner) override;
130   blink::CrossVariantMojoReceiver<
131       blink::mojom::WorkerTimingContainerInterfaceBase>
132   TakePendingWorkerTimingReceiver(int request_id) override;
133   void SetIsOfflineMode(bool is_offline_mode) override;
134 
135   // blink::mojom::ServiceWorkerWorkerClient implementation:
136   void OnControllerChanged(blink::mojom::ControllerServiceWorkerMode) override;
137 
138   // Sets the controller service worker mode.
139   // - For dedicated workers (non-PlzDedicatedWorker), they depend on the
140   //   controller of the ancestor frame (directly for non-nested workers, or
141   //   indirectly via its parent worker for nested workers), and inherit its
142   //   controller mode.
143   // - For dedicated workers (PlzDedicatedWorker) and shared workers, the
144   //   controller mode is passed from the browser processw when starting the
145   //   worker.
146   void set_controller_service_worker_mode(
147       blink::mojom::ControllerServiceWorkerMode mode);
148 
149   // Sets properties associated with frames.
150   // - For dedicated workers, the property is copied from the ancestor frame
151   //   (directly for non-nested workers, or indirectly via its parent worker for
152   //   nested workers).
153   // - For shared workers, there is no parent frame, so the default value, or a
154   //   value calculated in some way is set.
155   //
156   // TODO(nhiroki): Add more comments about security/privacy implications to
157   // each property, for example, site_for_cookies and top_frame_origin.
158   void set_ancestor_frame_id(int id);
159   void set_frame_request_blocker(
160       scoped_refptr<blink::WebFrameRequestBlocker> frame_request_blocker);
161   void set_site_for_cookies(const net::SiteForCookies& site_for_cookies);
162   void set_top_frame_origin(const blink::WebSecurityOrigin& top_frame_origin);
163 
164   void set_client_id(const std::string& client_id);
165 
166   using RewriteURLFunction = blink::WebURL (*)(base::StringPiece, bool);
167   static void InstallRewriteURLFunction(RewriteURLFunction rewrite_url);
168 
169   blink::WebString GetAcceptLanguages() const override;
170 
171   // Sets up |receiver| to receive resource performance timings for the given
172   // |request_id|. This receiver will be taken later by
173   // TakePendingWorkerTimingReceiver().
174   void AddPendingWorkerTimingReceiver(
175       int request_id,
176       mojo::PendingReceiver<blink::mojom::WorkerTimingContainer> receiver);
177 
178   std::unique_ptr<blink::ResourceLoadInfoNotifierWrapper>
179   CreateResourceLoadInfoNotifierWrapper() override;
180 
181  private:
182   class Factory;
183   using WorkerTimingContainerReceiverMap =
184       std::map<int /* request_id */,
185                mojo::PendingReceiver<blink::mojom::WorkerTimingContainer>>;
186 
187   // - |service_worker_client_receiver| receives OnControllerChanged()
188   //   notifications.
189   // - |service_worker_worker_client_registry| is used to register new
190   //   ServiceWorkerWorkerClients, which is needed when creating a
191   //   nested worker.
192   //
193   // Regarding the rest of params, see the comments on Create().
194   WebWorkerFetchContextImpl(
195       const blink::RendererPreferences& renderer_preferences,
196       mojo::PendingReceiver<blink::mojom::RendererPreferenceWatcher>
197           watcher_receiver,
198       mojo::PendingReceiver<blink::mojom::ServiceWorkerWorkerClient>
199           service_worker_client_receiver,
200       mojo::PendingRemote<blink::mojom::ServiceWorkerWorkerClientRegistry>
201           service_worker_worker_client_registry,
202       mojo::PendingRemote<blink::mojom::ServiceWorkerContainerHost>
203           service_worker_container_host,
204       std::unique_ptr<network::PendingSharedURLLoaderFactory>
205           pending_loader_factory,
206       std::unique_ptr<network::PendingSharedURLLoaderFactory>
207           pending_fallback_factory,
208       mojo::PendingReceiver<blink::mojom::SubresourceLoaderUpdater>
209           pending_subresource_loader_updater,
210       std::unique_ptr<URLLoaderThrottleProvider> throttle_provider,
211       std::unique_ptr<WebSocketHandshakeThrottleProvider>
212           websocket_handshake_throttle_provider,
213       const std::vector<std::string>& cors_exempt_header_list,
214       mojo::PendingRemote<blink::mojom::ResourceLoadInfoNotifier>
215           pending_resource_load_info_notifier);
216 
217   ~WebWorkerFetchContextImpl() override;
218 
219   scoped_refptr<WebWorkerFetchContextImpl> CloneForNestedWorkerInternal(
220       mojo::PendingReceiver<blink::mojom::ServiceWorkerWorkerClient>
221           service_worker_client_receiver,
222       mojo::PendingRemote<blink::mojom::ServiceWorkerWorkerClientRegistry>
223           service_worker_worker_client_registry,
224       mojo::PendingRemote<blink::mojom::ServiceWorkerContainerHost>
225           service_worker_container_host,
226       std::unique_ptr<network::PendingSharedURLLoaderFactory>
227           pending_loader_factory,
228       std::unique_ptr<network::PendingSharedURLLoaderFactory>
229           pending_fallback_factory,
230       mojo::PendingReceiver<blink::mojom::SubresourceLoaderUpdater>
231           pending_subresource_loader_updater,
232       scoped_refptr<base::SingleThreadTaskRunner> task_runner);
233 
234   // Resets the service worker url loader factory of a URLLoaderFactoryImpl
235   // which was passed to Blink. The url loader factory is connected to the
236   // controller service worker. Sets nullptr if the worker context is not
237   // controlled by a service worker.
238   void ResetServiceWorkerURLLoaderFactory();
239 
240   // Implements blink::mojom::SubresourceLoaderUpdater.
241   void UpdateSubresourceLoaderFactories(
242       std::unique_ptr<blink::PendingURLLoaderFactoryBundle>
243           subresource_loader_factories) override;
244 
245   // Implements blink::mojom::RendererPreferenceWatcher.
246   void NotifyUpdate(const blink::RendererPreferences& new_prefs) override;
247 
248   void ResetWeakWrapperResourceLoadInfoNotifier();
249 
250   // |receiver_| and |service_worker_worker_client_registry_| may be null if
251   // this context can't use service workers. See comments for Create().
252   mojo::Receiver<blink::mojom::ServiceWorkerWorkerClient> receiver_{this};
253   mojo::Remote<blink::mojom::ServiceWorkerWorkerClientRegistry>
254       service_worker_worker_client_registry_;
255 
256   // Bound to |this| on the worker thread.
257   mojo::PendingReceiver<blink::mojom::ServiceWorkerWorkerClient>
258       service_worker_client_receiver_;
259   // Consumed on the worker thread to create
260   // |service_worker_worker_client_registry_|.
261   mojo::PendingRemote<blink::mojom::ServiceWorkerWorkerClientRegistry>
262       pending_service_worker_worker_client_registry_;
263   // Consumed on the worker thread to create |service_worker_container_host_|.
264   mojo::PendingRemote<blink::mojom::ServiceWorkerContainerHost>
265       pending_service_worker_container_host_;
266   // Consumed on the worker thread to create |loader_factory_|.
267   std::unique_ptr<network::PendingSharedURLLoaderFactory>
268       pending_loader_factory_;
269   // Consumed on the worker thread to create |fallback_factory_|.
270   std::unique_ptr<network::PendingSharedURLLoaderFactory>
271       pending_fallback_factory_;
272 
273   blink::mojom::ControllerServiceWorkerMode controller_service_worker_mode_ =
274       blink::mojom::ControllerServiceWorkerMode::kNoController;
275 
276   // Initialized on the worker thread when InitializeOnWorkerThread() is called.
277   // This can be null if the |provider_context| passed to Create() was null or
278   // already being destructed (see
279   // ServiceWorkerProviderContext::OnNetworkProviderDestroyed()).
280   mojo::Remote<blink::mojom::ServiceWorkerContainerHost>
281       service_worker_container_host_;
282 
283   // The Client#id value of the shared worker or dedicated worker (since
284   // dedicated workers are not yet service worker clients, it is the parent
285   // document's id in that case). Passed to ControllerServiceWorkerConnector.
286   std::string client_id_;
287 
288   // Initialized on the worker thread when InitializeOnWorkerThread() is called.
289   std::unique_ptr<ResourceDispatcher> resource_dispatcher_;
290 
291   // Initialized on the worker thread when InitializeOnWorkerThread() is called.
292   // |loader_factory_| is used for regular loading by the worker. In
293   // If the worker is controlled by a service worker, it creates a
294   // ServiceWorkerSubresourceLoaderFactory instead.
295   scoped_refptr<network::SharedURLLoaderFactory> loader_factory_;
296 
297   // Initialized on the worker thread when InitializeOnWorkerThread() is called.
298   // If the worker is controlled by a service worker, it passes this factory to
299   // ServiceWorkerSubresourceLoaderFactory to use for network fallback.
300   scoped_refptr<network::SharedURLLoaderFactory> fallback_factory_;
301 
302   // Initialized on the worker thread when InitializeOnWorkerThread() is called.
303   // Used to reconnect to the Network Service after the Network Service crash.
304   // This is only used for dedicated workers when PlzDedicatedWorker is enabled.
305   // When PlzDedicatedWorker is disabled, the ancestor render frame updates the
306   // loaders via Host/TrackedChildURLLoaderFactoryBundle. For shared workers,
307   // the renderer process detects the crash, and terminates the worker instead
308   // of recovery.
309   mojo::PendingReceiver<blink::mojom::SubresourceLoaderUpdater>
310       pending_subresource_loader_updater_;
311   mojo::Receiver<blink::mojom::SubresourceLoaderUpdater>
312       subresource_loader_updater_{this};
313 
314   std::unique_ptr<blink::WebDocumentSubresourceFilter::Builder>
315       subresource_filter_builder_;
316   // For dedicated workers, this is the ancestor frame (the parent frame for
317   // non-nested workers, the closest ancestor for nested workers). For shared
318   // workers, this is the shadow page.
319   bool is_on_sub_frame_ = false;
320   int ancestor_frame_id_ = MSG_ROUTING_NONE;
321   // Set to non-null if the ancestor frame has an associated RequestBlocker,
322   // which blocks requests from this worker too when the ancestor frame is
323   // blocked.
324   scoped_refptr<blink::WebFrameRequestBlocker> frame_request_blocker_;
325   net::SiteForCookies site_for_cookies_;
326   base::Optional<url::Origin> top_frame_origin_;
327 
328   blink::RendererPreferences renderer_preferences_;
329 
330   // |preference_watcher_receiver_| and |child_preference_watchers_| are for
331   // keeping track of updates in the renderer preferences.
332   mojo::Receiver<blink::mojom::RendererPreferenceWatcher>
333       preference_watcher_receiver_{this};
334   // Kept while staring up the worker thread. Valid until
335   // InitializeOnWorkerThread().
336   mojo::PendingReceiver<blink::mojom::RendererPreferenceWatcher>
337       preference_watcher_pending_receiver_;
338   mojo::RemoteSet<blink::mojom::RendererPreferenceWatcher>
339       child_preference_watchers_;
340 
341   // This is owned by ThreadedMessagingProxyBase on the main thread.
342   base::WaitableEvent* terminate_sync_load_event_ = nullptr;
343 
344   // The blink::WebURLLoaderFactory which was created and passed to
345   // Blink by GetURLLoaderFactory().
346   std::unique_ptr<Factory> web_loader_factory_;
347 
348   std::unique_ptr<URLLoaderThrottleProvider> throttle_provider_;
349   std::unique_ptr<WebSocketHandshakeThrottleProvider>
350       websocket_handshake_throttle_provider_;
351 
352   std::vector<std::string> cors_exempt_header_list_;
353 
354   mojo::PendingRemote<blink::mojom::ResourceLoadInfoNotifier>
355       pending_resource_load_info_notifier_;
356 
357   // Used to notify the loading stats by ResourceLoadInfo struct for dedicated
358   // workers.
359   mojo::Remote<blink::mojom::ResourceLoadInfoNotifier>
360       resource_load_info_notifier_;
361 
362   // Wrap a raw blink::mojom::ResourceLoadInfoNotifier pointer directed at
363   // |resource_load_info_notifier_|'s receiver.
364   std::unique_ptr<blink::WeakWrapperResourceLoadInfoNotifier>
365       weak_wrapper_resource_load_info_notifier_;
366 
367   blink::AcceptLanguagesWatcher* accept_languages_watcher_ = nullptr;
368 
369   // Contains pending receivers whose corresponding requests are still
370   // in-flight. The pending receivers are taken by
371   // TakePendingWorkerTimingReceiver() when the request is completed.
372   WorkerTimingContainerReceiverMap worker_timing_container_receivers_;
373 
374   base::WeakPtrFactory<WebWorkerFetchContextImpl> weak_factory_{this};
375 };
376 
377 }  // namespace content
378 
379 #endif  // CONTENT_RENDERER_LOADER_WEB_WORKER_FETCH_CONTEXT_IMPL_H_
380