blob: 894953a0fd36fba85606220bcf0501453626f792 [file] [log] [blame]
// 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 "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "base/sequenced_task_runner_helpers.h"
#include "content/common/content_export.h"
#include "content/common/service_worker/controller_service_worker.mojom.h"
#include "content/common/service_worker/service_worker_container.mojom.h"
#include "content/common/service_worker/service_worker_provider.mojom.h"
#include "content/renderer/service_worker/web_service_worker_provider_impl.h"
#include "mojo/public/cpp/bindings/associated_binding.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_object.mojom.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_provider_type.mojom.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_registration.mojom.h"
#include "third_party/blink/public/platform/modules/serviceworker/web_service_worker_provider_client.h"
namespace base {
class SingleThreadTaskRunner;
} // namespace base
namespace content {
namespace mojom {
class URLLoaderFactory;
} // namespace mojom
namespace service_worker_provider_context_unittest {
class ServiceWorkerProviderContextTest;
} // namespace service_worker_provider_context_unittest
class WebServiceWorkerImpl;
class WebServiceWorkerRegistrationImpl;
struct ServiceWorkerProviderContextDeleter;
// ServiceWorkerProviderContext stores common state for service worker
// "providers" (currently WebServiceWorkerProviderImpl,
// ServiceWorkerNetworkProvider, and ServiceWorkerContextClient). Providers for
// the same underlying entity hold strong references to a shared instance of
// this class.
//
// ServiceWorkerProviderContext is also a
// 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 mojom::ServiceWorkerContainer,
public mojom::ServiceWorkerWorkerClientRegistry {
public:
// Constructor for service worker clients.
//
// |provider_id| is used to identify this provider in IPC messages to the
// browser process. |request| is an endpoint which is connected to
// the content::ServiceWorkerProviderHost that notifies of changes to the
// registration's and workers' status. |request| is bound with |binding_|.
//
// |controller_info| contains the endpoint (which is non-null only when
// S13nServiceWorker is enabled) and object info that is needed to set up the
// controller service worker for the client.
// For S13nServiceWorker:
// |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(
int provider_id,
blink::mojom::ServiceWorkerProviderType provider_type,
mojom::ServiceWorkerContainerAssociatedRequest request,
mojom::ServiceWorkerContainerHostAssociatedPtrInfo host_ptr_info,
mojom::ControllerServiceWorkerInfoPtr controller_info,
scoped_refptr<network::SharedURLLoaderFactory> fallback_loader_factory);
// Constructor for service worker execution contexts.
ServiceWorkerProviderContext(
int provider_id,
mojom::ServiceWorkerContainerAssociatedRequest request,
mojom::ServiceWorkerContainerHostAssociatedPtrInfo host_ptr_info);
blink::mojom::ServiceWorkerProviderType provider_type() const {
return provider_type_;
}
int provider_id() const { return provider_id_; }
// For service worker execution contexts. Sets the registration for
// ServiceWorkerGlobalScope#registration. Unlike
// TakeRegistrationForServiceWorkerGlobalScope(), called on the main thread.
// SetRegistrationForServiceWorkerGlobalScope() is called during the setup for
// service worker startup, so it is guaranteed to be called before
// TakeRegistrationForServiceWorkerGlobalScope().
void SetRegistrationForServiceWorkerGlobalScope(
blink::mojom::ServiceWorkerRegistrationObjectInfoPtr registration);
// For service worker execution contexts. Used for initializing
// ServiceWorkerGlobalScope#registration. Called on the worker thread.
// This takes the registration that was passed to
// SetRegistrationForServiceWorkerScope(), then creates a new
// WebServiceWorkerRegistrationImpl instance and returns it.
scoped_refptr<WebServiceWorkerRegistrationImpl>
TakeRegistrationForServiceWorkerGlobalScope();
// For service worker clients. Returns version id of the controller service
// worker object (ServiceWorkerContainer#controller).
int64_t GetControllerVersionId() const;
blink::mojom::ControllerServiceWorkerMode IsControlledByServiceWorker() const;
// For service worker clients. Takes the controller service worker object info
// set by SetController() if any, otherwise returns nullptr.
blink::mojom::ServiceWorkerObjectInfoPtr TakeController();
// S13nServiceWorker:
// For service worker clients. Returns URLLoaderFactory for loading
// subresources with the controller ServiceWorker, or nullptr if
// no controller is attached.
network::mojom::URLLoaderFactory* GetSubresourceLoaderFactory();
// For service worker clients. Returns the feature usage of its controller.
const std::set<blink::mojom::WebFeature>& used_features() const;
// S13nServiceWorker:
// The Client#id value of the client.
const std::string& client_id() const;
// For service worker clients. 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);
// mojom::ServiceWorkerWorkerClientRegistry:
void RegisterWorkerClient(
mojom::ServiceWorkerWorkerClientPtr client) override;
void CloneWorkerClientRegistry(
mojom::ServiceWorkerWorkerClientRegistryRequest request) override;
// S13nServiceWorker:
// For service worker clients. Creates a ServiceWorkerContainerHostPtrInfo
// which can be bound to a ServiceWorkerContainerHostPtr in a (dedicated or
// shared) worker thread. WorkerFetchContextImpl will use the host pointer to
// get the controller service worker by GetControllerServiceWorker() and send
// FetchEvents to the service worker.
mojom::ServiceWorkerContainerHostPtrInfo CloneContainerHostPtrInfo();
// For service worker clients. Returns the registration object described by
// |info|. Creates a new object if needed, or else returns the existing one.
scoped_refptr<WebServiceWorkerRegistrationImpl>
GetOrCreateServiceWorkerRegistrationObject(
blink::mojom::ServiceWorkerRegistrationObjectInfoPtr info);
// For service worker clients. Returns the service worker object described by
// |info|. Creates a new object if needed, or else returns the existing one.
scoped_refptr<WebServiceWorkerImpl> GetOrCreateServiceWorkerObject(
blink::mojom::ServiceWorkerObjectInfoPtr info);
// Called when ServiceWorkerNetworkProvider is destructed. This function
// severs the Mojo binding to the browser-side ServiceWorkerProviderHost. The
// reason ServiceWorkerNetworkProvider 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).
void OnNetworkProviderDestroyed();
// Gets the 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_|.
mojom::ServiceWorkerContainerHost* container_host() const;
// Pings the container host and calls |callback| once a pong arrived. Useful
// for waiting for all messages the host sent thus far to arrive.
void PingContainerHost(base::OnceClosure callback);
private:
friend class base::DeleteHelper<ServiceWorkerProviderContext>;
friend class base::RefCountedThreadSafe<ServiceWorkerProviderContext,
ServiceWorkerProviderContextDeleter>;
friend class service_worker_provider_context_unittest::
ServiceWorkerProviderContextTest;
friend class WebServiceWorkerImpl;
friend class WebServiceWorkerRegistrationImpl;
friend struct ServiceWorkerProviderContextDeleter;
struct ProviderStateForClient;
~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(mojom::ServiceWorkerWorkerClient*);
// Implementation of mojom::ServiceWorkerContainer.
void SetController(mojom::ControllerServiceWorkerInfoPtr controller_info,
const std::vector<blink::mojom::WebFeature>& used_features,
bool should_notify_controllerchange) override;
void PostMessageToClient(blink::mojom::ServiceWorkerObjectInfoPtr source,
blink::TransferableMessage message) override;
void CountFeature(blink::mojom::WebFeature feature) override;
// For service worker clients. Keeps the mapping from registration_id to
// ServiceWorkerRegistration object.
void AddServiceWorkerRegistrationObject(
int64_t registration_id,
WebServiceWorkerRegistrationImpl* registration);
void RemoveServiceWorkerRegistrationObject(int64_t registration_id);
bool ContainsServiceWorkerRegistrationObjectForTesting(
int64_t registration_id);
// For service worker clients. Keeps the mapping from version id to
// ServiceWorker object.
void AddServiceWorkerObject(int64_t version_id, WebServiceWorkerImpl* worker);
void RemoveServiceWorkerObject(int64_t version_id);
bool ContainsServiceWorkerObjectForTesting(int64_t version_id);
// S13nServiceWorker:
// For service worker clients.
// A convenient utility method to tell if a subresource loader factory
// can be created for this client.
bool CanCreateSubresourceLoaderFactory() const;
const blink::mojom::ServiceWorkerProviderType provider_type_;
const int provider_id_;
scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner_;
// Mojo binding for the |request| passed to the constructor. This keeps the
// connection to the content::ServiceWorkerProviderHost in the browser process
// alive.
mojo::AssociatedBinding<mojom::ServiceWorkerContainer> binding_;
// The |container_host_| interface represents the connection to the
// browser-side ServiceWorkerProviderHost, whose lifetime is bound to
// |container_host_| via the Mojo connection.
// The |container_host_| interface 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.
mojom::ServiceWorkerContainerHostAssociatedPtr container_host_;
// State for service worker clients.
std::unique_ptr<ProviderStateForClient> state_for_client_;
// NOTE: Add new members to |state_for_client_| if they are relevant only for
// service worker clients. Not here!
base::WeakPtrFactory<ServiceWorkerProviderContext> weak_factory_;
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_