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_context_request_handler.h"
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 "content/public/browser/resource_context.h"
15 #include "content/public/common/resource_response_info.h"
16 #include "net/base/load_flags.h"
17 #include "net/url_request/url_request.h"
21 ServiceWorkerContextRequestHandler::ServiceWorkerContextRequestHandler(
22 base::WeakPtr
<ServiceWorkerContextCore
> context
,
23 base::WeakPtr
<ServiceWorkerProviderHost
> provider_host
,
24 base::WeakPtr
<storage::BlobStorageContext
> blob_storage_context
,
25 ResourceType resource_type
)
26 : ServiceWorkerRequestHandler(context
,
30 version_(provider_host_
->running_hosted_version()) {
31 DCHECK(provider_host_
->IsHostToRunningServiceWorker());
34 ServiceWorkerContextRequestHandler::~ServiceWorkerContextRequestHandler() {
37 net::URLRequestJob
* ServiceWorkerContextRequestHandler::MaybeCreateJob(
38 net::URLRequest
* request
,
39 net::NetworkDelegate
* network_delegate
,
40 ResourceContext
* resource_context
) {
41 if (!provider_host_
|| !version_
.get() || !context_
)
44 // We currently have no use case for hijacking a redirected request.
45 if (request
->url_chain().size() > 1)
48 // We only use the script cache for main script loading and
49 // importScripts(), even if a cached script is xhr'd, we don't
50 // retrieve it from the script cache.
51 // TODO(michaeln): Get the desired behavior clarified in the spec,
52 // and make tweak the behavior here to match.
53 if (resource_type_
!= RESOURCE_TYPE_SERVICE_WORKER
&&
54 resource_type_
!= RESOURCE_TYPE_SCRIPT
) {
58 if (ShouldAddToScriptCache(request
->url())) {
59 ServiceWorkerRegistration
* registration
=
60 context_
->GetLiveRegistration(version_
->registration_id());
61 DCHECK(registration
); // We're registering or updating so must be there.
63 int64 response_id
= context_
->storage()->NewResourceId();
64 if (response_id
== kInvalidServiceWorkerResponseId
)
67 // Bypass the browser cache for initial installs and update
68 // checks after 24 hours have passed.
69 int extra_load_flags
= 0;
70 base::TimeDelta time_since_last_check
=
71 base::Time::Now() - registration
->last_update_check();
72 if (time_since_last_check
> base::TimeDelta::FromHours(
73 kServiceWorkerScriptMaxCacheAgeInHours
) ||
74 version_
->force_bypass_cache_for_scripts()) {
75 extra_load_flags
= net::LOAD_BYPASS_CACHE
;
78 ServiceWorkerVersion
* stored_version
= registration
->waiting_version()
79 ? registration
->waiting_version()
80 : registration
->active_version();
81 int64 incumbent_response_id
= kInvalidServiceWorkerResourceId
;
82 if (stored_version
&& stored_version
->script_url() == request
->url()) {
83 incumbent_response_id
=
84 stored_version
->script_cache_map()->LookupResourceId(request
->url());
86 return new ServiceWorkerWriteToCacheJob(
87 request
, network_delegate
, resource_type_
, context_
, version_
.get(),
88 extra_load_flags
, response_id
, incumbent_response_id
);
91 int64 response_id
= kInvalidServiceWorkerResponseId
;
92 if (ShouldReadFromScriptCache(request
->url(), &response_id
)) {
93 return new ServiceWorkerReadFromCacheJob(
94 request
, network_delegate
, context_
, version_
, response_id
);
97 // NULL means use the network.
101 void ServiceWorkerContextRequestHandler::GetExtraResponseInfo(
102 ResourceResponseInfo
* response_info
) const {
103 response_info
->was_fetched_via_service_worker
= false;
104 response_info
->was_fallback_required_by_service_worker
= false;
105 response_info
->original_url_via_service_worker
= GURL();
106 response_info
->response_type_via_service_worker
=
107 blink::WebServiceWorkerResponseTypeDefault
;
110 bool ServiceWorkerContextRequestHandler::ShouldAddToScriptCache(
112 // We only write imports that occur during the initial eval.
113 if (version_
->status() != ServiceWorkerVersion::NEW
&&
114 version_
->status() != ServiceWorkerVersion::INSTALLING
) {
117 return version_
->script_cache_map()->LookupResourceId(url
) ==
118 kInvalidServiceWorkerResponseId
;
121 bool ServiceWorkerContextRequestHandler::ShouldReadFromScriptCache(
122 const GURL
& url
, int64
* response_id_out
) {
123 // We don't read from the script cache until the version is INSTALLED.
124 if (version_
->status() == ServiceWorkerVersion::NEW
||
125 version_
->status() == ServiceWorkerVersion::INSTALLING
)
127 *response_id_out
= version_
->script_cache_map()->LookupResourceId(url
);
128 return *response_id_out
!= kInvalidServiceWorkerResponseId
;
131 } // namespace content