| Index: content/browser/service_worker/service_worker_provider_host.cc
|
| diff --git a/content/browser/service_worker/service_worker_provider_host.cc b/content/browser/service_worker/service_worker_provider_host.cc
|
| index 34be8dd0c8f7916e44abfbc074dc82f235056dd3..7e9f223e1510e1f532647545da50c3992a40c0d2 100644
|
| --- a/content/browser/service_worker/service_worker_provider_host.cc
|
| +++ b/content/browser/service_worker/service_worker_provider_host.cc
|
| @@ -19,6 +19,7 @@
|
| #include "content/browser/service_worker/service_worker_handle.h"
|
| #include "content/browser/service_worker/service_worker_registration_handle.h"
|
| #include "content/browser/service_worker/service_worker_version.h"
|
| +#include "content/browser/url_loader_factory_getter.h"
|
| #include "content/common/resource_request_body_impl.h"
|
| #include "content/common/service_worker/service_worker_messages.h"
|
| #include "content/common/service_worker/service_worker_types.h"
|
| @@ -31,15 +32,19 @@
|
| #include "content/public/common/origin_util.h"
|
| #include "mojo/public/cpp/bindings/strong_associated_binding.h"
|
| #include "net/base/url_util.h"
|
| +#include "storage/browser/blob/blob_storage_context.h"
|
|
|
| namespace content {
|
|
|
| namespace {
|
|
|
| -// PlzNavigate
|
| -// Next ServiceWorkerProviderHost ID for navigations, starts at -2 and keeps
|
| -// going down.
|
| -int g_next_navigation_provider_id = -2;
|
| +// Provider host for navigation with PlzNavigate or service worker's context is
|
| +// created on the browser side. This function provides the next
|
| +// ServiceWorkerProviderHost ID for them, starts at -2 and keeps going down.
|
| +int NextBrowserProvidedProviderId() {
|
| + static int g_next_browser_provided_provider_id = -2;
|
| + return g_next_browser_provided_provider_id--;
|
| +}
|
|
|
| // A request handler derivative used to handle navigation requests when
|
| // skip_service_worker flag is set. It tracks the document URL and sets the url
|
| @@ -59,10 +64,9 @@ class ServiceWorkerURLTrackingRequestHandler
|
| ~ServiceWorkerURLTrackingRequestHandler() override {}
|
|
|
| // Called via custom URLRequestJobFactory.
|
| - net::URLRequestJob* MaybeCreateJob(
|
| - net::URLRequest* request,
|
| - net::NetworkDelegate* /* network_delegate */,
|
| - ResourceContext* /* resource_context */) override {
|
| + net::URLRequestJob* MaybeCreateJob(net::URLRequest* request,
|
| + net::NetworkDelegate*,
|
| + ResourceContext*) override {
|
| // |provider_host_| may have been deleted when the request is resumed.
|
| if (!provider_host_)
|
| return nullptr;
|
| @@ -96,6 +100,152 @@ void RemoveProviderHost(base::WeakPtr<ServiceWorkerContextCore> context,
|
| context->RemoveProviderHost(process_id, provider_id);
|
| }
|
|
|
| +// Used by a Service Worker for script loading (only during installation,
|
| +// eventually). For now this is just a proxy loader for the network loader.
|
| +// TODO(kinuko): Implement this. Hook up the existing code in
|
| +// ServiceWorkerContextRequestHandler.
|
| +class ScriptURLLoader : public mojom::URLLoader, public mojom::URLLoaderClient {
|
| + public:
|
| + ScriptURLLoader(
|
| + int32_t routing_id,
|
| + int32_t request_id,
|
| + uint32_t options,
|
| + const ResourceRequest& url_request,
|
| + mojom::URLLoaderClientPtr client,
|
| + base::WeakPtr<ServiceWorkerContextCore> context,
|
| + base::WeakPtr<ServiceWorkerProviderHost> provider_host,
|
| + base::WeakPtr<storage::BlobStorageContext> blob_storage_context,
|
| + scoped_refptr<URLLoaderFactoryGetter> loader_factory_getter,
|
| + const net::MutableNetworkTrafficAnnotationTag& traffic_annotation)
|
| + : network_client_binding_(this),
|
| + forwarding_client_(std::move(client)),
|
| + provider_host_(provider_host) {
|
| + mojom::URLLoaderClientPtr network_client;
|
| + network_client_binding_.Bind(mojo::MakeRequest(&network_client));
|
| + loader_factory_getter->GetNetworkFactory()->get()->CreateLoaderAndStart(
|
| + mojo::MakeRequest(&network_loader_), routing_id, request_id, options,
|
| + url_request, std::move(network_client), traffic_annotation);
|
| + }
|
| + ~ScriptURLLoader() override {}
|
| +
|
| + // mojom::URLLoader:
|
| + void FollowRedirect() override { network_loader_->FollowRedirect(); }
|
| + void SetPriority(net::RequestPriority priority,
|
| + int32_t intra_priority_value) override {
|
| + network_loader_->SetPriority(priority, intra_priority_value);
|
| + }
|
| +
|
| + // mojom::URLLoaderClient for simply proxying network:
|
| + void OnReceiveResponse(
|
| + const ResourceResponseHead& response_head,
|
| + const base::Optional<net::SSLInfo>& ssl_info,
|
| + mojom::DownloadedTempFilePtr downloaded_file) override {
|
| + if (provider_host_) {
|
| + // We don't have complete info here, but fill in what we have now.
|
| + // At least we need headers and SSL info.
|
| + net::HttpResponseInfo response_info;
|
| + response_info.headers = response_head.headers;
|
| + if (ssl_info.has_value())
|
| + response_info.ssl_info = *ssl_info;
|
| + response_info.was_fetched_via_spdy = response_head.was_fetched_via_spdy;
|
| + response_info.was_alpn_negotiated = response_head.was_alpn_negotiated;
|
| + response_info.alpn_negotiated_protocol =
|
| + response_head.alpn_negotiated_protocol;
|
| + response_info.connection_info = response_head.connection_info;
|
| + response_info.socket_address = response_head.socket_address;
|
| +
|
| + DCHECK(provider_host_->IsHostToRunningServiceWorker());
|
| + provider_host_->running_hosted_version()->SetMainScriptHttpResponseInfo(
|
| + response_info);
|
| + }
|
| + forwarding_client_->OnReceiveResponse(response_head, ssl_info,
|
| + std::move(downloaded_file));
|
| + }
|
| + void OnReceiveRedirect(const net::RedirectInfo& redirect_info,
|
| + const ResourceResponseHead& response_head) override {
|
| + forwarding_client_->OnReceiveRedirect(redirect_info, response_head);
|
| + }
|
| + void OnDataDownloaded(int64_t data_len, int64_t encoded_data_len) override {
|
| + forwarding_client_->OnDataDownloaded(data_len, encoded_data_len);
|
| + }
|
| + void OnUploadProgress(int64_t current_position,
|
| + int64_t total_size,
|
| + OnUploadProgressCallback ack_callback) override {
|
| + forwarding_client_->OnUploadProgress(current_position, total_size,
|
| + std::move(ack_callback));
|
| + }
|
| + void OnReceiveCachedMetadata(const std::vector<uint8_t>& data) override {
|
| + forwarding_client_->OnReceiveCachedMetadata(data);
|
| + }
|
| + void OnTransferSizeUpdated(int32_t transfer_size_diff) override {
|
| + forwarding_client_->OnTransferSizeUpdated(transfer_size_diff);
|
| + }
|
| + void OnStartLoadingResponseBody(
|
| + mojo::ScopedDataPipeConsumerHandle body) override {
|
| + forwarding_client_->OnStartLoadingResponseBody(std::move(body));
|
| + }
|
| + void OnComplete(const ResourceRequestCompletionStatus& status) override {
|
| + forwarding_client_->OnComplete(status);
|
| + }
|
| +
|
| + private:
|
| + mojom::URLLoaderAssociatedPtr network_loader_;
|
| + mojo::Binding<mojom::URLLoaderClient> network_client_binding_;
|
| + mojom::URLLoaderClientPtr forwarding_client_;
|
| + base::WeakPtr<ServiceWorkerProviderHost> provider_host_;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(ScriptURLLoader);
|
| +};
|
| +
|
| +// Created per one controller worker for script loading (only during
|
| +// installation, eventually). This is kept alive while
|
| +// ServiceWorkerNetworkProvider in the renderer process is alive.
|
| +// Used only when IsServicificationEnabled is true.
|
| +class ScriptURLLoaderFactory : public mojom::URLLoaderFactory {
|
| + public:
|
| + ScriptURLLoaderFactory(
|
| + base::WeakPtr<ServiceWorkerContextCore> context,
|
| + base::WeakPtr<ServiceWorkerProviderHost> provider_host,
|
| + base::WeakPtr<storage::BlobStorageContext> blob_storage_context,
|
| + scoped_refptr<URLLoaderFactoryGetter> loader_factory_getter)
|
| + : context_(context),
|
| + provider_host_(provider_host),
|
| + blob_storage_context_(blob_storage_context),
|
| + loader_factory_getter_(loader_factory_getter) {}
|
| + ~ScriptURLLoaderFactory() override {}
|
| +
|
| + // mojom::URLLoaderFactory:
|
| + void CreateLoaderAndStart(mojom::URLLoaderAssociatedRequest request,
|
| + int32_t routing_id,
|
| + int32_t request_id,
|
| + uint32_t options,
|
| + const ResourceRequest& url_request,
|
| + mojom::URLLoaderClientPtr client,
|
| + const net::MutableNetworkTrafficAnnotationTag&
|
| + traffic_annotation) override {
|
| + mojo::MakeStrongAssociatedBinding(
|
| + base::MakeUnique<ScriptURLLoader>(
|
| + routing_id, request_id, options, url_request, std::move(client),
|
| + context_, provider_host_, blob_storage_context_,
|
| + loader_factory_getter_, traffic_annotation),
|
| + std::move(request));
|
| + }
|
| +
|
| + void SyncLoad(int32_t routing_id,
|
| + int32_t request_id,
|
| + const ResourceRequest& request,
|
| + SyncLoadCallback callback) override {
|
| + NOTREACHED();
|
| + }
|
| +
|
| + private:
|
| + base::WeakPtr<ServiceWorkerContextCore> context_;
|
| + base::WeakPtr<ServiceWorkerProviderHost> provider_host_;
|
| + base::WeakPtr<storage::BlobStorageContext> blob_storage_context_;
|
| + scoped_refptr<URLLoaderFactoryGetter> loader_factory_getter_;
|
| + DISALLOW_COPY_AND_ASSIGN(ScriptURLLoaderFactory);
|
| +};
|
| +
|
| } // anonymous namespace
|
|
|
| ServiceWorkerProviderHost::OneShotGetReadyCallback::OneShotGetReadyCallback(
|
| @@ -114,18 +264,32 @@ ServiceWorkerProviderHost::PreCreateNavigationHost(
|
| bool are_ancestors_secure,
|
| const WebContentsGetter& web_contents_getter) {
|
| CHECK(IsBrowserSideNavigationEnabled());
|
| - // Generate a new browser-assigned id for the host.
|
| - int provider_id = g_next_navigation_provider_id--;
|
| auto host = base::WrapUnique(new ServiceWorkerProviderHost(
|
| ChildProcessHost::kInvalidUniqueID,
|
| - ServiceWorkerProviderHostInfo(provider_id, MSG_ROUTING_NONE,
|
| - SERVICE_WORKER_PROVIDER_FOR_WINDOW,
|
| - are_ancestors_secure),
|
| + ServiceWorkerProviderHostInfo(
|
| + NextBrowserProvidedProviderId(), MSG_ROUTING_NONE,
|
| + SERVICE_WORKER_PROVIDER_FOR_WINDOW, are_ancestors_secure),
|
| context, nullptr));
|
| host->web_contents_getter_ = web_contents_getter;
|
| return host;
|
| }
|
|
|
| +// static
|
| +std::unique_ptr<ServiceWorkerProviderHost>
|
| +ServiceWorkerProviderHost::PreCreateForController(
|
| + ServiceWorkerVersion* version,
|
| + base::WeakPtr<ServiceWorkerContextCore> context) {
|
| + auto host = base::WrapUnique(new ServiceWorkerProviderHost(
|
| + ChildProcessHost::kInvalidUniqueID,
|
| + ServiceWorkerProviderHostInfo(NextBrowserProvidedProviderId(),
|
| + MSG_ROUTING_NONE,
|
| + SERVICE_WORKER_PROVIDER_FOR_CONTROLLER,
|
| + true /* is_parent_frame_secure */),
|
| + context, nullptr));
|
| + host->SetHostedVersion(version);
|
| + return host;
|
| +}
|
| +
|
| // static
|
| std::unique_ptr<ServiceWorkerProviderHost> ServiceWorkerProviderHost::Create(
|
| int process_id,
|
| @@ -177,20 +341,27 @@ ServiceWorkerProviderHost::ServiceWorkerProviderHost(
|
| binding_(this) {
|
| DCHECK_NE(SERVICE_WORKER_PROVIDER_UNKNOWN, info_.type);
|
|
|
| - // PlzNavigate
|
| - CHECK(render_process_id != ChildProcessHost::kInvalidUniqueID ||
|
| - IsBrowserSideNavigationEnabled());
|
|
|
| if (info_.type == SERVICE_WORKER_PROVIDER_FOR_CONTROLLER) {
|
| - // Actual thread id is set when the service worker context gets started.
|
| + // Actual |render_process_id| will be set after choosing a process for the
|
| + // controller, and |render_thread id| will be set when the service worker
|
| + // context gets started.
|
| + DCHECK_EQ(ChildProcessHost::kInvalidUniqueID, render_process_id);
|
| render_thread_id_ = kInvalidEmbeddedWorkerThreadId;
|
| + } else {
|
| + // PlzNavigate
|
| + CHECK(render_process_id != ChildProcessHost::kInvalidUniqueID ||
|
| + IsBrowserSideNavigationEnabled());
|
| }
|
| +
|
| context_->RegisterProviderHostByClientID(client_uuid_, this);
|
|
|
| - // PlzNavigate
|
| - // |provider_| and |binding_| will be bound on CompleteNavigationInitialized.
|
| - if (IsBrowserSideNavigationEnabled()) {
|
| - DCHECK(!info.client_ptr_info.is_valid() && !info.host_request.is_pending());
|
| + // |client_| and |binding_| will be bound on CompleteNavigationInitialized
|
| + // (PlzNavigate) or on CompleteStartWorkerPreparation (providers for
|
| + // controller).
|
| + if (!info_.client_ptr_info.is_valid() && !info_.host_request.is_pending()) {
|
| + DCHECK(IsBrowserSideNavigationEnabled() ||
|
| + info_.type == SERVICE_WORKER_PROVIDER_FOR_CONTROLLER);
|
| return;
|
| }
|
|
|
| @@ -327,8 +498,8 @@ void ServiceWorkerProviderHost::SetControllerVersionAttribute(
|
| void ServiceWorkerProviderHost::SetHostedVersion(
|
| ServiceWorkerVersion* version) {
|
| DCHECK(!IsProviderForClient());
|
| - DCHECK_EQ(EmbeddedWorkerStatus::STARTING, version->running_status());
|
| - DCHECK_EQ(render_process_id_, version->embedded_worker()->process_id());
|
| + DCHECK_EQ(EmbeddedWorkerStatus::STOPPED, version->running_status());
|
| + DCHECK(!running_hosted_version_);
|
| running_hosted_version_ = version;
|
| }
|
|
|
| @@ -566,6 +737,7 @@ bool ServiceWorkerProviderHost::GetRegistrationForReady(
|
| std::unique_ptr<ServiceWorkerProviderHost>
|
| ServiceWorkerProviderHost::PrepareForCrossSiteTransfer() {
|
| DCHECK(!IsBrowserSideNavigationEnabled());
|
| + DCHECK(!ServiceWorkerUtils::IsServicificationEnabled());
|
| DCHECK_NE(ChildProcessHost::kInvalidUniqueID, render_process_id_);
|
| DCHECK_NE(MSG_ROUTING_NONE, info_.route_id);
|
| DCHECK_EQ(kDocumentMainThreadId, render_thread_id_);
|
| @@ -599,6 +771,7 @@ ServiceWorkerProviderHost::PrepareForCrossSiteTransfer() {
|
| void ServiceWorkerProviderHost::CompleteCrossSiteTransfer(
|
| ServiceWorkerProviderHost* provisional_host) {
|
| DCHECK(!IsBrowserSideNavigationEnabled());
|
| + DCHECK(!ServiceWorkerUtils::IsServicificationEnabled());
|
| DCHECK_EQ(ChildProcessHost::kInvalidUniqueID, render_process_id_);
|
| DCHECK_NE(ChildProcessHost::kInvalidUniqueID, provisional_host->process_id());
|
| DCHECK_NE(MSG_ROUTING_NONE, provisional_host->frame_id());
|
| @@ -659,6 +832,64 @@ void ServiceWorkerProviderHost::CompleteNavigationInitialized(
|
| NotifyControllerToAssociatedProvider();
|
| }
|
|
|
| +void ServiceWorkerProviderHost::CompleteStartWorkerPreparation(
|
| + int process_id,
|
| + mojom::ServiceWorkerProviderClientInfoPtr* out_provider_client_info) {
|
| + DCHECK(context_);
|
| +
|
| + DCHECK_EQ(kInvalidEmbeddedWorkerThreadId, render_thread_id_);
|
| + DCHECK_EQ(ChildProcessHost::kInvalidUniqueID, render_process_id_);
|
| + DCHECK_EQ(SERVICE_WORKER_PROVIDER_FOR_CONTROLLER, provider_type());
|
| + DCHECK(running_hosted_version_);
|
| +
|
| + DCHECK_NE(ChildProcessHost::kInvalidUniqueID, process_id);
|
| +
|
| + ServiceWorkerDispatcherHost* dispatcher_host =
|
| + context_->GetDispatcherHost(process_id);
|
| + DCHECK(dispatcher_host);
|
| + render_process_id_ = process_id;
|
| + dispatcher_host_ = dispatcher_host;
|
| +
|
| + // Retrieve the registration associated with |version|. The registration
|
| + // must be alive because the version keeps it during starting worker.
|
| + ServiceWorkerRegistration* registration = context_->GetLiveRegistration(
|
| + running_hosted_version()->registration_id());
|
| + DCHECK(registration);
|
| + ServiceWorkerRegistrationObjectInfo info;
|
| + ServiceWorkerVersionAttributes attrs;
|
| + dispatcher_host->GetRegistrationObjectInfoAndVersionAttributes(
|
| + AsWeakPtr(), registration, &info, &attrs);
|
| +
|
| + // Initialize provider_client_info.
|
| + (*out_provider_client_info)->provider_id = provider_id();
|
| + (*out_provider_client_info)->type = provider_type();
|
| + (*out_provider_client_info)->attributes = std::move(attrs);
|
| + (*out_provider_client_info)->registration = std::move(info);
|
| + (*out_provider_client_info)->is_parent_frame_secure =
|
| + is_parent_frame_secure();
|
| + (*out_provider_client_info)->client_request = mojo::MakeRequest(&provider_);
|
| +
|
| + mojom::URLLoaderFactoryAssociatedPtr loader_factory_ptr;
|
| + if (ServiceWorkerUtils::IsServicificationEnabled()) {
|
| + mojo::MakeStrongAssociatedBinding(
|
| + base::MakeUnique<ScriptURLLoaderFactory>(
|
| + context_, AsWeakPtr(), context_->blob_storage_context(),
|
| + context_->loader_factory_getter()),
|
| + mojo::MakeRequest(&loader_factory_ptr));
|
| + (*out_provider_client_info)->script_loader_factory_ptr_info =
|
| + loader_factory_ptr.PassInterface();
|
| + }
|
| +
|
| + auto* host_ptr_info_ptr = &(*out_provider_client_info)->host_ptr_info;
|
| + binding_.Bind(mojo::MakeRequest(host_ptr_info_ptr));
|
| + binding_.set_connection_error_handler(
|
| + base::Bind(&RemoveProviderHost, context_, process_id, provider_id()));
|
| +
|
| + // Set the document URL to the script url in order to allow
|
| + // register/unregister/getRegistration on ServiceWorkerGlobalScope.
|
| + SetDocumentUrl(running_hosted_version()->script_url());
|
| +}
|
| +
|
| void ServiceWorkerProviderHost::SendUpdateFoundMessage(
|
| int registration_handle_id) {
|
| if (!dispatcher_host_)
|
|
|