#ifndef CONTENT_BROWSER_SERVICE_WORKER_EMBEDDED_WORKER_INSTANCE_H_
#define CONTENT_BROWSER_SERVICE_WORKER_EMBEDDED_WORKER_INSTANCE_H_
#include <stdint.h>
#include <memory>
#include <string>
#include "base/check_op.h"
#include "base/functional/callback_forward.h"
#include "base/gtest_prod_util.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
#include "base/unguessable_token.h"
#include "components/services/storage/public/cpp/buckets/bucket_locator.h"
#include "content/browser/service_worker/service_worker_metrics.h"
#include "content/common/content_export.h"
#include "content/public/browser/content_browser_client.h"
#include "mojo/public/cpp/bindings/associated_receiver.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "mojo/public/cpp/bindings/self_owned_receiver.h"
#include "services/network/public/mojom/client_security_state.mojom-forward.h"
#include "third_party/blink/public/common/service_worker/embedded_worker_status.h"
#include "third_party/blink/public/common/service_worker/service_worker_status_code.h"
#include "third_party/blink/public/common/tokens/tokens.h"
#include "third_party/blink/public/mojom/cache_storage/cache_storage.mojom.h"
#include "third_party/blink/public/mojom/service_worker/controller_service_worker.mojom.h"
#include "third_party/blink/public/mojom/service_worker/embedded_worker.mojom.h"
#include "third_party/blink/public/mojom/service_worker/service_worker.mojom.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_installed_scripts_manager.mojom.h"
#include "third_party/blink/public/mojom/usb/web_usb_service.mojom-forward.h"
#include "third_party/blink/public/mojom/worker/subresource_loader_updater.mojom.h"
#include "url/gurl.h"
#if !BUILDFLAG(IS_ANDROID)
#include "third_party/blink/public/mojom/hid/hid.mojom-forward.h"
#endif
namespace content {
class CrossOriginEmbedderPolicyReporter;
class DocumentIsolationPolicyReporter;
class RenderProcessHost;
class ServiceWorkerContentSettingsProxyImpl;
class ServiceWorkerContextCore;
class ServiceWorkerVersion;
class StoragePartitionImpl;
namespace service_worker_new_script_loader_unittest {
class ServiceWorkerNewScriptLoaderTest;
FORWARD_DECLARE_TEST(ServiceWorkerNewScriptLoaderTest, AccessedNetwork);
}
class CONTENT_EXPORT EmbeddedWorkerInstance
: public blink::mojom::EmbeddedWorkerInstanceHost {
public:
class DevToolsProxy;
using StatusCallback =
base::OnceCallback<void(blink::ServiceWorkerStatusCode)>;
enum StartingPhase {
NOT_STARTING = 0,
ALLOCATING_PROCESS = 1,
SENT_START_WORKER = 3,
SCRIPT_DOWNLOADING = 4,
SCRIPT_LOADED = 5,
SCRIPT_STREAMING = 10,
SCRIPT_EVALUATION = 11,
STARTING_PHASE_MAX_VALUE,
};
class Listener {
public:
virtual ~Listener() {}
virtual void OnStarting() {}
virtual void OnProcessAllocated() {}
virtual void OnRegisteredToDevToolsManager() {}
virtual void OnStartWorkerMessageSent() {}
virtual void OnScriptLoaded() {}
virtual void OnScriptEvaluationStart() {}
virtual void OnStarted(
blink::mojom::ServiceWorkerStartStatus status,
blink::mojom::ServiceWorkerFetchHandlerType fetch_handler_type,
bool has_hid_event_handlers,
bool has_usb_event_handlers) {}
virtual void OnStopping() {}
virtual void OnStopped(blink::EmbeddedWorkerStatus old_status) {}
virtual void OnDetached(blink::EmbeddedWorkerStatus old_status) {}
virtual void OnReportException(const std::u16string& error_message,
int line_number,
int column_number,
const GURL& source_url) {}
virtual void OnReportConsoleMessage(
blink::mojom::ConsoleMessageSource source,
blink::mojom::ConsoleMessageLevel message_level,
const std::u16string& message,
int line_number,
const GURL& source_url) {}
};
explicit EmbeddedWorkerInstance(ServiceWorkerVersion* owner_version);
EmbeddedWorkerInstance(const EmbeddedWorkerInstance&) = delete;
EmbeddedWorkerInstance& operator=(const EmbeddedWorkerInstance&) = delete;
~EmbeddedWorkerInstance() override;
void Start(blink::mojom::EmbeddedWorkerStartParamsPtr params,
StatusCallback sent_start_callback);
void Stop();
void StopIfNotAttachedToDevTools();
int embedded_worker_id() const { return embedded_worker_id_; }
blink::EmbeddedWorkerStatus status() const { return status_; }
StartingPhase starting_phase() const {
DCHECK_EQ(blink::EmbeddedWorkerStatus::kStarting, status());
return starting_phase_;
}
int restart_count() const { return restart_count_; }
bool pause_initializing_global_scope() const {
return pause_initializing_global_scope_;
}
void SetPauseInitializingGlobalScope();
void ResumeInitializingGlobalScope();
int process_id() const;
int thread_id() const { return thread_id_; }
int worker_devtools_agent_route_id() const;
base::UnguessableToken WorkerDevtoolsId() const;
void AddObserver(Listener* listener);
void RemoveObserver(Listener* listener);
void SetDevToolsAttached(bool attached);
bool devtools_attached() const { return devtools_attached_; }
bool network_accessed_for_script() const {
return network_accessed_for_script_;
}
ServiceWorkerMetrics::StartSituation start_situation() const {
DCHECK(status() == blink::EmbeddedWorkerStatus::kStarting ||
status() == blink::EmbeddedWorkerStatus::kRunning);
return start_situation_;
}
void OnNetworkAccessedForScriptLoad();
void OnWorkerVersionInstalled();
void OnWorkerVersionDoomed();
static std::string StatusToString(blink::EmbeddedWorkerStatus status);
static std::string StartingPhaseToString(StartingPhase phase);
void Detach();
void UpdateForegroundPriority();
void UpdateLoaderFactories(
std::unique_ptr<blink::PendingURLLoaderFactoryBundle> script_bundle,
std::unique_ptr<blink::PendingURLLoaderFactoryBundle> subresource_bundle);
void BindCacheStorage(
mojo::PendingReceiver<blink::mojom::CacheStorage> receiver,
const storage::BucketLocator& bucket_locator);
#if !BUILDFLAG(IS_ANDROID)
void BindHidService(const url::Origin& origin,
mojo::PendingReceiver<blink::mojom::HidService> receiver);
#endif
void BindUsbService(
const url::Origin& origin,
mojo::PendingReceiver<blink::mojom::WebUsbService> receiver);
base::WeakPtr<EmbeddedWorkerInstance> AsWeakPtr();
static std::unique_ptr<blink::PendingURLLoaderFactoryBundle>
CreateFactoryBundle(
RenderProcessHost* rph,
int routing_id,
const blink::StorageKey& storage_key,
network::mojom::ClientSecurityStatePtr client_security_state,
mojo::PendingRemote<network::mojom::CrossOriginEmbedderPolicyReporter>
coep_reporter,
mojo::PendingRemote<network::mojom::DocumentIsolationPolicyReporter>
dip_reporter,
ContentBrowserClient::URLLoaderFactoryType factory_type,
const std::string& devtools_worker_token);
mojo::PendingRemote<network::mojom::CrossOriginEmbedderPolicyReporter>
GetCoepReporter();
mojo::PendingRemote<network::mojom::DocumentIsolationPolicyReporter>
GetDipReporter();
private:
typedef base::ObserverList<Listener>::Unchecked ListenerList;
struct StartInfo;
class WorkerProcessHandle;
friend class EmbeddedWorkerInstanceTestHarness;
FRIEND_TEST_ALL_PREFIXES(EmbeddedWorkerInstanceTest, StartAndStop);
FRIEND_TEST_ALL_PREFIXES(EmbeddedWorkerInstanceTest, DetachDuringStart);
FRIEND_TEST_ALL_PREFIXES(EmbeddedWorkerInstanceTest, StopDuringStart);
FRIEND_TEST_ALL_PREFIXES(service_worker_new_script_loader_unittest::
ServiceWorkerNewScriptLoaderTest,
AccessedNetwork);
void OnProcessAllocated(std::unique_ptr<WorkerProcessHandle> handle,
ServiceWorkerMetrics::StartSituation start_situation);
void OnRegisteredToDevToolsManager(
std::unique_ptr<DevToolsProxy> devtools_proxy);
void SendStartWorker(blink::mojom::EmbeddedWorkerStartParamsPtr params);
void RequestTermination(RequestTerminationCallback callback) override;
void CountFeature(blink::mojom::WebFeature feature) override;
void OnReadyForInspection(
mojo::PendingRemote<blink::mojom::DevToolsAgent>,
mojo::PendingReceiver<blink::mojom::DevToolsAgentHost>) override;
void OnScriptLoaded() override;
void OnScriptEvaluationStart() override;
void OnStarted(
blink::mojom::ServiceWorkerStartStatus status,
blink::mojom::ServiceWorkerFetchHandlerType fetch_handler_type,
bool has_hid_event_handlers,
bool has_usb_event_handlers,
int thread_id,
blink::mojom::EmbeddedWorkerStartTimingPtr start_timing) override;
void OnStopped() override;
void OnReportException(const std::u16string& error_message,
int line_number,
int column_number,
const GURL& source_url) override;
void OnReportConsoleMessage(blink::mojom::ConsoleMessageSource source,
blink::mojom::ConsoleMessageLevel message_level,
const std::u16string& message,
int line_number,
const GURL& source_url) override;
void ReleaseProcess();
void OnSetupFailed(StatusCallback callback,
blink::ServiceWorkerStatusCode status);
void NotifyForegroundServiceWorkerAdded();
void NotifyForegroundServiceWorkerRemoved();
mojo::PendingRemote<network::mojom::URLLoaderFactory>
MakeScriptLoaderFactoryRemote(
std::unique_ptr<blink::PendingURLLoaderFactoryBundle> script_bundle);
void BindCacheStorageInternal();
mojo::PendingRemote<network::mojom::CrossOriginEmbedderPolicyReporter>
GetCoepReporterInternal(StoragePartitionImpl* storage_partition);
mojo::PendingRemote<network::mojom::DocumentIsolationPolicyReporter>
GetDipReporterInternal(StoragePartitionImpl* storage_partition);
base::WeakPtr<ServiceWorkerContextCore> context_;
raw_ptr<ServiceWorkerVersion> owner_version_;
const int embedded_worker_id_;
blink::EmbeddedWorkerStatus status_;
StartingPhase starting_phase_;
int restart_count_;
bool pause_initializing_global_scope_ = false;
std::unique_ptr<EmbeddedWorkerInstance::WorkerProcessHandle> process_handle_;
int thread_id_;
mojo::Remote<blink::mojom::EmbeddedWorkerInstanceClient> client_;
mojo::AssociatedReceiver<EmbeddedWorkerInstanceHost> instance_host_receiver_{
this};
bool devtools_attached_;
bool network_accessed_for_script_;
bool foreground_notified_;
ListenerList listener_list_;
std::unique_ptr<DevToolsProxy> devtools_proxy_;
std::unique_ptr<StartInfo> inflight_start_info_;
ServiceWorkerMetrics::StartSituation start_situation_ =
ServiceWorkerMetrics::StartSituation::UNKNOWN;
std::unique_ptr<ServiceWorkerContentSettingsProxyImpl> content_settings_;
mojo::SelfOwnedReceiverRef<network::mojom::URLLoaderFactory>
script_loader_factory_;
mojo::Remote<blink::mojom::SubresourceLoaderUpdater>
subresource_loader_updater_;
struct CacheStorageRequest {
CacheStorageRequest(
mojo::PendingReceiver<blink::mojom::CacheStorage> receiver,
storage::BucketLocator bucket);
CacheStorageRequest(CacheStorageRequest&& other);
~CacheStorageRequest();
mojo::PendingReceiver<blink::mojom::CacheStorage> receiver;
storage::BucketLocator bucket;
};
std::vector<CacheStorageRequest> pending_cache_storage_requests_;
std::unique_ptr<CrossOriginEmbedderPolicyReporter> coep_reporter_;
mojo::PendingReceiver<blink::mojom::ReportingObserver>
coep_reporting_observer_receiver_;
std::unique_ptr<DocumentIsolationPolicyReporter> dip_reporter_;
mojo::PendingReceiver<blink::mojom::ReportingObserver>
dip_reporting_observer_receiver_;
bool in_dtor_{false};
base::WeakPtrFactory<EmbeddedWorkerInstance> weak_factory_{this};
};
}
#endif