Battery Status API: add UMA logging for Linux.
[chromium-blink-merge.git] / content / browser / service_worker / service_worker_controllee_request_handler.cc
blob64442b5bf60a80ec5135b3ec0dd4aa0aed6b2e44
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.
5 #include "content/browser/service_worker/service_worker_controllee_request_handler.h"
7 #include "content/browser/service_worker/service_worker_context_core.h"
8 #include "content/browser/service_worker/service_worker_metrics.h"
9 #include "content/browser/service_worker/service_worker_provider_host.h"
10 #include "content/browser/service_worker/service_worker_registration.h"
11 #include "content/browser/service_worker/service_worker_url_request_job.h"
12 #include "content/browser/service_worker/service_worker_utils.h"
13 #include "content/common/resource_request_body.h"
14 #include "content/common/service_worker/service_worker_types.h"
15 #include "net/base/load_flags.h"
16 #include "net/base/net_util.h"
17 #include "net/url_request/url_request.h"
19 namespace content {
21 ServiceWorkerControlleeRequestHandler::ServiceWorkerControlleeRequestHandler(
22 base::WeakPtr<ServiceWorkerContextCore> context,
23 base::WeakPtr<ServiceWorkerProviderHost> provider_host,
24 base::WeakPtr<storage::BlobStorageContext> blob_storage_context,
25 ResourceType resource_type,
26 scoped_refptr<ResourceRequestBody> body)
27 : ServiceWorkerRequestHandler(context,
28 provider_host,
29 blob_storage_context,
30 resource_type),
31 is_main_resource_load_(
32 ServiceWorkerUtils::IsMainResourceType(resource_type)),
33 body_(body),
34 weak_factory_(this) {
37 ServiceWorkerControlleeRequestHandler::
38 ~ServiceWorkerControlleeRequestHandler() {
39 // Navigation triggers an update to occur shortly after the page and
40 // its initial subresources load.
41 if (provider_host_ && provider_host_->active_version()) {
42 if (is_main_resource_load_)
43 provider_host_->active_version()->ScheduleUpdate();
44 else
45 provider_host_->active_version()->DeferScheduledUpdate();
49 net::URLRequestJob* ServiceWorkerControlleeRequestHandler::MaybeCreateJob(
50 net::URLRequest* request,
51 net::NetworkDelegate* network_delegate) {
52 if (!context_ || !provider_host_) {
53 // We can't do anything other than to fall back to network.
54 job_ = NULL;
55 return NULL;
58 if (request->load_flags() & net::LOAD_BYPASS_CACHE) {
59 if (is_main_resource_load_) {
60 provider_host_->SetDocumentUrl(
61 net::SimplifyUrlForRequest(request->url()));
63 job_ = NULL;
64 return NULL;
67 // This may get called multiple times for original and redirect requests:
68 // A. original request case: job_ is null, no previous location info.
69 // B. redirect or restarted request case:
70 // a) job_ is non-null if the previous location was forwarded to SW.
71 // b) job_ is null if the previous location was fallback.
72 // c) job_ is non-null if additional restart was required to fall back.
74 // We've come here by restart, we already have original request and it
75 // tells we should fallback to network. (Case B-c)
76 if (job_.get() && job_->ShouldFallbackToNetwork()) {
77 job_ = NULL;
78 return NULL;
81 // It's for original request (A) or redirect case (B-a or B-b).
82 DCHECK(!job_.get() || job_->ShouldForwardToServiceWorker());
84 job_ = new ServiceWorkerURLRequestJob(
85 request, network_delegate, provider_host_, blob_storage_context_, body_);
86 if (is_main_resource_load_)
87 PrepareForMainResource(request->url());
88 else
89 PrepareForSubResource();
91 if (job_->ShouldFallbackToNetwork()) {
92 // If we know we can fallback to network at this point (in case
93 // the storage lookup returned immediately), just return NULL here to
94 // fallback to network.
95 job_ = NULL;
96 return NULL;
99 return job_.get();
102 void ServiceWorkerControlleeRequestHandler::GetExtraResponseInfo(
103 bool* was_fetched_via_service_worker,
104 GURL* original_url_via_service_worker) const {
105 if (!job_.get()) {
106 *was_fetched_via_service_worker = false;
107 *original_url_via_service_worker = GURL();
108 return;
110 job_->GetExtraResponseInfo(was_fetched_via_service_worker,
111 original_url_via_service_worker);
114 void ServiceWorkerControlleeRequestHandler::PrepareForMainResource(
115 const GURL& url) {
116 DCHECK(job_.get());
117 DCHECK(context_);
118 // The corresponding provider_host may already have associated a registration
119 // in redirect case, unassociate it now.
120 provider_host_->UnassociateRegistration();
122 GURL stripped_url = net::SimplifyUrlForRequest(url);
123 provider_host_->SetDocumentUrl(stripped_url);
124 context_->storage()->FindRegistrationForDocument(
125 stripped_url,
126 base::Bind(&self::DidLookupRegistrationForMainResource,
127 weak_factory_.GetWeakPtr()));
130 void
131 ServiceWorkerControlleeRequestHandler::DidLookupRegistrationForMainResource(
132 ServiceWorkerStatusCode status,
133 const scoped_refptr<ServiceWorkerRegistration>& registration) {
134 DCHECK(job_.get());
135 if (status != SERVICE_WORKER_OK) {
136 job_->FallbackToNetwork();
137 return;
139 DCHECK(registration.get());
141 ServiceWorkerMetrics::CountControlledPageLoad();
143 // Initiate activation of a waiting version.
144 // Usually a register job initiates activation but that
145 // doesn't happen if the browser exits prior to activation
146 // having occurred. This check handles that case.
147 if (registration->waiting_version())
148 registration->ActivateWaitingVersionWhenReady();
150 scoped_refptr<ServiceWorkerVersion> active_version =
151 registration->active_version();
153 // Wait until it's activated before firing fetch events.
154 if (active_version.get() &&
155 active_version->status() == ServiceWorkerVersion::ACTIVATING) {
156 registration->active_version()->RegisterStatusChangeCallback(
157 base::Bind(&self::OnVersionStatusChanged,
158 weak_factory_.GetWeakPtr(),
159 registration,
160 active_version));
161 return;
164 if (!active_version.get() ||
165 active_version->status() != ServiceWorkerVersion::ACTIVATED) {
166 job_->FallbackToNetwork();
167 return;
170 provider_host_->AssociateRegistration(registration.get());
171 job_->ForwardToServiceWorker();
174 void ServiceWorkerControlleeRequestHandler::OnVersionStatusChanged(
175 ServiceWorkerRegistration* registration,
176 ServiceWorkerVersion* version) {
177 if (version != registration->active_version() ||
178 version->status() != ServiceWorkerVersion::ACTIVATED) {
179 job_->FallbackToNetwork();
180 return;
183 provider_host_->AssociateRegistration(registration);
184 job_->ForwardToServiceWorker();
187 void ServiceWorkerControlleeRequestHandler::PrepareForSubResource() {
188 DCHECK(job_.get());
189 DCHECK(context_);
190 DCHECK(provider_host_->active_version());
191 job_->ForwardToServiceWorker();
194 } // namespace content