service_worker_controllee_request_handler.cc revision 6e8cce623b6e4fe0c9e4af605d675dd9d0338c38
15c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// Copyright 2014 The Chromium Authors. All rights reserved.
25c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// Use of this source code is governed by a BSD-style license that can be
35c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// found in the LICENSE file.
45c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
55c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "content/browser/service_worker/service_worker_controllee_request_handler.h"
65c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
75c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "content/browser/service_worker/service_worker_context_core.h"
8116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "content/browser/service_worker/service_worker_metrics.h"
95c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "content/browser/service_worker/service_worker_provider_host.h"
105c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "content/browser/service_worker/service_worker_registration.h"
115c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "content/browser/service_worker/service_worker_url_request_job.h"
125c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "content/browser/service_worker/service_worker_utils.h"
135c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "content/common/service_worker/service_worker_types.h"
14116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "net/base/load_flags.h"
1546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "net/base/net_util.h"
165c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "net/url_request/url_request.h"
175c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
185c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liunamespace content {
195c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
205c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuServiceWorkerControlleeRequestHandler::ServiceWorkerControlleeRequestHandler(
215c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    base::WeakPtr<ServiceWorkerContextCore> context,
225c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    base::WeakPtr<ServiceWorkerProviderHost> provider_host,
23cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    base::WeakPtr<webkit_blob::BlobStorageContext> blob_storage_context,
245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    ResourceType resource_type)
25cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    : ServiceWorkerRequestHandler(context,
26cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                  provider_host,
27cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                  blob_storage_context,
28cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                  resource_type),
29116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      is_main_resource_load_(
30116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch          ServiceWorkerUtils::IsMainResourceType(resource_type)),
315c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      weak_factory_(this) {
325c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
335c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
345c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuServiceWorkerControlleeRequestHandler::
355c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    ~ServiceWorkerControlleeRequestHandler() {
36116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // Navigation triggers an update to occur shortly after the page and
37116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // its initial subresources load.
38116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (provider_host_ && provider_host_->active_version()) {
39116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    if (is_main_resource_load_)
40116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      provider_host_->active_version()->ScheduleUpdate();
41116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    else
42116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      provider_host_->active_version()->DeferScheduledUpdate();
43116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
445c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
455c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
465c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liunet::URLRequestJob* ServiceWorkerControlleeRequestHandler::MaybeCreateJob(
475c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    net::URLRequest* request,
485c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    net::NetworkDelegate* network_delegate) {
495c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  if (!context_ || !provider_host_) {
505c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    // We can't do anything other than to fall back to network.
515c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    job_ = NULL;
525c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    return NULL;
535c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  }
545c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
55116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (request->load_flags() & net::LOAD_BYPASS_CACHE) {
56116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    if (is_main_resource_load_) {
57116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      provider_host_->SetDocumentUrl(
58116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch          net::SimplifyUrlForRequest(request->url()));
59116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    }
60116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    job_ = NULL;
61116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return NULL;
62116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
63116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
645c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // This may get called multiple times for original and redirect requests:
655c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // A. original request case: job_ is null, no previous location info.
665c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // B. redirect or restarted request case:
675c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  //  a) job_ is non-null if the previous location was forwarded to SW.
685c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  //  b) job_ is null if the previous location was fallback.
695c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  //  c) job_ is non-null if additional restart was required to fall back.
705c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
715c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // We've come here by restart, we already have original request and it
725c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // tells we should fallback to network. (Case B-c)
735c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  if (job_.get() && job_->ShouldFallbackToNetwork()) {
745c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    job_ = NULL;
755c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    return NULL;
765c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  }
775c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
785c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // It's for original request (A) or redirect case (B-a or B-b).
795c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  DCHECK(!job_.get() || job_->ShouldForwardToServiceWorker());
805c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
81cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  job_ = new ServiceWorkerURLRequestJob(
82cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      request, network_delegate, provider_host_, blob_storage_context_);
83116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (is_main_resource_load_)
845c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    PrepareForMainResource(request->url());
855c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  else
865c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    PrepareForSubResource();
875c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
885c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  if (job_->ShouldFallbackToNetwork()) {
895c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    // If we know we can fallback to network at this point (in case
905c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    // the storage lookup returned immediately), just return NULL here to
915c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    // fallback to network.
925c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    job_ = NULL;
935c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    return NULL;
945c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  }
955c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
965c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  return job_.get();
975c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
985c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void ServiceWorkerControlleeRequestHandler::GetExtraResponseInfo(
1005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    bool* was_fetched_via_service_worker,
1015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    GURL* original_url_via_service_worker) const {
1025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (!job_) {
1035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    *was_fetched_via_service_worker = false;
1045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    *original_url_via_service_worker = GURL();
1055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return;
1065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
1075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  job_->GetExtraResponseInfo(was_fetched_via_service_worker,
1085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                             original_url_via_service_worker);
1095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
1105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1115c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuvoid ServiceWorkerControlleeRequestHandler::PrepareForMainResource(
1125c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    const GURL& url) {
1135c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  DCHECK(job_.get());
1145c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  DCHECK(context_);
1155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // The corresponding provider_host may already have associated a registration
1165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // in redirect case, unassociate it now.
1176e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  provider_host_->UnassociateRegistration();
11846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
11946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  GURL stripped_url = net::SimplifyUrlForRequest(url);
12046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  provider_host_->SetDocumentUrl(stripped_url);
1215c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  context_->storage()->FindRegistrationForDocument(
12246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      stripped_url,
1235c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      base::Bind(&self::DidLookupRegistrationForMainResource,
1245c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                 weak_factory_.GetWeakPtr()));
1255c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
1265c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
1275c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuvoid
1285c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuServiceWorkerControlleeRequestHandler::DidLookupRegistrationForMainResource(
1295c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    ServiceWorkerStatusCode status,
1305c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    const scoped_refptr<ServiceWorkerRegistration>& registration) {
1315c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  DCHECK(job_.get());
1325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (status != SERVICE_WORKER_OK) {
1335c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    job_->FallbackToNetwork();
1345c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    return;
1355c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  }
1365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  DCHECK(registration);
137116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
138116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  ServiceWorkerMetrics::CountControlledPageLoad();
139116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
1405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // Initiate activation of a waiting version.
1415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // Usually a register job initiates activation but that
1425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // doesn't happen if the browser exits prior to activation
1435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // having occurred. This check handles that case.
1445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (registration->waiting_version())
1455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    registration->ActivateWaitingVersionWhenReady();
1465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  scoped_refptr<ServiceWorkerVersion> active_version =
1485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      registration->active_version();
1495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // Wait until it's activated before firing fetch events.
1515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (active_version &&
1526e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      active_version->status() == ServiceWorkerVersion::ACTIVATING) {
1535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    registration->active_version()->RegisterStatusChangeCallback(
1545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        base::Bind(&self::OnVersionStatusChanged,
1555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                   weak_factory_.GetWeakPtr(),
1565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                   registration,
1575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                   active_version));
1585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return;
1595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
1605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (!active_version ||
1625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      active_version->status() != ServiceWorkerVersion::ACTIVATED) {
1635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    job_->FallbackToNetwork();
1645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return;
1655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
1665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1676e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  provider_host_->AssociateRegistration(registration);
1685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  job_->ForwardToServiceWorker();
1695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
1705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void ServiceWorkerControlleeRequestHandler::OnVersionStatusChanged(
1725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    ServiceWorkerRegistration* registration,
1735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    ServiceWorkerVersion* version) {
1745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (version != registration->active_version() ||
1755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      version->status() != ServiceWorkerVersion::ACTIVATED) {
1765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    job_->FallbackToNetwork();
1775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return;
1785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
1795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1806e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  provider_host_->AssociateRegistration(registration);
1815c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  job_->ForwardToServiceWorker();
1825c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
1835c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
1845c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuvoid ServiceWorkerControlleeRequestHandler::PrepareForSubResource() {
1855c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  DCHECK(job_.get());
1865c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  DCHECK(context_);
1875c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  DCHECK(provider_host_->active_version());
1885c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  job_->ForwardToServiceWorker();
1895c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
1905c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
1915c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}  // namespace content
192