| // Copyright 2014 The Chromium Authors. All rights reserved. |
| // 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_PROVIDER_CONTEXT_H_ |
| #define CONTENT_RENDERER_SERVICE_WORKER_SERVICE_WORKER_PROVIDER_CONTEXT_H_ |
| |
| #include <memory> |
| #include <set> |
| #include <string> |
| #include <vector> |
| |
| #include "base/gtest_prod_util.h" |
| #include "base/macros.h" |
| #include "base/memory/ref_counted.h" |
| #include "base/memory/weak_ptr.h" |
| #include "content/common/content_export.h" |
| #include "mojo/public/cpp/bindings/associated_receiver.h" |
| #include "mojo/public/cpp/bindings/associated_remote.h" |
| #include "mojo/public/cpp/bindings/pending_associated_receiver.h" |
| #include "mojo/public/cpp/bindings/pending_associated_remote.h" |
| #include "mojo/public/cpp/bindings/pending_receiver.h" |
| #include "mojo/public/cpp/bindings/pending_remote.h" |
| #include "mojo/public/cpp/bindings/receiver_set.h" |
| #include "mojo/public/cpp/bindings/remote.h" |
| #include "services/network/public/mojom/url_loader_factory.mojom.h" |
| #include "third_party/blink/public/mojom/service_worker/controller_service_worker.mojom.h" |
| #include "third_party/blink/public/mojom/service_worker/service_worker_container.mojom.h" |
| #include "third_party/blink/public/mojom/service_worker/service_worker_container_type.mojom-forward.h" |
| #include "third_party/blink/public/mojom/service_worker/service_worker_object.mojom-forward.h" |
| #include "third_party/blink/public/mojom/service_worker/service_worker_provider.mojom.h" |
| #include "third_party/blink/public/mojom/service_worker/service_worker_registration.mojom-forward.h" |
| #include "third_party/blink/public/mojom/timing/worker_timing_container.mojom-forward.h" |
| #include "third_party/blink/public/mojom/web_feature/web_feature.mojom-forward.h" |
| #include "third_party/blink/public/platform/modules/service_worker/web_service_worker_provider_client.h" |
| |
| namespace base { |
| class SingleThreadTaskRunner; |
| } // namespace base |
| |
| namespace network { |
| class SharedURLLoaderFactory; |
| class WeakWrapperSharedURLLoaderFactory; |
| } // namespace network |
| |
| namespace content { |
| |
| namespace mojom { |
| class URLLoaderFactory; |
| } // namespace mojom |
| |
| namespace service_worker_provider_context_unittest { |
| class ServiceWorkerProviderContextTest; |
| FORWARD_DECLARE_TEST(ServiceWorkerProviderContextTest, |
| SetControllerServiceWorker); |
| FORWARD_DECLARE_TEST(ServiceWorkerProviderContextTest, |
| ControllerWithoutFetchHandler); |
| } // namespace service_worker_provider_context_unittest |
| |
| class WebServiceWorkerProviderImpl; |
| struct ServiceWorkerProviderContextDeleter; |
| |
| // ServiceWorkerProviderContext stores common state for "providers" for service |
| // worker clients (currently WebServiceWorkerProviderImpl and |
| // ServiceWorkerNetworkProviderForFrame). Providers for the same underlying |
| // entity hold strong references to a shared instance of this class. |
| // |
| // ServiceWorkerProviderContext is also a |
| // blink::mojom::ServiceWorkerWorkerClientRegistry. If it's a provider for a |
| // document, then it tracks all the dedicated workers created from the document |
| // (including nested workers), as dedicated workers don't yet have their own |
| // providers. If it's a provider for a shared worker, then it tracks only the |
| // shared worker itself. |
| // |
| // Created and destructed on the main thread. Unless otherwise noted, all |
| // methods are called on the main thread. |
| class CONTENT_EXPORT ServiceWorkerProviderContext |
| : public base::RefCountedThreadSafe<ServiceWorkerProviderContext, |
| ServiceWorkerProviderContextDeleter>, |
| public blink::mojom::ServiceWorkerContainer, |
| public blink::mojom::ServiceWorkerWorkerClientRegistry { |
| public: |
| // |receiver_| is connected to the content::ServiceWorkerProviderHost that |
| // notifies of changes to the registration's and workers' status. |
| // |
| // |controller_info| contains the endpoint and object info that is needed to |
| // set up the controller service worker for the context. |
| // |
| // |fallback_loader_factory| is a default loader factory for fallback |
| // requests, and is used when we create a subresource loader for controllees. |
| // This is non-null only if the provider is created for controllees, and if |
| // the loading context, e.g. a frame, provides it. |
| ServiceWorkerProviderContext( |
| blink::mojom::ServiceWorkerContainerType container_type, |
| mojo::PendingAssociatedReceiver<blink::mojom::ServiceWorkerContainer> |
| receiver, |
| mojo::PendingAssociatedRemote<blink::mojom::ServiceWorkerContainerHost> |
| host_remote, |
| blink::mojom::ControllerServiceWorkerInfoPtr controller_info, |
| scoped_refptr<network::SharedURLLoaderFactory> fallback_loader_factory); |
| |
| blink::mojom::ServiceWorkerContainerType container_type() const { |
| return container_type_; |
| } |
| |
| // Returns version id of the controller service worker object |
| // (ServiceWorkerContainer#controller). |
| int64_t GetControllerVersionId() const; |
| |
| blink::mojom::ControllerServiceWorkerMode GetControllerServiceWorkerMode() |
| const; |
| |
| // Takes the controller service worker object info set by SetController() if |
| // any, otherwise returns nullptr. |
| blink::mojom::ServiceWorkerObjectInfoPtr TakeController(); |
| |
| // Returns the factory for loading subresources with the controller |
| // ServiceWorker, or nullptr if no controller is attached. Returns a |
| // WeakWrapperSharedURLLoaderFactory because the inner factory is destroyed |
| // when this context is destroyed but loaders may persist a reference to the |
| // loader returned from this method. |
| scoped_refptr<network::WeakWrapperSharedURLLoaderFactory> |
| GetSubresourceLoaderFactory(); |
| |
| // Returns the feature usage of the controller service worker. |
| const std::set<blink::mojom::WebFeature>& used_features() const; |
| |
| // The Client#id value of this context. |
| const std::string& client_id() const; |
| |
| // For providers for frames. See |fetch_request_window_id| in |
| // network::ResourceRequest. |
| const base::UnguessableToken& fetch_request_window_id() const; |
| |
| // Sets a weak pointer back to the WebServiceWorkerProviderImpl (which |
| // corresponds to ServiceWorkerContainer in JavaScript) which has a strong |
| // reference to |this|. This allows us to notify the |
| // WebServiceWorkerProviderImpl when ServiceWorkerContainer#controller should |
| // be changed. |
| void SetWebServiceWorkerProvider( |
| base::WeakPtr<WebServiceWorkerProviderImpl> provider); |
| |
| // blink::mojom::ServiceWorkerWorkerClientRegistry: |
| void RegisterWorkerClient( |
| mojo::PendingRemote<blink::mojom::ServiceWorkerWorkerClient> |
| pending_client) override; |
| void CloneWorkerClientRegistry( |
| mojo::PendingReceiver<blink::mojom::ServiceWorkerWorkerClientRegistry> |
| receiver) override; |
| |
| // Returns a remote to this context's container host. This can return null |
| // after OnNetworkProviderDestroyed() is called (in which case |this| will be |
| // destroyed soon). |
| mojo::PendingRemote<blink::mojom::ServiceWorkerContainerHost> |
| CloneRemoteContainerHost(); |
| |
| // Called when WebServiceWorkerNetworkProvider is destructed. This function |
| // severs the Mojo binding to the browser-side ServiceWorkerProviderHost. The |
| // reason WebServiceWorkerNetworkProvider is special compared to the other |
| // providers, is that it is destructed synchronously when a service worker |
| // client (Document) is removed from the DOM. Once this happens, the |
| // ServiceWorkerProviderHost must destruct quickly in order to remove the |
| // ServiceWorkerClient from the system (thus allowing unregistration/update to |
| // occur and ensuring the Clients API doesn't return the client). |
| // |
| // TODO(https://crbug.com/931497): Remove this weird partially destroyed |
| // state. |
| void OnNetworkProviderDestroyed(); |
| |
| // Gets the blink::mojom::ServiceWorkerContainerHost* for sending requests to |
| // browser-side ServiceWorkerProviderHost. May be nullptr if |
| // OnNetworkProviderDestroyed() has already been called. |
| // Currently this can be called only for clients that are Documents, |
| // see comments of |container_host_|. |
| blink::mojom::ServiceWorkerContainerHost* container_host() const; |
| |
| // Called when blink::IdlenessDetector emits its network idle signal. Tells |
| // the browser process that this page is quiet soon after page load, as a |
| // hint to start the service worker update check. |
| void DispatchNetworkQuiet(); |
| |
| // Tells the container host that this context is execution ready: |
| // https://html.spec.whatwg.org/multipage/webappapis.html#concept-environment-execution-ready-flag |
| void NotifyExecutionReady(); |
| |
| // Sets up |receiver| to receive resource performance timings for the given |
| // |request_id|. This receiver will be taken later by |
| // TakePendingWorkerTimingReceiver(). |
| void AddPendingWorkerTimingReceiver( |
| int request_id, |
| mojo::PendingReceiver<blink::mojom::WorkerTimingContainer> receiver); |
| |
| mojo::PendingReceiver<blink::mojom::WorkerTimingContainer> |
| TakePendingWorkerTimingReceiver(int request_id); |
| |
| private: |
| friend class base::DeleteHelper<ServiceWorkerProviderContext>; |
| friend class base::RefCountedThreadSafe<ServiceWorkerProviderContext, |
| ServiceWorkerProviderContextDeleter>; |
| friend class service_worker_provider_context_unittest:: |
| ServiceWorkerProviderContextTest; |
| friend struct ServiceWorkerProviderContextDeleter; |
| FRIEND_TEST_ALL_PREFIXES(service_worker_provider_context_unittest:: |
| ServiceWorkerProviderContextTest, |
| SetControllerServiceWorker); |
| FRIEND_TEST_ALL_PREFIXES(service_worker_provider_context_unittest:: |
| ServiceWorkerProviderContextTest, |
| ControllerWithoutFetchHandler); |
| using WorkerTimingContainerReceiverMap = |
| std::map<int /* request_id */, |
| mojo::PendingReceiver<blink::mojom::WorkerTimingContainer>>; |
| |
| ~ServiceWorkerProviderContext() override; |
| |
| void DestructOnMainThread() const; |
| |
| // Clears the information of the ServiceWorkerWorkerClient of dedicated (or |
| // shared) worker, when the connection to the worker is disconnected. |
| void UnregisterWorkerFetchContext(blink::mojom::ServiceWorkerWorkerClient*); |
| |
| // Implementation of blink::mojom::ServiceWorkerContainer. |
| void SetController( |
| blink::mojom::ControllerServiceWorkerInfoPtr controller_info, |
| bool should_notify_controllerchange) override; |
| void PostMessageToClient(blink::mojom::ServiceWorkerObjectInfoPtr source, |
| blink::TransferableMessage message) override; |
| void CountFeature(blink::mojom::WebFeature feature) override; |
| |
| // A convenient utility method to tell if a subresource loader factory |
| // can be created for this context. |
| bool CanCreateSubresourceLoaderFactory() const; |
| |
| // Returns URLLoaderFactory for loading subresources with the controller |
| // ServiceWorker, or nullptr if no controller is attached. |
| network::mojom::URLLoaderFactory* GetSubresourceLoaderFactoryInternal(); |
| |
| const blink::mojom::ServiceWorkerContainerType container_type_; |
| scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner_; |
| |
| // This keeps the connection to the content::ServiceWorkerProviderHost in the |
| // browser process alive. |
| mojo::AssociatedReceiver<blink::mojom::ServiceWorkerContainer> receiver_; |
| |
| // The |container_host_| remote represents the connection to the |
| // browser-side ServiceWorkerProviderHost, whose lifetime is bound to |
| // |container_host_| via the Mojo connection. This may be nullptr if the Mojo |
| // connection was broken in OnNetworkProviderDestroyed(). |
| // |
| // The |container_host_| remote also implements functions for |
| // navigator.serviceWorker, but all the methods that correspond to |
| // navigator.serviceWorker.* can be used only if |this| is a provider |
| // for a Document, as navigator.serviceWorker is currently only implemented |
| // for Document (https://crbug.com/371690). |
| // Note: Currently this is always bound on main thread. |
| mojo::AssociatedRemote<blink::mojom::ServiceWorkerContainerHost> |
| container_host_; |
| |
| // |controller_| will be set by SetController() and taken by TakeController(). |
| blink::mojom::ServiceWorkerObjectInfoPtr controller_; |
| // Keeps version id of the current controller service worker object. |
| int64_t controller_version_id_ = blink::mojom::kInvalidServiceWorkerVersionId; |
| |
| // Used to intercept requests from the controllee and dispatch them |
| // as events to the controller ServiceWorker. |
| mojo::Remote<network::mojom::URLLoaderFactory> subresource_loader_factory_; |
| |
| // Used when we create |subresource_loader_factory_|. |
| scoped_refptr<network::SharedURLLoaderFactory> fallback_loader_factory_; |
| |
| // Used to ensure handed out loader factories are properly detached when the |
| // contained subresource_loader_factory goes away. |
| scoped_refptr<network::WeakWrapperSharedURLLoaderFactory> |
| weak_wrapped_subresource_loader_factory_; |
| |
| // The Client#id value for this context. |
| std::string client_id_; |
| |
| // Corresponds to a request's "window" in the Fetch spec: |
| // https://fetch.spec.whatwg.org/#concept-request-window |
| base::UnguessableToken fetch_request_window_id_; |
| |
| blink::mojom::ControllerServiceWorkerMode controller_mode_ = |
| blink::mojom::ControllerServiceWorkerMode::kNoController; |
| |
| // Tracks feature usage for UseCounter. |
| std::set<blink::mojom::WebFeature> used_features_; |
| |
| // Corresponds to this context's ServiceWorkerContainer. May be null when not |
| // yet created, when already destroyed, or when this client is not a Document |
| // and therefore doesn't support navigator.serviceWorker. |
| base::WeakPtr<WebServiceWorkerProviderImpl> web_service_worker_provider_; |
| |
| // Remotes for dedicated or shared workers which are associated with the |
| // ServiceWorkerProviderContext. |
| // - If this ServiceWorkerProviderContext is for a Document, then |
| // |worker_clients| contains all its dedicated workers. |
| // - If this ServiceWorkerProviderContext is for a SharedWorker (technically |
| // speaking, for its shadow page), then |worker_clients| has one element: |
| // the shared worker. |
| std::vector<mojo::Remote<blink::mojom::ServiceWorkerWorkerClient>> |
| worker_clients_; |
| |
| // For adding new ServiceWorkerWorkerClients. |
| mojo::ReceiverSet<blink::mojom::ServiceWorkerWorkerClientRegistry> |
| worker_client_registry_receivers_; |
| |
| // Used in |subresource_loader_factory_| to get the connection to the |
| // controller service worker. |
| // |
| // |remote_controller_| is a Mojo pipe to the controller service worker, |
| // and is to be passed to (i.e. taken by) a subresource loader factory when |
| // GetSubresourceLoaderFactory() is called for the first time when a valid |
| // controller exists. |
| // |
| // |controller_connector_| is a Mojo pipe to the |
| // ControllerServiceWorkerConnector that is attached to the newly created |
| // subresource loader factory and lives on a background thread. This is |
| // populated when GetSubresourceLoader() creates the subresource loader |
| // factory and takes |controller_endpoint_|. |
| mojo::PendingRemote<blink::mojom::ControllerServiceWorker> remote_controller_; |
| mojo::Remote<blink::mojom::ControllerServiceWorkerConnector> |
| controller_connector_; |
| |
| bool sent_execution_ready_ = false; |
| |
| // Contains pending receivers whose corresponding requests are still |
| // in-flight. The pending receivers are taken by |
| // TakePendingWorkerTimingReceiver() when the request is completed. |
| WorkerTimingContainerReceiverMap worker_timing_container_receivers_; |
| |
| base::WeakPtrFactory<ServiceWorkerProviderContext> weak_factory_{this}; |
| |
| DISALLOW_COPY_AND_ASSIGN(ServiceWorkerProviderContext); |
| }; |
| |
| struct ServiceWorkerProviderContextDeleter { |
| static void Destruct(const ServiceWorkerProviderContext* context) { |
| context->DestructOnMainThread(); |
| } |
| }; |
| |
| } // namespace content |
| |
| #endif // CONTENT_RENDERER_SERVICE_WORKER_SERVICE_WORKER_PROVIDER_CONTEXT_H_ |