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_) { |