Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(210)

Unified Diff: content/browser/service_worker/service_worker_provider_host.cc

Issue 2936623002: Implement dumb URLLoader{Factory} for ServiceWorker script loading (for try)
Patch Set: . Created 3 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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_)

Powered by Google App Engine
This is Rietveld 408576698