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