| Index: content/browser/service_worker/service_worker_controllee_request_handler.cc
|
| diff --git a/content/browser/service_worker/service_worker_controllee_request_handler.cc b/content/browser/service_worker/service_worker_controllee_request_handler.cc
|
| index 76e9c2d3139b242ea1acf4b0bc601f4edd6c3a0c..05380d909c5092d62e93a3337f4c863226fff542 100644
|
| --- a/content/browser/service_worker/service_worker_controllee_request_handler.cc
|
| +++ b/content/browser/service_worker/service_worker_controllee_request_handler.cc
|
| @@ -25,6 +25,7 @@
|
| #include "content/public/common/browser_side_navigation_policy.h"
|
| #include "content/public/common/content_client.h"
|
| #include "content/public/common/resource_response_info.h"
|
| +#include "mojo/public/cpp/bindings/strong_binding.h"
|
| #include "net/base/load_flags.h"
|
| #include "net/base/url_util.h"
|
| #include "net/url_request/url_request.h"
|
| @@ -32,10 +33,98 @@
|
|
|
| namespace content {
|
|
|
| +// Helper to support both a URLRequestJob and a URLLoaderFactory to support
|
| +// running with and without --enable-network-service.
|
| +class ServiceWorkerControlleeRequestHandler::JobWrapper {
|
| + public:
|
| + explicit JobWrapper(base::WeakPtr<ServiceWorkerURLRequestJob> url_request_job)
|
| + : url_request_job_(std::move(url_request_job)), factory_(nullptr) {}
|
| +
|
| + // --enable-network-service.
|
| + explicit JobWrapper(ServiceWorkerControlleeURLLoaderFactory* factory)
|
| + : factory_(factory) {}
|
| +
|
| + void FallbackToNetwork() {
|
| + if (factory_) {
|
| + factory_->FallbackToNetwork();
|
| + } else {
|
| + url_request_job_->FallbackToNetwork();
|
| + }
|
| + }
|
| +
|
| + bool ShouldFallbackToNetwork() {
|
| + if (factory_) {
|
| + return factory_->ShouldFallbackToNetwork();
|
| + } else {
|
| + return url_request_job_->ShouldFallbackToNetwork();
|
| + }
|
| + }
|
| +
|
| + ui::PageTransition GetPageTransition() {
|
| + if (factory_) {
|
| + return factory_->GetPageTransition();
|
| + } else {
|
| + const ResourceRequestInfo* info =
|
| + ResourceRequestInfo::ForRequest(url_request_job_->request());
|
| + // ResourceRequestInfo may not be set in some tests.
|
| + if (!info)
|
| + return ui::PAGE_TRANSITION_LINK;
|
| + return info->GetPageTransition();
|
| + }
|
| + }
|
| +
|
| + size_t GetURLChainSize() const {
|
| + if (factory_) {
|
| + return factory_->GetURLChainSize();
|
| + } else {
|
| + return url_request_job_->request()->url_chain().size();
|
| + }
|
| + }
|
| +
|
| + void ForwardToServiceWorker() {
|
| + if (factory_) {
|
| + factory_->ForwardToServiceWorker();
|
| + } else {
|
| + url_request_job_->ForwardToServiceWorker();
|
| + }
|
| + }
|
| +
|
| + void FallbackToNetworkOrRenderer() {
|
| + if (factory_) {
|
| + factory_->FallbackToNetworkOrRenderer();
|
| + } else {
|
| + url_request_job_->FallbackToNetworkOrRenderer();
|
| + }
|
| + }
|
| +
|
| + void FailDueToLostController() {
|
| + if (factory_) {
|
| + factory_->FailDueToLostController();
|
| + } else {
|
| + url_request_job_->FailDueToLostController();
|
| + }
|
| + }
|
| +
|
| + bool WasCanceled() const {
|
| + if (factory_) {
|
| + return factory_->WasCanceled();
|
| + } else {
|
| + return !url_request_job_;
|
| + }
|
| + }
|
| +
|
| + private:
|
| + base::WeakPtr<ServiceWorkerURLRequestJob> url_request_job_;
|
| + ServiceWorkerControlleeURLLoaderFactory* factory_;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(JobWrapper);
|
| +};
|
| +
|
| namespace {
|
|
|
| -bool MaybeForwardToServiceWorker(ServiceWorkerURLRequestJob* job,
|
| - const ServiceWorkerVersion* version) {
|
| +bool MaybeForwardToServiceWorker(
|
| + ServiceWorkerControlleeRequestHandler::JobWrapper* job,
|
| + const ServiceWorkerVersion* version) {
|
| DCHECK(job);
|
| DCHECK(version);
|
| DCHECK_NE(version->fetch_handler_existence(),
|
| @@ -50,14 +139,6 @@ bool MaybeForwardToServiceWorker(ServiceWorkerURLRequestJob* job,
|
| return false;
|
| }
|
|
|
| -ui::PageTransition GetPageTransition(net::URLRequest* request) {
|
| - const ResourceRequestInfo* info = ResourceRequestInfo::ForRequest(request);
|
| - // ResourceRequestInfo may not be set in some tests.
|
| - if (!info)
|
| - return ui::PAGE_TRANSITION_LINK;
|
| - return info->GetPageTransition();
|
| -}
|
| -
|
| } // namespace
|
|
|
| ServiceWorkerControlleeRequestHandler::ServiceWorkerControlleeRequestHandler(
|
| @@ -70,7 +151,8 @@ ServiceWorkerControlleeRequestHandler::ServiceWorkerControlleeRequestHandler(
|
| ResourceType resource_type,
|
| RequestContextType request_context_type,
|
| RequestContextFrameType frame_type,
|
| - scoped_refptr<ResourceRequestBodyImpl> body)
|
| + scoped_refptr<ResourceRequestBodyImpl> body,
|
| + NetworkFallbackCallback network_fallback_callback)
|
| : ServiceWorkerRequestHandler(context,
|
| provider_host,
|
| blob_storage_context,
|
| @@ -86,6 +168,7 @@ ServiceWorkerControlleeRequestHandler::ServiceWorkerControlleeRequestHandler(
|
| body_(body),
|
| force_update_started_(false),
|
| use_network_(false),
|
| + network_fallback_callback_(network_fallback_callback),
|
| weak_factory_(this) {}
|
|
|
| ServiceWorkerControlleeRequestHandler::
|
| @@ -140,12 +223,12 @@ net::URLRequestJob* ServiceWorkerControlleeRequestHandler::MaybeCreateJob(
|
| credentials_mode_, redirect_mode_, resource_type_,
|
| request_context_type_, frame_type_, body_,
|
| ServiceWorkerFetchType::FETCH, base::nullopt, this));
|
| - job_ = job->GetWeakPtr();
|
| + job_ = base::MakeUnique<JobWrapper>(job->GetWeakPtr());
|
|
|
| resource_context_ = resource_context;
|
|
|
| if (is_main_resource_load_)
|
| - PrepareForMainResource(request);
|
| + PrepareForMainResource(request->url(), request->first_party_for_cookies());
|
| else
|
| PrepareForSubResource();
|
|
|
| @@ -166,16 +249,85 @@ net::URLRequestJob* ServiceWorkerControlleeRequestHandler::MaybeCreateJob(
|
| return job.release();
|
| }
|
|
|
| +mojom::URLLoaderFactoryPtrInfo
|
| +ServiceWorkerControlleeRequestHandler::MaybeGetURLLoaderFactory(
|
| + const ResourceRequest& request,
|
| + ResourceContext* resource_context,
|
| + std::unique_ptr<ServiceWorkerRequestHandler> request_handler) {
|
| + ClearJob();
|
| + // TODO(scottmg):
|
| + // ServiceWorkerResponseInfo::ResetDataForRequest(request);
|
| +
|
| + if (!context_ || !provider_host_) {
|
| + // We can't do anything other than to fall back to network.
|
| + return mojom::URLLoaderFactoryPtrInfo();
|
| + }
|
| +
|
| + DCHECK(is_main_resource_load_);
|
| +
|
| + // This may get called multiple times for original and redirect requests:
|
| + // A. original request case: use_network_ is false, no previous location info.
|
| + // B. redirect or restarted request case:
|
| + // a) use_network_ is false if the previous location was forwarded to SW.
|
| + // b) use_network_ is false if the previous location was fallback.
|
| + // c) use_network_ is true if additional restart was required to fall back.
|
| +
|
| + // Fall back to network. (Case B-c)
|
| + if (use_network_) {
|
| + // Once a subresource request has fallen back to the network once, it will
|
| + // never be handled by a service worker. This is not true of main frame
|
| + // requests.
|
| + if (is_main_resource_load_)
|
| + use_network_ = false;
|
| + return mojom::URLLoaderFactoryPtrInfo();
|
| + }
|
| +
|
| + mojom::URLLoaderFactoryPtr url_loader_factory;
|
| + auto factory_impl = base::MakeUnique<ServiceWorkerControlleeURLLoaderFactory>(
|
| + std::move(request_handler), provider_host_->client_uuid(),
|
| + blob_storage_context_, resource_context, request_mode_, credentials_mode_,
|
| + redirect_mode_, resource_type_, request_context_type_, frame_type_, body_,
|
| + ServiceWorkerFetchType::FETCH, base::nullopt, this,
|
| + network_fallback_callback_);
|
| + auto* factory = factory_impl.get();
|
| + mojo::MakeStrongBinding(std::move(factory_impl),
|
| + mojo::MakeRequest(&url_loader_factory));
|
| +
|
| + // It's for original request (A) or redirect case (B-a or B-b).
|
| + job_ = base::MakeUnique<JobWrapper>(factory);
|
| +
|
| + resource_context_ = resource_context;
|
| +
|
| + if (is_main_resource_load_)
|
| + PrepareForMainResource(request.url, request.first_party_for_cookies);
|
| +
|
| + if (job_->ShouldFallbackToNetwork()) {
|
| + // If we know we can fallback to network at this point (in case
|
| + // the storage lookup returned immediately), just destroy the job and return
|
| + // NULL here to fallback to network.
|
| +
|
| + // If this is a subresource request, all subsequent requests should also use
|
| + // the network.
|
| + if (!is_main_resource_load_)
|
| + use_network_ = true;
|
| +
|
| + ClearJob();
|
| + return mojom::URLLoaderFactoryPtrInfo();
|
| + }
|
| +
|
| + return url_loader_factory.PassInterface();
|
| +}
|
| +
|
| void ServiceWorkerControlleeRequestHandler::PrepareForMainResource(
|
| - const net::URLRequest* request) {
|
| + const GURL& url,
|
| + const GURL& first_party_for_cookies) {
|
| DCHECK(job_.get());
|
| DCHECK(context_);
|
| DCHECK(provider_host_);
|
| TRACE_EVENT_ASYNC_BEGIN1(
|
| "ServiceWorker",
|
| "ServiceWorkerControlleeRequestHandler::PrepareForMainResource",
|
| - job_.get(),
|
| - "URL", request->url().spec());
|
| + job_.get(), "URL", url.spec());
|
| // The corresponding provider_host may already have associated a registration
|
| // in redirect case, unassociate it now.
|
| provider_host_->DisassociateRegistration();
|
| @@ -184,9 +336,9 @@ void ServiceWorkerControlleeRequestHandler::PrepareForMainResource(
|
| // registration while we're finding an existing registration.
|
| provider_host_->SetAllowAssociation(false);
|
|
|
| - stripped_url_ = net::SimplifyUrlForRequest(request->url());
|
| + stripped_url_ = net::SimplifyUrlForRequest(url);
|
| provider_host_->SetDocumentUrl(stripped_url_);
|
| - provider_host_->SetTopmostFrameUrl(request->first_party_for_cookies());
|
| + provider_host_->SetTopmostFrameUrl(first_party_for_cookies);
|
| context_->storage()->FindRegistrationForDocument(
|
| stripped_url_, base::Bind(&self::DidLookupRegistrationForMainResource,
|
| weak_factory_.GetWeakPtr()));
|
| @@ -197,7 +349,7 @@ void ServiceWorkerControlleeRequestHandler::
|
| ServiceWorkerStatusCode status,
|
| scoped_refptr<ServiceWorkerRegistration> registration) {
|
| // The job may have been canceled and then destroyed before this was invoked.
|
| - if (!job_)
|
| + if (job_->WasCanceled())
|
| return;
|
|
|
| const bool need_to_update = !force_update_started_ && registration &&
|
| @@ -312,7 +464,7 @@ void ServiceWorkerControlleeRequestHandler::
|
| ServiceWorkerVersion::FetchHandlerExistence::UNKNOWN);
|
| ServiceWorkerMetrics::CountControlledPageLoad(
|
| active_version->site_for_uma(), stripped_url_, is_main_frame_load_,
|
| - GetPageTransition(job_->request()), job_->request()->url_chain().size());
|
| + job_->GetPageTransition(), job_->GetURLChainSize());
|
|
|
| bool is_forwarded =
|
| MaybeForwardToServiceWorker(job_.get(), active_version.get());
|
| @@ -329,7 +481,7 @@ void ServiceWorkerControlleeRequestHandler::OnVersionStatusChanged(
|
| ServiceWorkerRegistration* registration,
|
| ServiceWorkerVersion* version) {
|
| // The job may have been canceled and then destroyed before this was invoked.
|
| - if (!job_)
|
| + if (job_->WasCanceled())
|
| return;
|
|
|
| if (provider_host_)
|
| @@ -345,7 +497,7 @@ void ServiceWorkerControlleeRequestHandler::OnVersionStatusChanged(
|
| ServiceWorkerVersion::FetchHandlerExistence::UNKNOWN);
|
| ServiceWorkerMetrics::CountControlledPageLoad(
|
| version->site_for_uma(), stripped_url_, is_main_frame_load_,
|
| - GetPageTransition(job_->request()), job_->request()->url_chain().size());
|
| + job_->GetPageTransition(), job_->GetURLChainSize());
|
|
|
| provider_host_->AssociateRegistration(registration,
|
| false /* notify_controllerchange */);
|
| @@ -361,7 +513,7 @@ void ServiceWorkerControlleeRequestHandler::DidUpdateRegistration(
|
| DCHECK(force_update_started_);
|
|
|
| // The job may have been canceled and then destroyed before this was invoked.
|
| - if (!job_)
|
| + if (job_->WasCanceled())
|
| return;
|
|
|
| if (!context_) {
|
| @@ -391,7 +543,7 @@ void ServiceWorkerControlleeRequestHandler::OnUpdatedVersionStatusChanged(
|
| const scoped_refptr<ServiceWorkerRegistration>& registration,
|
| const scoped_refptr<ServiceWorkerVersion>& version) {
|
| // The job may have been canceled and then destroyed before this was invoked.
|
| - if (!job_)
|
| + if (job_->WasCanceled())
|
| return;
|
|
|
| if (!context_) {
|
|
|