1 // Copyright 2014 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "content/browser/service_worker/service_worker_controllee_request_handler.h" 6 7 #include "content/browser/service_worker/service_worker_context_core.h" 8 #include "content/browser/service_worker/service_worker_provider_host.h" 9 #include "content/browser/service_worker/service_worker_registration.h" 10 #include "content/browser/service_worker/service_worker_url_request_job.h" 11 #include "content/browser/service_worker/service_worker_utils.h" 12 #include "content/common/service_worker/service_worker_types.h" 13 #include "net/base/net_util.h" 14 #include "net/url_request/url_request.h" 15 16 namespace content { 17 18 ServiceWorkerControlleeRequestHandler::ServiceWorkerControlleeRequestHandler( 19 base::WeakPtr<ServiceWorkerContextCore> context, 20 base::WeakPtr<ServiceWorkerProviderHost> provider_host, 21 base::WeakPtr<webkit_blob::BlobStorageContext> blob_storage_context, 22 ResourceType::Type resource_type) 23 : ServiceWorkerRequestHandler(context, 24 provider_host, 25 blob_storage_context, 26 resource_type), 27 weak_factory_(this) { 28 } 29 30 ServiceWorkerControlleeRequestHandler:: 31 ~ServiceWorkerControlleeRequestHandler() { 32 } 33 34 net::URLRequestJob* ServiceWorkerControlleeRequestHandler::MaybeCreateJob( 35 net::URLRequest* request, 36 net::NetworkDelegate* network_delegate) { 37 if (!context_ || !provider_host_) { 38 // We can't do anything other than to fall back to network. 39 job_ = NULL; 40 return NULL; 41 } 42 43 // This may get called multiple times for original and redirect requests: 44 // A. original request case: job_ is null, no previous location info. 45 // B. redirect or restarted request case: 46 // a) job_ is non-null if the previous location was forwarded to SW. 47 // b) job_ is null if the previous location was fallback. 48 // c) job_ is non-null if additional restart was required to fall back. 49 50 // We've come here by restart, we already have original request and it 51 // tells we should fallback to network. (Case B-c) 52 if (job_.get() && job_->ShouldFallbackToNetwork()) { 53 job_ = NULL; 54 return NULL; 55 } 56 57 // It's for original request (A) or redirect case (B-a or B-b). 58 DCHECK(!job_.get() || job_->ShouldForwardToServiceWorker()); 59 60 job_ = new ServiceWorkerURLRequestJob( 61 request, network_delegate, provider_host_, blob_storage_context_); 62 if (ServiceWorkerUtils::IsMainResourceType(resource_type_)) 63 PrepareForMainResource(request->url()); 64 else 65 PrepareForSubResource(); 66 67 if (job_->ShouldFallbackToNetwork()) { 68 // If we know we can fallback to network at this point (in case 69 // the storage lookup returned immediately), just return NULL here to 70 // fallback to network. 71 job_ = NULL; 72 return NULL; 73 } 74 75 return job_.get(); 76 } 77 78 void ServiceWorkerControlleeRequestHandler::PrepareForMainResource( 79 const GURL& url) { 80 DCHECK(job_.get()); 81 DCHECK(context_); 82 // The corresponding provider_host may already have associate version in 83 // redirect case, unassociate it now. 84 provider_host_->SetActiveVersion(NULL); 85 provider_host_->SetWaitingVersion(NULL); 86 87 GURL stripped_url = net::SimplifyUrlForRequest(url); 88 provider_host_->SetDocumentUrl(stripped_url); 89 context_->storage()->FindRegistrationForDocument( 90 stripped_url, 91 base::Bind(&self::DidLookupRegistrationForMainResource, 92 weak_factory_.GetWeakPtr())); 93 } 94 95 void 96 ServiceWorkerControlleeRequestHandler::DidLookupRegistrationForMainResource( 97 ServiceWorkerStatusCode status, 98 const scoped_refptr<ServiceWorkerRegistration>& registration) { 99 DCHECK(job_.get()); 100 if (status != SERVICE_WORKER_OK || !registration->active_version()) { 101 // No registration, or no active version for the registration is available. 102 job_->FallbackToNetwork(); 103 return; 104 } 105 // TODO(michaeln): should SetWaitingVersion() even if no active version so 106 // so the versions in the pipeline (.installing, .waiting) show up in the 107 // attribute values. 108 DCHECK(registration); 109 provider_host_->SetActiveVersion(registration->active_version()); 110 provider_host_->SetWaitingVersion(registration->waiting_version()); 111 job_->ForwardToServiceWorker(); 112 } 113 114 void ServiceWorkerControlleeRequestHandler::PrepareForSubResource() { 115 DCHECK(job_.get()); 116 DCHECK(context_); 117 DCHECK(provider_host_->active_version()); 118 job_->ForwardToServiceWorker(); 119 } 120 121 } // namespace content 122