service_worker_context_request_handler.cc revision 1320f92c476a1ad9d19dba2a48c72b75566198e9
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_context_request_handler.h"
65c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
71320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/time/time.h"
8cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "content/browser/service_worker/service_worker_context_core.h"
9010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "content/browser/service_worker/service_worker_provider_host.h"
10010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "content/browser/service_worker/service_worker_read_from_cache_job.h"
11cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "content/browser/service_worker/service_worker_storage.h"
12010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "content/browser/service_worker/service_worker_version.h"
13cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "content/browser/service_worker/service_worker_write_to_cache_job.h"
146e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "net/base/load_flags.h"
15010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "net/url_request/url_request.h"
16010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
175c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liunamespace content {
185c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
195c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuServiceWorkerContextRequestHandler::ServiceWorkerContextRequestHandler(
205c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    base::WeakPtr<ServiceWorkerContextCore> context,
215c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    base::WeakPtr<ServiceWorkerProviderHost> provider_host,
2203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    base::WeakPtr<storage::BlobStorageContext> blob_storage_context,
235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    ResourceType resource_type)
24cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    : ServiceWorkerRequestHandler(context,
25cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                  provider_host,
26cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                  blob_storage_context,
27cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                  resource_type),
28010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      version_(provider_host_->running_hosted_version()) {
29010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  DCHECK(provider_host_->IsHostToRunningServiceWorker());
305c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
315c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
325c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuServiceWorkerContextRequestHandler::~ServiceWorkerContextRequestHandler() {
335c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
345c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
355c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liunet::URLRequestJob* ServiceWorkerContextRequestHandler::MaybeCreateJob(
365c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    net::URLRequest* request,
375c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    net::NetworkDelegate* network_delegate) {
381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (!provider_host_ || !version_.get() || !context_)
39cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return NULL;
40cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
41cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // We currently have no use case for hijacking a redirected request.
42cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (request->url_chain().size() > 1)
43010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    return NULL;
44010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
45010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // We only use the script cache for main script loading and
46010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // importScripts(), even if a cached script is xhr'd, we don't
47010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // retrieve it from the script cache.
48010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // TODO(michaeln): Get the desired behavior clarified in the spec,
49010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // and make tweak the behavior here to match.
505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (resource_type_ != RESOURCE_TYPE_SERVICE_WORKER &&
515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      resource_type_ != RESOURCE_TYPE_SCRIPT) {
52010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    return NULL;
53010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
54010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
55010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (ShouldAddToScriptCache(request->url())) {
566e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    ServiceWorkerRegistration* registration =
576e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        context_->GetLiveRegistration(version_->registration_id());
586e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    DCHECK(registration);  // We're registering or updating so must be there.
596e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
60cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    int64 response_id = context_->storage()->NewResourceId();
61cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if (response_id == kInvalidServiceWorkerResponseId)
62cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      return NULL;
636e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
646e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    // Bypass the browser cache for initial installs and update
656e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    // checks after 24 hours have passed.
666e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    int extra_load_flags = 0;
676e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    base::TimeDelta time_since_last_check =
686e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        base::Time::Now() - registration->last_update_check();
696e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    if (time_since_last_check > base::TimeDelta::FromHours(24))
706e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      extra_load_flags = net::LOAD_BYPASS_CACHE;
716e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
72116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return new ServiceWorkerWriteToCacheJob(request,
73116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                            network_delegate,
74116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                            resource_type_,
75116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                            context_,
761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                            version_.get(),
776e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                                            extra_load_flags,
78116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                            response_id);
79010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
80010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
81010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  int64 response_id = kInvalidServiceWorkerResponseId;
82010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (ShouldReadFromScriptCache(request->url(), &response_id)) {
83010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    return new ServiceWorkerReadFromCacheJob(
84010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        request, network_delegate, context_, response_id);
85010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
86010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
87010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // NULL means use the network.
885c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  return NULL;
895c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
905c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void ServiceWorkerContextRequestHandler::GetExtraResponseInfo(
925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    bool* was_fetched_via_service_worker,
931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    GURL* original_url_via_service_worker,
941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    base::TimeTicks* fetch_start_time,
951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    base::TimeTicks* fetch_ready_time,
961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    base::TimeTicks* fetch_end_time) const {
975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  *was_fetched_via_service_worker = false;
985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  *original_url_via_service_worker = GURL();
995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
1005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
101010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)bool ServiceWorkerContextRequestHandler::ShouldAddToScriptCache(
102010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    const GURL& url) {
103cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // We only write imports that occur during the initial eval.
104116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (version_->status() != ServiceWorkerVersion::NEW &&
105116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      version_->status() != ServiceWorkerVersion::INSTALLING) {
106010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    return false;
107116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
108cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return version_->script_cache_map()->Lookup(url) ==
109cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)            kInvalidServiceWorkerResponseId;
110010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
111010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
112010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)bool ServiceWorkerContextRequestHandler::ShouldReadFromScriptCache(
113010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    const GURL& url, int64* response_id_out) {
114010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // We don't read from the script cache until the version is INSTALLED.
115010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (version_->status() == ServiceWorkerVersion::NEW ||
116010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      version_->status() == ServiceWorkerVersion::INSTALLING)
117010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    return false;
118cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  *response_id_out = version_->script_cache_map()->Lookup(url);
119010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  return *response_id_out != kInvalidServiceWorkerResponseId;
120010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
121010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
1225c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}  // namespace content
123