1 // Copyright 2014 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_SERVICE_WORKER_SERVICE_WORKER_CONTEXT_CLIENT_H_
6 #define CONTENT_RENDERER_SERVICE_WORKER_SERVICE_WORKER_CONTEXT_CLIENT_H_
7 
8 #include <stddef.h>
9 #include <stdint.h>
10 
11 #include <map>
12 #include <memory>
13 #include <string>
14 
15 #include "base/callback.h"
16 #include "base/containers/id_map.h"
17 #include "base/macros.h"
18 #include "base/memory/scoped_refptr.h"
19 #include "base/strings/string16.h"
20 #include "base/time/time.h"
21 #include "content/common/content_export.h"
22 #include "ipc/ipc_listener.h"
23 #include "mojo/public/cpp/bindings/pending_associated_remote.h"
24 #include "mojo/public/cpp/bindings/pending_receiver.h"
25 #include "mojo/public/cpp/bindings/remote.h"
26 #include "mojo/public/cpp/bindings/shared_associated_remote.h"
27 #include "third_party/blink/public/common/service_worker/service_worker_status_code.h"
28 #include "third_party/blink/public/mojom/background_fetch/background_fetch.mojom-forward.h"
29 #include "third_party/blink/public/mojom/payments/payment_app.mojom-forward.h"
30 #include "third_party/blink/public/mojom/service_worker/controller_service_worker.mojom-forward.h"
31 #include "third_party/blink/public/mojom/service_worker/embedded_worker.mojom.h"
32 #include "third_party/blink/public/mojom/service_worker/service_worker.mojom-forward.h"
33 #include "third_party/blink/public/mojom/service_worker/service_worker_client.mojom-forward.h"
34 #include "third_party/blink/public/mojom/service_worker/service_worker_event_status.mojom-forward.h"
35 #include "third_party/blink/public/mojom/service_worker/service_worker_provider.mojom-forward.h"
36 #include "third_party/blink/public/mojom/service_worker/service_worker_registration.mojom-forward.h"
37 #include "third_party/blink/public/mojom/worker/subresource_loader_updater.mojom-forward.h"
38 #include "third_party/blink/public/mojom/worker/worker_content_settings_proxy.mojom-forward.h"
39 #include "third_party/blink/public/mojom/worker/worker_content_settings_proxy.mojom.h"
40 #include "third_party/blink/public/platform/modules/service_worker/web_service_worker_error.h"
41 #include "third_party/blink/public/web/modules/service_worker/web_service_worker_context_client.h"
42 #include "third_party/blink/public/web/modules/service_worker/web_service_worker_context_proxy.h"
43 #include "third_party/blink/public/web/web_embedded_worker.h"
44 #include "v8/include/v8.h"
45 
46 namespace base {
47 class SequencedTaskRunner;
48 class SingleThreadTaskRunner;
49 }
50 
51 namespace blink {
52 class ChildURLLoaderFactoryBundle;
53 class WebServiceWorkerContextProxy;
54 class WebURLResponse;
55 struct WebServiceWorkerInstalledScriptsManagerParams;
56 }
57 
58 namespace content {
59 
60 class EmbeddedWorkerInstanceClientImpl;
61 class WebServiceWorkerFetchContext;
62 
63 // ServiceWorkerContextClient is a "client" of a service worker execution
64 // context. It enables communication between the embedder and Blink's
65 // ServiceWorkerGlobalScope. It is created when the service worker begins
66 // starting up, and destroyed when the service worker stops. It is owned by
67 // WebEmbeddedWorkerImpl (which is owned by EmbeddedWorkerInstanceClientImpl).
68 //
69 // This class is created and destroyed on the "initiator" thread. The initiator
70 // thread is the thread that constructs this class. Currently it's the main
71 // thread but could be the IO thread in the future. https://crbug.com/692909
72 //
73 // Unless otherwise noted (here or in base class documentation), all methods
74 // are called on the worker thread.
75 class CONTENT_EXPORT ServiceWorkerContextClient
76     : public blink::WebServiceWorkerContextClient {
77  public:
78   // Called on the initiator thread.
79   // - |is_starting_installed_worker| is true if the script is already installed
80   //   and will be streamed from the browser process.
81   // - |owner| must outlive this new instance.
82   // - |start_timing| should be initially populated with
83   //   |start_worker_received_time|. This instance will fill in the rest during
84   //   startup.
85   // - |subresource_loader_updater| is a mojo receiver that will be bound to
86   //   ServiceWorkerFetchContextImpl. This interface is used to update
87   //   subresource loader factories.
88   // - |script_url_to_skip_throttling| is the URL of the service worker script
89   //   that already started being loaded by the browser process due to the
90   //   update check, or the empty URL if there is no such script. See also
91   //   comments in EmbeddedWorkerStartParams::script_url_to_skip_throttling.
92   ServiceWorkerContextClient(
93       int64_t service_worker_version_id,
94       const GURL& service_worker_scope,
95       const GURL& script_url,
96       bool is_starting_installed_worker,
97       const blink::RendererPreferences& renderer_preferences,
98       mojo::PendingReceiver<blink::mojom::ServiceWorker>
99           service_worker_receiver,
100       mojo::PendingReceiver<blink::mojom::ControllerServiceWorker>
101           controller_receiver,
102       mojo::PendingAssociatedRemote<blink::mojom::EmbeddedWorkerInstanceHost>
103           instance_host,
104       blink::mojom::ServiceWorkerProviderInfoForStartWorkerPtr provider_info,
105       EmbeddedWorkerInstanceClientImpl* owner,
106       blink::mojom::EmbeddedWorkerStartTimingPtr start_timing,
107       mojo::PendingReceiver<blink::mojom::RendererPreferenceWatcher>
108           preference_watcher_receiver,
109       std::unique_ptr<blink::PendingURLLoaderFactoryBundle> subresource_loaders,
110       mojo::PendingReceiver<blink::mojom::SubresourceLoaderUpdater>
111           subresource_loader_updater,
112       const GURL& script_url_to_skip_throttling,
113       scoped_refptr<base::SingleThreadTaskRunner> initiator_thread_task_runner,
114       int32_t service_worker_route_id,
115       const std::vector<std::string>& cors_exempt_header_list);
116   // Called on the initiator thread.
117   ~ServiceWorkerContextClient() override;
118 
119   // Called on the initiator thread.
120   void StartWorkerContextOnInitiatorThread(
121       std::unique_ptr<blink::WebEmbeddedWorker> worker,
122       std::unique_ptr<blink::WebEmbeddedWorkerStartData> start_data,
123       std::unique_ptr<blink::WebServiceWorkerInstalledScriptsManagerParams>,
124       mojo::PendingRemote<blink::mojom::WorkerContentSettingsProxy>
125           content_settings,
126       mojo::PendingRemote<blink::mojom::CacheStorage> cache_storage,
127       mojo::PendingRemote<blink::mojom::BrowserInterfaceBroker>
128           browser_interface_broker);
129 
130   // Called on the initiator thread.
131   blink::WebEmbeddedWorker& worker();
132 
133   // WebServiceWorkerContextClient overrides.
134   void WorkerReadyForInspectionOnInitiatorThread(
135       blink::CrossVariantMojoRemote<blink::mojom::DevToolsAgentInterfaceBase>
136           devtools_agent_remote,
137       blink::CrossVariantMojoReceiver<
138           blink::mojom::DevToolsAgentHostInterfaceBase>
139           devtools_agent_host_receiver) override;
140   void FailedToFetchClassicScript() override;
141   void FailedToFetchModuleScript() override;
142   void WorkerScriptLoadedOnWorkerThread() override;
143   void WorkerContextStarted(
144       blink::WebServiceWorkerContextProxy* proxy,
145       scoped_refptr<base::SequencedTaskRunner> worker_task_runner) override;
146   void WillEvaluateScript(v8::Local<v8::Context> v8_context) override;
147   void DidEvaluateScript(bool success) override;
148   void WillInitializeWorkerContext() override;
149   void WillDestroyWorkerContext(v8::Local<v8::Context> context) override;
150   void WorkerContextDestroyed() override;
151   void CountFeature(blink::mojom::WebFeature feature) override;
152   void ReportException(const blink::WebString& error_message,
153                        int line_number,
154                        int column_number,
155                        const blink::WebString& source_url) override;
156   void ReportConsoleMessage(blink::mojom::ConsoleMessageSource source,
157                             blink::mojom::ConsoleMessageLevel level,
158                             const blink::WebString& message,
159                             int line_number,
160                             const blink::WebString& source_url) override;
161   void SetupNavigationPreload(int fetch_event_id,
162                               const blink::WebURL& url,
163                               std::unique_ptr<blink::WebFetchEventPreloadHandle>
164                                   preload_handle) override;
165   void RequestTermination(RequestTerminationCallback callback) override;
166   scoped_refptr<blink::WebServiceWorkerFetchContext>
167   CreateWorkerFetchContextOnInitiatorThread() override;
168 
169   /////////////////////////////////////////////////////////////////////////////
170   // The following are for use by NavigationPreloadRequest.
171   //
172   // Called to resolve the FetchEvent.preloadResponse promise.
173   void OnNavigationPreloadResponse(
174       int fetch_event_id,
175       std::unique_ptr<blink::WebURLResponse> response,
176       mojo::ScopedDataPipeConsumerHandle data_pipe);
177 
178   // Called when the navigation preload request completed. Either
179   // OnNavigationPreloadComplete() or OnNavigationPreloadError() must be
180   // called to release the preload related resources.
181   void OnNavigationPreloadComplete(int fetch_event_id,
182                                    base::TimeTicks completion_time,
183                                    int64_t encoded_data_length,
184                                    int64_t encoded_body_length,
185                                    int64_t decoded_body_length);
186 
187   // Called when an error occurred while receiving the response of the
188   // navigation preload request.
189   void OnNavigationPreloadError(
190       int fetch_event_id,
191       std::unique_ptr<blink::WebServiceWorkerError> error);
192   /////////////////////////////////////////////////////////////////////////////
193 
194  private:
195   struct WorkerContextData;
196   friend class ControllerServiceWorkerImpl;
197   friend class ServiceWorkerContextClientTest;
198   FRIEND_TEST_ALL_PREFIXES(
199       ServiceWorkerContextClientTest,
200       DispatchOrQueueFetchEvent_RequestedTerminationAndDie);
201   FRIEND_TEST_ALL_PREFIXES(
202       ServiceWorkerContextClientTest,
203       DispatchOrQueueFetchEvent_RequestedTerminationAndWakeUp);
204   FRIEND_TEST_ALL_PREFIXES(ServiceWorkerContextClientTest,
205                            DispatchOrQueueFetchEvent_NotRequestedTermination);
206   FRIEND_TEST_ALL_PREFIXES(ServiceWorkerContextClientTest, TaskInServiceWorker);
207 
208   void SendWorkerStarted(blink::mojom::ServiceWorkerStartStatus status);
209 
210   // Stops the worker context. Called on the initiator thread.
211   void StopWorkerOnInitiatorThread();
212 
213   base::WeakPtr<ServiceWorkerContextClient> GetWeakPtr();
214 
215   const int64_t service_worker_version_id_;
216   const GURL service_worker_scope_;
217   const GURL script_url_;
218   // True if this service worker was already installed at worker
219   // startup time.
220   const bool is_starting_installed_worker_;
221 
222   // See comments in EmbeddedWorkerStartParams::script_url_to_skip_throttling.
223   const GURL script_url_to_skip_throttling_;
224 
225   blink::RendererPreferences renderer_preferences_;
226   // Passed on creation of ServiceWorkerFetchContext.
227   mojo::PendingReceiver<blink::mojom::RendererPreferenceWatcher>
228       preference_watcher_receiver_;
229 
230   scoped_refptr<base::SingleThreadTaskRunner> initiator_thread_task_runner_;
231   scoped_refptr<base::SequencedTaskRunner> worker_task_runner_;
232 
233   // Not owned; |this| is destroyed when |proxy_| becomes invalid.
234   blink::WebServiceWorkerContextProxy* proxy_;
235 
236   // These Mojo objects are bound on the worker thread.
237   mojo::PendingReceiver<blink::mojom::ServiceWorker>
238       pending_service_worker_receiver_;
239   mojo::PendingReceiver<blink::mojom::ControllerServiceWorker>
240       controller_receiver_;
241   mojo::PendingReceiver<blink::mojom::SubresourceLoaderUpdater>
242       pending_subresource_loader_updater_;
243 
244   // This is bound on the initiator thread.
245   mojo::SharedAssociatedRemote<blink::mojom::EmbeddedWorkerInstanceHost>
246       instance_host_;
247 
248   // This holds blink.mojom.ServiceWorkerContainer(Host) connections to the
249   // browser-side ServiceWorkerHost to keep it alive there.
250   // Note: |service_worker_provider_info_->script_loader_factory_remote| is
251   // moved to WebServiceWorkerNetworkProviderImpl when
252   // CreateServiceWorkerNetworkProvider is called.
253   blink::mojom::ServiceWorkerProviderInfoForStartWorkerPtr
254       service_worker_provider_info_;
255 
256   // Must be accessed on the initiator thread only.
257   EmbeddedWorkerInstanceClientImpl* owner_;
258 
259   // Initialized on the worker thread in WorkerContextStarted and
260   // destructed on the worker thread in WillDestroyWorkerContext.
261   //
262   // WARNING: This can be cleared at nearly any time, since WillDestroyContext
263   // is called by Blink when it decides to terminate the worker thread. This
264   // includes during event dispatch if a JavaScript debugger breakpoint pauses
265   // execution (see issue 934622). It should be safe to assume |context_| is
266   // valid at the start of a task that was posted to |worker_task_runner_|, as
267   // that is from WorkerThread::GetTaskRunner() which safely drops the task on
268   // worker termination.
269   std::unique_ptr<WorkerContextData> context_;
270 
271   // Accessed on the worker thread. Passed to the browser process after worker
272   // startup completes.
273   blink::mojom::EmbeddedWorkerStartTimingPtr start_timing_;
274 
275   // A URLLoaderFactory instance used for subresource loading.
276   scoped_refptr<blink::ChildURLLoaderFactoryBundle> loader_factories_;
277 
278   // Out-of-process NetworkService:
279   // Detects disconnection from the network service.
280   mojo::Remote<network::mojom::URLLoaderFactory>
281       network_service_disconnect_handler_holder_;
282 
283   std::unique_ptr<blink::WebEmbeddedWorker> worker_;
284 
285   int32_t service_worker_route_id_;
286 
287   std::vector<std::string> cors_exempt_header_list_;
288 
289   DISALLOW_COPY_AND_ASSIGN(ServiceWorkerContextClient);
290 };
291 
292 }  // namespace content
293 
294 #endif  // CONTENT_RENDERER_SERVICE_WORKER_SERVICE_WORKER_CONTEXT_CLIENT_H_
295