blob: a6ec8410adf9004fcba0748939832ca2db878d3a [file] [log] [blame]
// Copyright 2019 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_BROWSER_SERVICE_WORKER_SERVICE_WORKER_CONTAINER_HOST_H_
#define CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_CONTAINER_HOST_H_
#include <map>
#include <memory>
#include <string>
#include <vector>
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "base/optional.h"
#include "base/time/time.h"
#include "content/browser/renderer_host/back_forward_cache_metrics.h"
#include "content/browser/service_worker/service_worker_registration.h"
#include "content/common/content_export.h"
#include "content/public/browser/service_worker_client_info.h"
#include "content/public/common/child_process_host.h"
#include "mojo/public/cpp/bindings/associated_remote.h"
#include "mojo/public/cpp/bindings/receiver_set.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "net/cookies/site_for_cookies.h"
#include "services/metrics/public/cpp/ukm_source_id.h"
#include "third_party/blink/public/common/service_worker/service_worker_status_code.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_client.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.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_registration.mojom.h"
namespace network {
struct CrossOriginEmbedderPolicy;
}
namespace content {
namespace service_worker_object_host_unittest {
class ServiceWorkerObjectHostTest;
}
class ServiceWorkerContextCore;
class ServiceWorkerHost;
class ServiceWorkerObjectHost;
class ServiceWorkerRegistrationObjectHost;
class ServiceWorkerVersion;
// ServiceWorkerContainerHost is the host of a service worker client (a window,
// dedicated worker, or shared worker) or service worker execution context in
// the renderer process.
//
// Most of its functionality helps implement the web-exposed
// ServiceWorkerContainer interface (navigator.serviceWorker). The long-term
// goal is for it to be the host of ServiceWorkerContainer in the renderer,
// although currently only windows support ServiceWorkerContainers (see
// https://crbug.com/371690).
//
// ServiceWorkerContainerHost is also responsible for handling service worker
// related things in the execution context where the container lives. For
// example, the container host manages service worker (registration) JavaScript
// object hosts, delivers messages to/from the service worker, and dispatches
// events on the container.
//
// Ownership model and responsibilities of ServiceWorkerContainerHost are
// slightly different based on the type of the execution context that the
// container host serves:
//
// For service worker clients, ServiceWorkerContainerHost is owned by
// ServiceWorkerContextCore. The container host has a Mojo connection to the
// container in the renderer, and destruction of the container host happens upon
// disconnection of the Mojo pipe.
//
// For service worker clients, the container host works as a source of truth of
// a service worker client.
//
// Example:
// When a new service worker registration is created, the browser process
// iterates over all ServiceWorkerContainerHosts to find clients (frames,
// dedicated workers if PlzDedicatedWorker is enabled, and shared workers) with
// a URL inside the registration's scope, and has the container host watch the
// registration in order to resolve navigator.serviceWorker.ready once the
// registration settles, if need.
//
// For service worker execution contexts, ServiceWorkerContainerHost is owned
// by ServiceWorkerHost, which in turn is owned by ServiceWorkerVersion. The
// container host and worker host are destructed when the service worker is
// stopped.
class CONTENT_EXPORT ServiceWorkerContainerHost final
: public blink::mojom::ServiceWorkerContainerHost,
public ServiceWorkerRegistration::Listener {
public:
using ExecutionReadyCallback = base::OnceClosure;
// Constructor for service worker.
explicit ServiceWorkerContainerHost(
base::WeakPtr<ServiceWorkerContextCore> context);
// Constructor for window clients.
ServiceWorkerContainerHost(
base::WeakPtr<ServiceWorkerContextCore> context,
bool is_parent_frame_secure,
mojo::PendingAssociatedRemote<blink::mojom::ServiceWorkerContainer>
container_remote,
int frame_tree_node_id);
// Constructor for worker clients.
ServiceWorkerContainerHost(
base::WeakPtr<ServiceWorkerContextCore> context,
int process_id,
mojo::PendingAssociatedRemote<blink::mojom::ServiceWorkerContainer>
container_remote,
ServiceWorkerClientInfo client_info);
~ServiceWorkerContainerHost() override;
ServiceWorkerContainerHost(const ServiceWorkerContainerHost& other) = delete;
ServiceWorkerContainerHost& operator=(
const ServiceWorkerContainerHost& other) = delete;
ServiceWorkerContainerHost(ServiceWorkerContainerHost&& other) = delete;
ServiceWorkerContainerHost& operator=(ServiceWorkerContainerHost&& other) =
delete;
// Implements blink::mojom::ServiceWorkerContainerHost.
void Register(const GURL& script_url,
blink::mojom::ServiceWorkerRegistrationOptionsPtr options,
blink::mojom::FetchClientSettingsObjectPtr
outside_fetch_client_settings_object,
RegisterCallback callback) override;
void GetRegistration(const GURL& client_url,
GetRegistrationCallback callback) override;
void GetRegistrations(GetRegistrationsCallback callback) override;
void GetRegistrationForReady(
GetRegistrationForReadyCallback callback) override;
void EnsureControllerServiceWorker(
mojo::PendingReceiver<blink::mojom::ControllerServiceWorker> receiver,
blink::mojom::ControllerServiceWorkerPurpose purpose) override;
void CloneContainerHost(
mojo::PendingReceiver<blink::mojom::ServiceWorkerContainerHost> receiver)
override;
void HintToUpdateServiceWorker() override;
void EnsureFileAccess(const std::vector<base::FilePath>& file_paths,
EnsureFileAccessCallback callback) override;
void OnExecutionReady() override;
// ServiceWorkerRegistration::Listener overrides.
void OnVersionAttributesChanged(
ServiceWorkerRegistration* registration,
blink::mojom::ChangedServiceWorkerObjectsMaskPtr changed_mask) override;
void OnRegistrationFailed(ServiceWorkerRegistration* registration) override;
void OnRegistrationFinishedUninstalling(
ServiceWorkerRegistration* registration) override;
void OnSkippedWaiting(ServiceWorkerRegistration* registration) override;
// For service worker clients. The host keeps track of all the prospective
// longest-matching registrations, in order to resolve .ready or respond to
// claim() attempts.
//
// This is subtle: it doesn't keep all registrations (e.g., from storage) in
// memory, but just the ones that are possibly the longest-matching one. The
// best match from storage is added at load time. That match can't uninstall
// while this host is a controllee, so all the other stored registrations can
// be ignored. Only a newly installed registration can claim it, and new
// installing registrations are added as matches.
void AddMatchingRegistration(ServiceWorkerRegistration* registration);
void RemoveMatchingRegistration(ServiceWorkerRegistration* registration);
// An optimized implementation of [[Match Service Worker Registration]]
// for the current client.
ServiceWorkerRegistration* MatchRegistration() const;
// For service worker clients. Called when |version| is the active worker upon
// the main resource request for this client. Remembers |version| as needing
// a Soft Update. To avoid affecting page load performance, the update occurs
// when we get a HintToUpdateServiceWorker message from the renderer, or when
// |this| is destroyed before receiving that message.
//
// Corresponds to the Handle Fetch algorithm:
// "If request is a non-subresource request...invoke Soft Update algorithm
// with registration."
// https://w3c.github.io/ServiceWorker/#on-fetch-request-algorithm
//
// This can be called multiple times due to redirects during a main resource
// load. All service workers are updated.
void AddServiceWorkerToUpdate(scoped_refptr<ServiceWorkerVersion> version);
// Dispatches message event to the client (document, dedicated worker when
// PlzDedicatedWorker is enabled, or shared worker).
void PostMessageToClient(ServiceWorkerVersion* version,
blink::TransferableMessage message);
// Notifies the client that its controller used a feature, for UseCounter
// purposes. This can only be called if IsContainerForClient() is true.
void CountFeature(blink::mojom::WebFeature feature);
// Sends information about the controller to the container of the service
// worker clients in the renderer. If |notify_controllerchange| is true,
// instructs the renderer to dispatch a 'controllerchange' event.
void SendSetControllerServiceWorker(bool notify_controllerchange);
// Called when this container host's controller has been terminated and doomed
// due to an exceptional condition like it could no longer be read from the
// script cache.
void NotifyControllerLost();
// Returns an object info representing |registration|. The object info holds a
// Mojo connection to the ServiceWorkerRegistrationObjectHost for the
// |registration| to ensure the host stays alive while the object info is
// alive. A new ServiceWorkerRegistrationObjectHost instance is created if one
// can not be found in |registration_object_hosts_|.
//
// NOTE: The registration object info should be sent over Mojo in the same
// task with calling this method. Otherwise, some Mojo calls to
// blink::mojom::ServiceWorkerRegistrationObject or
// blink::mojom::ServiceWorkerObject may happen before establishing the
// connections, and they'll end up with crashes.
blink::mojom::ServiceWorkerRegistrationObjectInfoPtr
CreateServiceWorkerRegistrationObjectInfo(
scoped_refptr<ServiceWorkerRegistration> registration);
// Removes the ServiceWorkerRegistrationObjectHost corresponding to
// |registration_id|.
void RemoveServiceWorkerRegistrationObjectHost(int64_t registration_id);
// For service worker execution contexts.
// Returns an object info representing |self.serviceWorker|. The object
// info holds a Mojo connection to the ServiceWorkerObjectHost for the
// |serviceWorker| to ensure the host stays alive while the object info is
// alive. See documentation.
blink::mojom::ServiceWorkerObjectInfoPtr CreateServiceWorkerObjectInfoToSend(
scoped_refptr<ServiceWorkerVersion> version);
// Returns a ServiceWorkerObjectHost instance for |version| for this
// container host. A new instance is created if one does not already exist.
// ServiceWorkerObjectHost will have an ownership of the |version|.
base::WeakPtr<ServiceWorkerObjectHost> GetOrCreateServiceWorkerObjectHost(
scoped_refptr<ServiceWorkerVersion> version);
// Removes the ServiceWorkerObjectHost corresponding to |version_id|.
void RemoveServiceWorkerObjectHost(int64_t version_id);
// Returns true if this container host is for a service worker.
bool IsContainerForServiceWorker() const;
// Returns true if this container host is for a service worker client.
bool IsContainerForClient() const;
// Returns the client type of this container host. Can only be called when
// IsContainerForClient() is true.
blink::mojom::ServiceWorkerClientType GetClientType() const;
// Returns true if this container host is specifically for a window client.
bool IsContainerForWindowClient() const;
// Returns true if this container host is specifically for a worker client.
bool IsContainerForWorkerClient() const;
// Returns the client info for this container host.
ServiceWorkerClientInfo GetServiceWorkerClientInfo() const;
// For service worker window clients. Called when the navigation is ready to
// commit. Updates this host with information about the frame committed to.
// After this is called, is_response_committed() and is_execution_ready()
// return true.
void OnBeginNavigationCommit(
int container_process_id,
int container_frame_id,
const network::CrossOriginEmbedderPolicy& cross_origin_embedder_policy,
mojo::PendingRemote<network::mojom::CrossOriginEmbedderPolicyReporter>
coep_reporter,
ukm::SourceId document_ukm_source_id);
// For service worker window clients. Called after the navigation commits to a
// render frame host. At this point, the previous ServiceWorkerContainerHost
// for that render frame host no longer exists.
void OnEndNavigationCommit();
// For service worker clients that are shared workers or dedicated workers.
// Called when the web worker main script resource has finished loading.
// Updates this host with information about the worker.
// After this is called, is_response_committed() and is_execution_ready()
// return true.
void CompleteWebWorkerPreparation(
const network::CrossOriginEmbedderPolicy& cross_origin_embedder_policy,
ukm::SourceId worker_ukm_source_id);
// Sets |url_|, |site_for_cookies_| and |top_frame_origin_|. For service
// worker clients, updates the client uuid if it's a cross-origin transition.
void UpdateUrls(const GURL& url,
const net::SiteForCookies& site_for_cookies,
const base::Optional<url::Origin>& top_frame_origin);
// For service worker clients. Makes this client be controlled by
// |registration|'s active worker, or makes this client be not
// controlled if |registration| is null. If |notify_controllerchange| is true,
// instructs the renderer to dispatch a 'controllerchange' event.
void SetControllerRegistration(
scoped_refptr<ServiceWorkerRegistration> controller_registration,
bool notify_controllerchange);
// For service worker clients. Similar to EnsureControllerServiceWorker, but
// this returns a bound Mojo ptr which is supposed to be sent to clients. The
// controller ptr passed to the clients will be used to intercept requests
// from them.
// It is invalid to call this when controller_ is null.
//
// This method can be called in one of the following cases:
//
// - During navigation, right after a request handler for the main resource
// has found the matching registration and has started the worker.
// - When a controller is updated by UpdateController() (e.g.
// by OnSkippedWaiting() or SetControllerRegistration()).
// In some cases the controller worker may not be started yet.
//
// This may return nullptr if the controller service worker does not have a
// fetch handler, i.e. when the renderer does not need the controller ptr.
//
// WARNING:
// Unlike EnsureControllerServiceWorker, this method doesn't guarantee that
// the controller worker is running because this method can be called in some
// situations where the worker isn't running yet. When the returned ptr is
// stored somewhere and intended to use later, clients need to make sure
// that the worker is eventually started to use the ptr.
// Currently all the callsites do this, i.e. they start the worker before
// or after calling this, but there's no mechanism to prevent future breakage.
// TODO(crbug.com/827935): Figure out a way to prevent misuse of this method.
// TODO(crbug.com/827935): Make sure the connection error handler fires in
// ControllerServiceWorkerConnector (so that it can correctly call
// EnsureControllerServiceWorker later) if the worker gets killed before
// events are dispatched.
//
// TODO(kinuko): revisit this if we start to use the ControllerServiceWorker
// for posting messages.
// TODO(hayato): Return PendingRemote, instead of Remote. Binding to Remote
// as late as possible is more idiomatic for new Mojo types.
mojo::Remote<blink::mojom::ControllerServiceWorker>
GetRemoteControllerServiceWorker();
// |registration| claims the client (document, dedicated worker when
// PlzDedicatedWorker is enabled, or shared worker) to be controlled.
void ClaimedByRegistration(
scoped_refptr<ServiceWorkerRegistration> registration);
// The URL of this context. For service worker clients, this is the document
// URL (for documents) or script URL (for workers). For service worker
// execution contexts, this is the script URL.
//
// For clients, url() may be empty if loading has not started, or our custom
// loading handler didn't see the load (because e.g. another handler did
// first, or the initial request URL was such that
// OriginCanAccessServiceWorkers returned false).
//
// The URL may also change on redirects during loading. Once
// is_response_committed() is true, the URL should no longer change.
const GURL& url() const { return url_; }
// Representing the first party for cookies, if any, for this context. See
// |URLRequest::site_for_cookies()| for details.
// For service worker execution contexts, site_for_cookies() always
// corresponds to the service worker script URL.
const net::SiteForCookies& site_for_cookies() const {
return site_for_cookies_;
}
// The URL representing the first-party site for this context.
// For service worker execution contexts, top_frame_origin() always
// returns the origin of the service worker scope's URL.
// For shared worker it is the origin of the document that created the worker.
// For dedicated worker it is the top-frame origin of the document that owns
// the worker.
base::Optional<url::Origin> top_frame_origin() const {
return top_frame_origin_;
}
// Calls ContentBrowserClient::AllowServiceWorker(). Returns true if content
// settings allows service workers to run at |scope|. If this container is for
// a window client, the check involves the topmost frame url as well as
// |scope|, and may display tab-level UI.
// If non-empty, |script_url| is the script the service worker will run.
bool AllowServiceWorker(const GURL& scope, const GURL& script_url);
// Returns whether this container host is secure enough to have a service
// worker controller.
// Analogous to Blink's Document::IsSecureContext. Because of how service
// worker intercepts main resource requests, this check must be done
// browser-side once the URL is known (see comments in
// ServiceWorkerNetworkProviderForFrame::Create). This function uses
// |url_| and |is_parent_frame_secure_| to determine context security, so they
// must be set properly before calling this function.
bool IsEligibleForServiceWorkerController() const;
// For service worker clients. True if the response for the main resource load
// was committed to the renderer. When this is false, the client's URL may
// still change due to redirects.
bool is_response_committed() const;
// For service worker clients. |callback| is called when this client becomes
// execution ready or if it is destroyed first.
void AddExecutionReadyCallback(ExecutionReadyCallback callback);
// For service worker clients. True if the client is execution ready and
// therefore can be exposed to JavaScript. Execution ready implies response
// committed.
// https://html.spec.whatwg.org/multipage/webappapis.html#concept-environment-execution-ready-flag
bool is_execution_ready() const;
const base::UnguessableToken& fetch_request_window_id() const {
return fetch_request_window_id_;
}
base::TimeTicks create_time() const { return create_time_; }
int process_id() const { return process_id_; }
int frame_id() const { return frame_id_; }
int frame_tree_node_id() const { return client_info_->GetFrameTreeNodeId(); }
// For service worker clients.
const std::string& client_uuid() const;
// For service worker clients. Describes whether the client has a controller
// and if it has a fetch event handler.
blink::mojom::ControllerServiceWorkerMode GetControllerMode() const;
// For service worker clients. Returns this client's controller.
ServiceWorkerVersion* controller() const;
// For service worker clients. Returns this client's controller's
// registration.
ServiceWorkerRegistration* controller_registration() const;
// For service worker execution contexts.
void set_service_worker_host(ServiceWorkerHost* service_worker_host);
ServiceWorkerHost* service_worker_host();
// BackForwardCache:
// For service worker clients that are windows.
bool IsInBackForwardCache() const;
void EvictFromBackForwardCache(
BackForwardCacheMetrics::NotRestoredReason reason);
// Called when this container host's frame goes into BackForwardCache.
void OnEnterBackForwardCache();
// Called when a frame gets restored from BackForwardCache. Note that a
// BackForwardCached frame can be deleted while in the cache but in this case
// OnRestoreFromBackForwardCache will not be called.
void OnRestoreFromBackForwardCache();
bool navigation_commit_ended() const { return navigation_commit_ended_; }
void EnterBackForwardCacheForTesting() { is_in_back_forward_cache_ = true; }
void LeaveBackForwardCacheForTesting() { is_in_back_forward_cache_ = false; }
// Returns the origin of this container host.
// Note that you must use this function instead of retrieving the origin from
// url(). That can be invalid when this container host is created for a blob
// URL context. See comments on GetUrlForScopeMatch() for details.
const GURL GetOrigin() const;
// For service worker clients. Returns the URL that is used for scope matching
// algorithm. This can be different from url() in the case of blob URL
// workers. In that case, url() may be like "blob://https://a.test" and the
// scope matching URL is "https://a.test", inherited from the parent container
// host.
const GURL& GetUrlForScopeMatch() const;
// For service worker clients that are dedicated workers. Inherits the
// controller of the creator document or worker. Used when the client was
// created with a blob URL.
void InheritControllerFrom(ServiceWorkerContainerHost& creator_host,
const GURL& blob_url);
base::WeakPtr<ServiceWorkerContainerHost> GetWeakPtr();
ukm::SourceId ukm_source_id() const { return ukm_source_id_; }
private:
friend class ServiceWorkerContainerHostTest;
friend class service_worker_object_host_unittest::ServiceWorkerObjectHostTest;
FRIEND_TEST_ALL_PREFIXES(ServiceWorkerJobTest, Unregister);
FRIEND_TEST_ALL_PREFIXES(ServiceWorkerJobTest, RegisterDuplicateScript);
FRIEND_TEST_ALL_PREFIXES(ServiceWorkerUpdateJobTest,
RegisterWithDifferentUpdateViaCache);
FRIEND_TEST_ALL_PREFIXES(BackgroundSyncManagerTest,
RegisterWithoutLiveSWRegistration);
// Syncs matching registrations with live registrations.
void SyncMatchingRegistrations();
#if DCHECK_IS_ON()
bool IsMatchingRegistration(ServiceWorkerRegistration* registration) const;
#endif // DCHECK_IS_ON()
// Discards all references to matching registrations.
void RemoveAllMatchingRegistrations();
void ReturnRegistrationForReadyIfNeeded();
// Sets |execution_ready_| and runs execution ready callbacks.
void SetExecutionReady();
void RunExecutionReadyCallbacks();
// For service worker clients. The flow is kInitial -> kResponseCommitted ->
// kExecutionReady.
//
// - kInitial: The initial phase.
// - kResponseCommitted: The response for the main resource has been
// committed to the renderer. This client's URL should no longer change.
// - kExecutionReady: This client can be exposed to JavaScript as a Client
// object.
enum class ClientPhase { kInitial, kResponseCommitted, kExecutionReady };
void TransitionToClientPhase(ClientPhase new_phase);
// Sets the controller to |controller_registration_->active_version()| or null
// if there is no associated registration.
//
// If |notify_controllerchange| is true, instructs the renderer to dispatch a
// 'controller' change event.
void UpdateController(bool notify_controllerchange);
#if DCHECK_IS_ON()
void CheckControllerConsistency(bool should_crash) const;
#endif // DCHECK_IS_ON()
// Callback for ServiceWorkerVersion::RunAfterStartWorker()
void StartControllerComplete(
mojo::PendingReceiver<blink::mojom::ControllerServiceWorker> receiver,
blink::ServiceWorkerStatusCode status);
// Callback for ServiceWorkerContextCore::RegisterServiceWorker().
void RegistrationComplete(const GURL& script_url,
const GURL& scope,
RegisterCallback callback,
int64_t trace_id,
mojo::ReportBadMessageCallback bad_message_callback,
blink::ServiceWorkerStatusCode status,
const std::string& status_message,
int64_t registration_id);
// Callback for ServiceWorkerRegistry::FindRegistrationForClientUrl().
void GetRegistrationComplete(
GetRegistrationCallback callback,
int64_t trace_id,
blink::ServiceWorkerStatusCode status,
scoped_refptr<ServiceWorkerRegistration> registration);
// Callback for ServiceWorkerStorage::GetRegistrationsForOrigin().
void GetRegistrationsComplete(
GetRegistrationsCallback callback,
int64_t trace_id,
blink::ServiceWorkerStatusCode status,
const std::vector<scoped_refptr<ServiceWorkerRegistration>>&
registrations);
bool IsValidGetRegistrationMessage(const GURL& client_url,
std::string* out_error) const;
bool IsValidGetRegistrationsMessage(std::string* out_error) const;
bool IsValidGetRegistrationForReadyMessage(std::string* out_error) const;
// Perform common checks that need to run before ContainerHost methods that
// come from a child process are handled.
// |scope| is checked if it is allowed to run a service worker.
// If non-empty, |script_url| is the script associated with the service
// worker.
// Returns true if all checks have passed.
// If anything looks wrong |callback| will run with an error
// message prefixed by |error_prefix| and |args|, and false is returned.
template <typename CallbackType, typename... Args>
bool CanServeContainerHostMethods(CallbackType* callback,
const GURL& scope,
const GURL& script_url,
const char* error_prefix,
Args... args);
base::WeakPtr<ServiceWorkerContextCore> context_;
// The time when the container host is created.
const base::TimeTicks create_time_;
// See comments for the getter functions.
GURL url_;
net::SiteForCookies site_for_cookies_;
base::Optional<url::Origin> top_frame_origin_;
// Contains all ServiceWorkerRegistrationObjectHost instances corresponding to
// the service worker registration JavaScript objects for the hosted execution
// context (service worker global scope or service worker client) in the
// renderer process.
std::map<int64_t /* registration_id */,
std::unique_ptr<ServiceWorkerRegistrationObjectHost>>
registration_object_hosts_;
// Contains all ServiceWorkerObjectHost instances corresponding to
// the service worker JavaScript objects for the hosted execution
// context (service worker global scope or service worker client) in the
// renderer process.
std::map<int64_t /* version_id */, std::unique_ptr<ServiceWorkerObjectHost>>
service_worker_object_hosts_;
// For all service worker clients --------------------------------------------
// A GUID that is web-exposed as FetchEvent.clientId.
std::string client_uuid_;
// |is_parent_frame_secure_| is false if the container host is created for a
// document whose parent frame is not secure. This doesn't mean the document
// is necessarily an insecure context, because the document may have a URL
// whose scheme is granted an exception that allows bypassing the ancestor
// secure context check. If the container is not created for a document, or
// the document does not have a parent frame, is_parent_frame_secure_| is
// true.
const bool is_parent_frame_secure_ = true;
// The phase that this container host is on.
ClientPhase client_phase_ = ClientPhase::kInitial;
// The ID of the process where the container lives. For window clients, this
// is set on response commit, while it is set during initialization for worker
// clients.
int process_id_ = ChildProcessHost::kInvalidUniqueID;
// Callbacks to run upon transition to kExecutionReady.
std::vector<ExecutionReadyCallback> execution_ready_callbacks_;
// The ready() promise is only allowed to be created once.
// |get_ready_callback_| has three states:
// 1. |get_ready_callback_| is null when ready() has not yet been called.
// 2. |*get_ready_callback_| is a valid OnceCallback after ready() has been
// called and the callback has not yet been run.
// 3. |*get_ready_callback_| is a null OnceCallback after the callback has
// been run.
std::unique_ptr<GetRegistrationForReadyCallback> get_ready_callback_;
// The controller service worker (i.e., ServiceWorkerContainer#controller) and
// its registration. The controller is typically the same as the
// registration's active version, but during algorithms such as the update,
// skipWaiting(), and claim() steps, the active version and controller may
// temporarily differ. For example, to perform skipWaiting(), the
// registration's active version is updated first and then the container
// host's controller is updated to match it.
scoped_refptr<ServiceWorkerVersion> controller_;
scoped_refptr<ServiceWorkerRegistration> controller_registration_;
// Keyed by registration scope URL length.
using ServiceWorkerRegistrationMap =
std::map<size_t, scoped_refptr<ServiceWorkerRegistration>>;
// Contains all living registrations whose scope this client's URL starts
// with, used for .ready and claim(). It is empty if
// IsEligibleForServiceWorkerController() is false. See also
// AddMatchingRegistration().
ServiceWorkerRegistrationMap matching_registrations_;
// The service workers in the chain of redirects during the main resource
// request for this client. These workers should be updated "soon". See
// AddServiceWorkerToUpdate() documentation.
class PendingUpdateVersion;
base::flat_set<PendingUpdateVersion> versions_to_update_;
// Mojo endpoint which will be be sent to the service worker just before
// the response is committed, where |cross_origin_embedder_policy_| is ready.
// We need to store this here because navigation code depends on having a
// mojo::Remote<ControllerServiceWorker> for making a SubresourceLoaderParams,
// which is created before the response header is ready.
mojo::PendingReceiver<blink::mojom::ControllerServiceWorker>
pending_controller_receiver_;
// Container host receivers other than the original |receiver_|. These include
// receivers used from (dedicated or shared) worker threads, or from
// ServiceWorkerSubresourceLoaderFactory.
mojo::ReceiverSet<blink::mojom::ServiceWorkerContainerHost>
additional_receivers_;
// |container_| is the remote renderer-side ServiceWorkerContainer that |this|
// is hosting.
mojo::AssociatedRemote<blink::mojom::ServiceWorkerContainer> container_;
// The type of client.
const base::Optional<ServiceWorkerClientInfo> client_info_;
// The source id of the client's ExecutionContext, set on response commit.
ukm::SourceId ukm_source_id_ = ukm::kInvalidSourceId;
// The URL used for service worker scope matching. It is empty except in the
// case of a service worker client with a blob URL.
GURL scope_match_url_for_blob_client_;
// For window clients only ---------------------------------------------------
// A token used internally to identify this context in requests. Corresponds
// to the Fetch specification's concept of a request's associated window:
// https://fetch.spec.whatwg.org/#concept-request-window. This gets reset on
// redirects, unlike |client_uuid_|.
//
// TODO(falken): Consider using this for |client_uuid_| as well. We can't
// right now because this gets reset on redirects, and potentially sites rely
// on the GUID format.
base::UnguessableToken fetch_request_window_id_;
// The ID of the RenderFrameHost used for the navigation. Set on response
// commit.
int frame_id_ = MSG_ROUTING_NONE;
// The embedder policy of the client. Set on response commit.
base::Optional<network::CrossOriginEmbedderPolicy>
cross_origin_embedder_policy_;
// An endpoint connected to the COEP reporter. A clone of this connection is
// passed to the service worker. Bound on response commit.
mojo::Remote<network::mojom::CrossOriginEmbedderPolicyReporter>
coep_reporter_;
// Indicates if this container host is in the back-forward cache.
//
// TODO(yuzus): This bit will be unnecessary once ServiceWorkerContainerHost
// and RenderFrameHost have the same lifetime.
bool is_in_back_forward_cache_ = false;
// Indicates if OnEndNavigationCommit() was called on this container host.
bool navigation_commit_ended_ = false;
// For service worker execution contexts -------------------------------------
// The ServiceWorkerHost that owns |this|.
ServiceWorkerHost* service_worker_host_ = nullptr;
base::WeakPtrFactory<ServiceWorkerContainerHost> weak_factory_{this};
};
} // namespace content
#endif // CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_CONTAINER_HOST_H_