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