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_context_request_handler.h" 6 7#include "base/time/time.h" 8#include "content/browser/service_worker/service_worker_context_core.h" 9#include "content/browser/service_worker/service_worker_provider_host.h" 10#include "content/browser/service_worker/service_worker_read_from_cache_job.h" 11#include "content/browser/service_worker/service_worker_storage.h" 12#include "content/browser/service_worker/service_worker_version.h" 13#include "content/browser/service_worker/service_worker_write_to_cache_job.h" 14#include "net/base/load_flags.h" 15#include "net/url_request/url_request.h" 16 17namespace content { 18 19ServiceWorkerContextRequestHandler::ServiceWorkerContextRequestHandler( 20 base::WeakPtr<ServiceWorkerContextCore> context, 21 base::WeakPtr<ServiceWorkerProviderHost> provider_host, 22 base::WeakPtr<storage::BlobStorageContext> blob_storage_context, 23 ResourceType resource_type) 24 : ServiceWorkerRequestHandler(context, 25 provider_host, 26 blob_storage_context, 27 resource_type), 28 version_(provider_host_->running_hosted_version()) { 29 DCHECK(provider_host_->IsHostToRunningServiceWorker()); 30} 31 32ServiceWorkerContextRequestHandler::~ServiceWorkerContextRequestHandler() { 33} 34 35net::URLRequestJob* ServiceWorkerContextRequestHandler::MaybeCreateJob( 36 net::URLRequest* request, 37 net::NetworkDelegate* network_delegate) { 38 if (!provider_host_ || !version_.get() || !context_) 39 return NULL; 40 41 // We currently have no use case for hijacking a redirected request. 42 if (request->url_chain().size() > 1) 43 return NULL; 44 45 // We only use the script cache for main script loading and 46 // importScripts(), even if a cached script is xhr'd, we don't 47 // retrieve it from the script cache. 48 // TODO(michaeln): Get the desired behavior clarified in the spec, 49 // and make tweak the behavior here to match. 50 if (resource_type_ != RESOURCE_TYPE_SERVICE_WORKER && 51 resource_type_ != RESOURCE_TYPE_SCRIPT) { 52 return NULL; 53 } 54 55 if (ShouldAddToScriptCache(request->url())) { 56 ServiceWorkerRegistration* registration = 57 context_->GetLiveRegistration(version_->registration_id()); 58 DCHECK(registration); // We're registering or updating so must be there. 59 60 int64 response_id = context_->storage()->NewResourceId(); 61 if (response_id == kInvalidServiceWorkerResponseId) 62 return NULL; 63 64 // Bypass the browser cache for initial installs and update 65 // checks after 24 hours have passed. 66 int extra_load_flags = 0; 67 base::TimeDelta time_since_last_check = 68 base::Time::Now() - registration->last_update_check(); 69 if (time_since_last_check > base::TimeDelta::FromHours(24)) 70 extra_load_flags = net::LOAD_BYPASS_CACHE; 71 72 return new ServiceWorkerWriteToCacheJob(request, 73 network_delegate, 74 resource_type_, 75 context_, 76 version_.get(), 77 extra_load_flags, 78 response_id); 79 } 80 81 int64 response_id = kInvalidServiceWorkerResponseId; 82 if (ShouldReadFromScriptCache(request->url(), &response_id)) { 83 return new ServiceWorkerReadFromCacheJob( 84 request, network_delegate, context_, response_id); 85 } 86 87 // NULL means use the network. 88 return NULL; 89} 90 91void ServiceWorkerContextRequestHandler::GetExtraResponseInfo( 92 bool* was_fetched_via_service_worker, 93 GURL* original_url_via_service_worker, 94 base::TimeTicks* fetch_start_time, 95 base::TimeTicks* fetch_ready_time, 96 base::TimeTicks* fetch_end_time) const { 97 *was_fetched_via_service_worker = false; 98 *original_url_via_service_worker = GURL(); 99} 100 101bool ServiceWorkerContextRequestHandler::ShouldAddToScriptCache( 102 const GURL& url) { 103 // We only write imports that occur during the initial eval. 104 if (version_->status() != ServiceWorkerVersion::NEW && 105 version_->status() != ServiceWorkerVersion::INSTALLING) { 106 return false; 107 } 108 return version_->script_cache_map()->Lookup(url) == 109 kInvalidServiceWorkerResponseId; 110} 111 112bool ServiceWorkerContextRequestHandler::ShouldReadFromScriptCache( 113 const GURL& url, int64* response_id_out) { 114 // We don't read from the script cache until the version is INSTALLED. 115 if (version_->status() == ServiceWorkerVersion::NEW || 116 version_->status() == ServiceWorkerVersion::INSTALLING) 117 return false; 118 *response_id_out = version_->script_cache_map()->Lookup(url); 119 return *response_id_out != kInvalidServiceWorkerResponseId; 120} 121 122} // namespace content 123