Home | History | Annotate | Download | only in service_worker
      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