Chromium Code Reviews| 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..34e5d67085e08360413299a4d80e10eaad8d5e9d 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(); |
| + } |
| + |
|
kinuko
2017/05/09 14:45:25
We should always be loading main resource here, so
scottmg
2017/05/09 22:14:10
Yup, good point, done. I was thinking maybe we'd s
|
| + // 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); |
| + else |
| + PrepareForSubResource(); |
|
kinuko
2017/05/09 14:45:25
This path shouldn't be necessary?
scottmg
2017/05/09 22:14:10
Done.
|
| + |
| + 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_) { |