OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "webkit/appcache/appcache_request_handler.h" | 5 #include "webkit/appcache/appcache_request_handler.h" |
6 | 6 |
7 #include "net/url_request/url_request.h" | 7 #include "net/url_request/url_request.h" |
8 #include "net/url_request/url_request_job.h" | 8 #include "net/url_request/url_request_job.h" |
9 #include "webkit/appcache/appcache.h" | 9 #include "webkit/appcache/appcache.h" |
10 #include "webkit/appcache/appcache_policy.h" | 10 #include "webkit/appcache/appcache_policy.h" |
(...skipping 18 matching lines...) Expand all Loading... |
29 } | 29 } |
30 } | 30 } |
31 | 31 |
32 AppCacheStorage* AppCacheRequestHandler::storage() const { | 32 AppCacheStorage* AppCacheRequestHandler::storage() const { |
33 DCHECK(host_); | 33 DCHECK(host_); |
34 return host_->service()->storage(); | 34 return host_->service()->storage(); |
35 } | 35 } |
36 | 36 |
37 void AppCacheRequestHandler::GetExtraResponseInfo( | 37 void AppCacheRequestHandler::GetExtraResponseInfo( |
38 int64* cache_id, GURL* manifest_url) { | 38 int64* cache_id, GURL* manifest_url) { |
39 if (job_ && job_->is_delivering_appcache_response()) { | 39 if (job_.get() && job_->is_delivering_appcache_response()) { |
40 *cache_id = job_->cache_id(); | 40 *cache_id = job_->cache_id(); |
41 *manifest_url = job_->manifest_url(); | 41 *manifest_url = job_->manifest_url(); |
42 } | 42 } |
43 } | 43 } |
44 | 44 |
45 AppCacheURLRequestJob* AppCacheRequestHandler::MaybeLoadResource( | 45 AppCacheURLRequestJob* AppCacheRequestHandler::MaybeLoadResource( |
46 net::URLRequest* request, net::NetworkDelegate* network_delegate) { | 46 net::URLRequest* request, net::NetworkDelegate* network_delegate) { |
47 maybe_load_resource_executed_ = true; | 47 maybe_load_resource_executed_ = true; |
48 if (!host_ || !IsSchemeAndMethodSupported(request) || cache_entry_not_found_) | 48 if (!host_ || !IsSchemeAndMethodSupported(request) || cache_entry_not_found_) |
49 return NULL; | 49 return NULL; |
50 | 50 |
51 // This method can get called multiple times over the life | 51 // This method can get called multiple times over the life |
52 // of a request. The case we detect here is having scheduled | 52 // of a request. The case we detect here is having scheduled |
53 // delivery of a "network response" using a job setup on an | 53 // delivery of a "network response" using a job setup on an |
54 // earlier call thru this method. To send the request thru | 54 // earlier call thru this method. To send the request thru |
55 // to the network involves restarting the request altogether, | 55 // to the network involves restarting the request altogether, |
56 // which will call thru to our interception layer again. | 56 // which will call thru to our interception layer again. |
57 // This time thru, we return NULL so the request hits the wire. | 57 // This time thru, we return NULL so the request hits the wire. |
58 if (job_) { | 58 if (job_.get()) { |
59 DCHECK(job_->is_delivering_network_response() || | 59 DCHECK(job_->is_delivering_network_response() || |
60 job_->cache_entry_not_found()); | 60 job_->cache_entry_not_found()); |
61 if (job_->cache_entry_not_found()) | 61 if (job_->cache_entry_not_found()) |
62 cache_entry_not_found_ = true; | 62 cache_entry_not_found_ = true; |
63 job_ = NULL; | 63 job_ = NULL; |
64 storage()->CancelDelegateCallbacks(this); | 64 storage()->CancelDelegateCallbacks(this); |
65 return NULL; | 65 return NULL; |
66 } | 66 } |
67 | 67 |
68 // Clear out our 'found' fields since we're starting a request for a | 68 // Clear out our 'found' fields since we're starting a request for a |
69 // new resource, any values in those fields are no longer valid. | 69 // new resource, any values in those fields are no longer valid. |
70 found_entry_ = AppCacheEntry(); | 70 found_entry_ = AppCacheEntry(); |
71 found_fallback_entry_ = AppCacheEntry(); | 71 found_fallback_entry_ = AppCacheEntry(); |
72 found_cache_id_ = kNoCacheId; | 72 found_cache_id_ = kNoCacheId; |
73 found_manifest_url_ = GURL(); | 73 found_manifest_url_ = GURL(); |
74 found_network_namespace_ = false; | 74 found_network_namespace_ = false; |
75 | 75 |
76 if (is_main_resource()) | 76 if (is_main_resource()) |
77 MaybeLoadMainResource(request, network_delegate); | 77 MaybeLoadMainResource(request, network_delegate); |
78 else | 78 else |
79 MaybeLoadSubResource(request, network_delegate); | 79 MaybeLoadSubResource(request, network_delegate); |
80 | 80 |
81 // If its been setup to deliver a network response, we can just delete | 81 // If its been setup to deliver a network response, we can just delete |
82 // it now and return NULL instead to achieve that since it couldn't | 82 // it now and return NULL instead to achieve that since it couldn't |
83 // have been started yet. | 83 // have been started yet. |
84 if (job_ && job_->is_delivering_network_response()) { | 84 if (job_.get() && job_->is_delivering_network_response()) { |
85 DCHECK(!job_->has_been_started()); | 85 DCHECK(!job_->has_been_started()); |
86 job_ = NULL; | 86 job_ = NULL; |
87 } | 87 } |
88 | 88 |
89 return job_; | 89 return job_.get(); |
90 } | 90 } |
91 | 91 |
92 AppCacheURLRequestJob* AppCacheRequestHandler::MaybeLoadFallbackForRedirect( | 92 AppCacheURLRequestJob* AppCacheRequestHandler::MaybeLoadFallbackForRedirect( |
93 net::URLRequest* request, | 93 net::URLRequest* request, |
94 net::NetworkDelegate* network_delegate, | 94 net::NetworkDelegate* network_delegate, |
95 const GURL& location) { | 95 const GURL& location) { |
96 if (!host_ || !IsSchemeAndMethodSupported(request) || cache_entry_not_found_) | 96 if (!host_ || !IsSchemeAndMethodSupported(request) || cache_entry_not_found_) |
97 return NULL; | 97 return NULL; |
98 if (is_main_resource()) | 98 if (is_main_resource()) |
99 return NULL; | 99 return NULL; |
100 // TODO(vabr) This is a temporary fix (see crbug/141114). We should get rid of | 100 // TODO(vabr) This is a temporary fix (see crbug/141114). We should get rid of |
101 // it once a more general solution to crbug/121325 is in place. | 101 // it once a more general solution to crbug/121325 is in place. |
102 if (!maybe_load_resource_executed_) | 102 if (!maybe_load_resource_executed_) |
103 return NULL; | 103 return NULL; |
104 if (request->url().GetOrigin() == location.GetOrigin()) | 104 if (request->url().GetOrigin() == location.GetOrigin()) |
105 return NULL; | 105 return NULL; |
106 | 106 |
107 DCHECK(!job_); // our jobs never generate redirects | 107 DCHECK(!job_.get()); // our jobs never generate redirects |
108 | 108 |
109 if (found_fallback_entry_.has_response_id()) { | 109 if (found_fallback_entry_.has_response_id()) { |
110 // 6.9.6, step 4: If this results in a redirect to another origin, | 110 // 6.9.6, step 4: If this results in a redirect to another origin, |
111 // get the resource of the fallback entry. | 111 // get the resource of the fallback entry. |
112 job_ = new AppCacheURLRequestJob(request, network_delegate, storage()); | 112 job_ = new AppCacheURLRequestJob(request, network_delegate, storage()); |
113 DeliverAppCachedResponse( | 113 DeliverAppCachedResponse( |
114 found_fallback_entry_, found_cache_id_, found_group_id_, | 114 found_fallback_entry_, found_cache_id_, found_group_id_, |
115 found_manifest_url_, true, found_namespace_entry_url_); | 115 found_manifest_url_, true, found_namespace_entry_url_); |
116 } else if (!found_network_namespace_) { | 116 } else if (!found_network_namespace_) { |
117 // 6.9.6, step 6: Fail the resource load. | 117 // 6.9.6, step 6: Fail the resource load. |
118 job_ = new AppCacheURLRequestJob(request, network_delegate, storage()); | 118 job_ = new AppCacheURLRequestJob(request, network_delegate, storage()); |
119 DeliverErrorResponse(); | 119 DeliverErrorResponse(); |
120 } else { | 120 } else { |
121 // 6.9.6 step 3 and 5: Fetch the resource normally. | 121 // 6.9.6 step 3 and 5: Fetch the resource normally. |
122 } | 122 } |
123 | 123 |
124 return job_; | 124 return job_.get(); |
125 } | 125 } |
126 | 126 |
127 AppCacheURLRequestJob* AppCacheRequestHandler::MaybeLoadFallbackForResponse( | 127 AppCacheURLRequestJob* AppCacheRequestHandler::MaybeLoadFallbackForResponse( |
128 net::URLRequest* request, net::NetworkDelegate* network_delegate) { | 128 net::URLRequest* request, net::NetworkDelegate* network_delegate) { |
129 if (!host_ || !IsSchemeAndMethodSupported(request) || cache_entry_not_found_) | 129 if (!host_ || !IsSchemeAndMethodSupported(request) || cache_entry_not_found_) |
130 return NULL; | 130 return NULL; |
131 if (!found_fallback_entry_.has_response_id()) | 131 if (!found_fallback_entry_.has_response_id()) |
132 return NULL; | 132 return NULL; |
133 | 133 |
134 if (request->status().status() == net::URLRequestStatus::CANCELED) { | 134 if (request->status().status() == net::URLRequestStatus::CANCELED) { |
135 // 6.9.6, step 4: But not if the user canceled the download. | 135 // 6.9.6, step 4: But not if the user canceled the download. |
136 return NULL; | 136 return NULL; |
137 } | 137 } |
138 | 138 |
139 // We don't fallback for responses that we delivered. | 139 // We don't fallback for responses that we delivered. |
140 if (job_) { | 140 if (job_.get()) { |
141 DCHECK(!job_->is_delivering_network_response()); | 141 DCHECK(!job_->is_delivering_network_response()); |
142 return NULL; | 142 return NULL; |
143 } | 143 } |
144 | 144 |
145 if (request->status().is_success()) { | 145 if (request->status().is_success()) { |
146 int code_major = request->GetResponseCode() / 100; | 146 int code_major = request->GetResponseCode() / 100; |
147 if (code_major !=4 && code_major != 5) | 147 if (code_major !=4 && code_major != 5) |
148 return NULL; | 148 return NULL; |
149 | 149 |
150 // Servers can override the fallback behavior with a response header. | 150 // Servers can override the fallback behavior with a response header. |
151 const std::string kFallbackOverrideHeader( | 151 const std::string kFallbackOverrideHeader( |
152 "x-chromium-appcache-fallback-override"); | 152 "x-chromium-appcache-fallback-override"); |
153 const std::string kFallbackOverrideValue( | 153 const std::string kFallbackOverrideValue( |
154 "disallow-fallback"); | 154 "disallow-fallback"); |
155 std::string header_value; | 155 std::string header_value; |
156 request->GetResponseHeaderByName(kFallbackOverrideHeader, &header_value); | 156 request->GetResponseHeaderByName(kFallbackOverrideHeader, &header_value); |
157 if (header_value == kFallbackOverrideValue) | 157 if (header_value == kFallbackOverrideValue) |
158 return NULL; | 158 return NULL; |
159 } | 159 } |
160 | 160 |
161 // 6.9.6, step 4: If this results in a 4xx or 5xx status code | 161 // 6.9.6, step 4: If this results in a 4xx or 5xx status code |
162 // or there were network errors, get the resource of the fallback entry. | 162 // or there were network errors, get the resource of the fallback entry. |
163 job_ = new AppCacheURLRequestJob(request, network_delegate, storage()); | 163 job_ = new AppCacheURLRequestJob(request, network_delegate, storage()); |
164 DeliverAppCachedResponse( | 164 DeliverAppCachedResponse( |
165 found_fallback_entry_, found_cache_id_, found_group_id_, | 165 found_fallback_entry_, found_cache_id_, found_group_id_, |
166 found_manifest_url_, true, found_namespace_entry_url_); | 166 found_manifest_url_, true, found_namespace_entry_url_); |
167 return job_; | 167 return job_.get(); |
168 } | 168 } |
169 | 169 |
170 void AppCacheRequestHandler::OnDestructionImminent(AppCacheHost* host) { | 170 void AppCacheRequestHandler::OnDestructionImminent(AppCacheHost* host) { |
171 storage()->CancelDelegateCallbacks(this); | 171 storage()->CancelDelegateCallbacks(this); |
172 host_ = NULL; // no need to RemoveObserver, the host is being deleted | 172 host_ = NULL; // no need to RemoveObserver, the host is being deleted |
173 | 173 |
174 // Since the host is being deleted, we don't have to complete any job | 174 // Since the host is being deleted, we don't have to complete any job |
175 // that is current running. It's destined for the bit bucket anyway. | 175 // that is current running. It's destined for the bit bucket anyway. |
176 if (job_) { | 176 if (job_.get()) { |
177 job_->Kill(); | 177 job_->Kill(); |
178 job_ = NULL; | 178 job_ = NULL; |
179 } | 179 } |
180 } | 180 } |
181 | 181 |
182 void AppCacheRequestHandler::DeliverAppCachedResponse( | 182 void AppCacheRequestHandler::DeliverAppCachedResponse( |
183 const AppCacheEntry& entry, int64 cache_id, int64 group_id, | 183 const AppCacheEntry& entry, int64 cache_id, int64 group_id, |
184 const GURL& manifest_url, bool is_fallback, | 184 const GURL& manifest_url, bool is_fallback, |
185 const GURL& namespace_entry_url) { | 185 const GURL& namespace_entry_url) { |
186 DCHECK(host_ && job_ && job_->is_waiting()); | 186 DCHECK(host_ && job_.get() && job_->is_waiting()); |
187 DCHECK(entry.has_response_id()); | 187 DCHECK(entry.has_response_id()); |
188 | 188 |
189 if (ResourceType::IsFrame(resource_type_) && !namespace_entry_url.is_empty()) | 189 if (ResourceType::IsFrame(resource_type_) && !namespace_entry_url.is_empty()) |
190 host_->NotifyMainResourceIsNamespaceEntry(namespace_entry_url); | 190 host_->NotifyMainResourceIsNamespaceEntry(namespace_entry_url); |
191 | 191 |
192 job_->DeliverAppCachedResponse(manifest_url, group_id, cache_id, | 192 job_->DeliverAppCachedResponse(manifest_url, group_id, cache_id, |
193 entry, is_fallback); | 193 entry, is_fallback); |
194 } | 194 } |
195 | 195 |
196 void AppCacheRequestHandler::DeliverErrorResponse() { | 196 void AppCacheRequestHandler::DeliverErrorResponse() { |
197 DCHECK(job_ && job_->is_waiting()); | 197 DCHECK(job_.get() && job_->is_waiting()); |
198 job_->DeliverErrorResponse(); | 198 job_->DeliverErrorResponse(); |
199 } | 199 } |
200 | 200 |
201 void AppCacheRequestHandler::DeliverNetworkResponse() { | 201 void AppCacheRequestHandler::DeliverNetworkResponse() { |
202 DCHECK(job_ && job_->is_waiting()); | 202 DCHECK(job_.get() && job_->is_waiting()); |
203 job_->DeliverNetworkResponse(); | 203 job_->DeliverNetworkResponse(); |
204 } | 204 } |
205 | 205 |
206 // Main-resource handling ---------------------------------------------- | 206 // Main-resource handling ---------------------------------------------- |
207 | 207 |
208 void AppCacheRequestHandler::MaybeLoadMainResource( | 208 void AppCacheRequestHandler::MaybeLoadMainResource( |
209 net::URLRequest* request, net::NetworkDelegate* network_delegate) { | 209 net::URLRequest* request, net::NetworkDelegate* network_delegate) { |
210 DCHECK(!job_); | 210 DCHECK(!job_.get()); |
211 DCHECK(host_); | 211 DCHECK(host_); |
212 | 212 |
213 const AppCacheHost* spawning_host = | 213 const AppCacheHost* spawning_host = |
214 ResourceType::IsSharedWorker(resource_type_) ? | 214 ResourceType::IsSharedWorker(resource_type_) ? |
215 host_ : host_->GetSpawningHost(); | 215 host_ : host_->GetSpawningHost(); |
216 GURL preferred_manifest_url = spawning_host ? | 216 GURL preferred_manifest_url = spawning_host ? |
217 spawning_host->preferred_manifest_url() : GURL(); | 217 spawning_host->preferred_manifest_url() : GURL(); |
218 | 218 |
219 // We may have to wait for our storage query to complete, but | 219 // We may have to wait for our storage query to complete, but |
220 // this query can also complete syncrhonously. | 220 // this query can also complete syncrhonously. |
221 job_ = new AppCacheURLRequestJob(request, network_delegate, storage()); | 221 job_ = new AppCacheURLRequestJob(request, network_delegate, storage()); |
222 storage()->FindResponseForMainRequest( | 222 storage()->FindResponseForMainRequest( |
223 request->url(), preferred_manifest_url, this); | 223 request->url(), preferred_manifest_url, this); |
224 } | 224 } |
225 | 225 |
226 void AppCacheRequestHandler::OnMainResponseFound( | 226 void AppCacheRequestHandler::OnMainResponseFound( |
227 const GURL& url, const AppCacheEntry& entry, | 227 const GURL& url, const AppCacheEntry& entry, |
228 const GURL& namespace_entry_url, const AppCacheEntry& fallback_entry, | 228 const GURL& namespace_entry_url, const AppCacheEntry& fallback_entry, |
229 int64 cache_id, int64 group_id, const GURL& manifest_url) { | 229 int64 cache_id, int64 group_id, const GURL& manifest_url) { |
230 DCHECK(job_); | 230 DCHECK(job_.get()); |
231 DCHECK(host_); | 231 DCHECK(host_); |
232 DCHECK(is_main_resource()); | 232 DCHECK(is_main_resource()); |
233 DCHECK(!entry.IsForeign()); | 233 DCHECK(!entry.IsForeign()); |
234 DCHECK(!fallback_entry.IsForeign()); | 234 DCHECK(!fallback_entry.IsForeign()); |
235 DCHECK(!(entry.has_response_id() && fallback_entry.has_response_id())); | 235 DCHECK(!(entry.has_response_id() && fallback_entry.has_response_id())); |
236 | 236 |
237 if (!job_) | 237 if (!job_.get()) |
238 return; | 238 return; |
239 | 239 |
240 AppCachePolicy* policy = host_->service()->appcache_policy(); | 240 AppCachePolicy* policy = host_->service()->appcache_policy(); |
241 bool was_blocked_by_policy = !manifest_url.is_empty() && policy && | 241 bool was_blocked_by_policy = !manifest_url.is_empty() && policy && |
242 !policy->CanLoadAppCache(manifest_url, host_->first_party_url()); | 242 !policy->CanLoadAppCache(manifest_url, host_->first_party_url()); |
243 | 243 |
244 if (was_blocked_by_policy) { | 244 if (was_blocked_by_policy) { |
245 if (ResourceType::IsFrame(resource_type_)) { | 245 if (ResourceType::IsFrame(resource_type_)) { |
246 host_->NotifyMainResourceBlocked(manifest_url); | 246 host_->NotifyMainResourceBlocked(manifest_url); |
247 } else { | 247 } else { |
(...skipping 30 matching lines...) Expand all Loading... |
278 false, found_namespace_entry_url_); | 278 false, found_namespace_entry_url_); |
279 } else { | 279 } else { |
280 DeliverNetworkResponse(); | 280 DeliverNetworkResponse(); |
281 } | 281 } |
282 } | 282 } |
283 | 283 |
284 // Sub-resource handling ---------------------------------------------- | 284 // Sub-resource handling ---------------------------------------------- |
285 | 285 |
286 void AppCacheRequestHandler::MaybeLoadSubResource( | 286 void AppCacheRequestHandler::MaybeLoadSubResource( |
287 net::URLRequest* request, net::NetworkDelegate* network_delegate) { | 287 net::URLRequest* request, net::NetworkDelegate* network_delegate) { |
288 DCHECK(!job_); | 288 DCHECK(!job_.get()); |
289 | 289 |
290 if (host_->is_selection_pending()) { | 290 if (host_->is_selection_pending()) { |
291 // We have to wait until cache selection is complete and the | 291 // We have to wait until cache selection is complete and the |
292 // selected cache is loaded. | 292 // selected cache is loaded. |
293 is_waiting_for_cache_selection_ = true; | 293 is_waiting_for_cache_selection_ = true; |
294 job_ = new AppCacheURLRequestJob(request, network_delegate, storage()); | 294 job_ = new AppCacheURLRequestJob(request, network_delegate, storage()); |
295 return; | 295 return; |
296 } | 296 } |
297 | 297 |
298 if (!host_->associated_cache() || | 298 if (!host_->associated_cache() || |
299 !host_->associated_cache()->is_complete()) { | 299 !host_->associated_cache()->is_complete()) { |
300 return; | 300 return; |
301 } | 301 } |
302 | 302 |
303 job_ = new AppCacheURLRequestJob(request, network_delegate, storage()); | 303 job_ = new AppCacheURLRequestJob(request, network_delegate, storage()); |
304 ContinueMaybeLoadSubResource(); | 304 ContinueMaybeLoadSubResource(); |
305 } | 305 } |
306 | 306 |
307 void AppCacheRequestHandler::ContinueMaybeLoadSubResource() { | 307 void AppCacheRequestHandler::ContinueMaybeLoadSubResource() { |
308 // 6.9.6 Changes to the networking model | 308 // 6.9.6 Changes to the networking model |
309 // If the resource is not to be fetched using the HTTP GET mechanism or | 309 // If the resource is not to be fetched using the HTTP GET mechanism or |
310 // equivalent ... then fetch the resource normally. | 310 // equivalent ... then fetch the resource normally. |
311 DCHECK(job_); | 311 DCHECK(job_.get()); |
312 DCHECK(host_->associated_cache() && | 312 DCHECK(host_->associated_cache() && host_->associated_cache()->is_complete()); |
313 host_->associated_cache()->is_complete()); | |
314 | 313 |
315 const GURL& url = job_->request()->url(); | 314 const GURL& url = job_->request()->url(); |
316 AppCache* cache = host_->associated_cache(); | 315 AppCache* cache = host_->associated_cache(); |
317 storage()->FindResponseForSubRequest( | 316 storage()->FindResponseForSubRequest( |
318 host_->associated_cache(), url, | 317 host_->associated_cache(), url, |
319 &found_entry_, &found_fallback_entry_, &found_network_namespace_); | 318 &found_entry_, &found_fallback_entry_, &found_network_namespace_); |
320 | 319 |
321 if (found_entry_.has_response_id()) { | 320 if (found_entry_.has_response_id()) { |
322 // Step 2: If there's an entry, get it instead. | 321 // Step 2: If there's an entry, get it instead. |
323 DCHECK(!found_network_namespace_ && | 322 DCHECK(!found_network_namespace_ && |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
366 if (!host_->associated_cache() || | 365 if (!host_->associated_cache() || |
367 !host_->associated_cache()->is_complete()) { | 366 !host_->associated_cache()->is_complete()) { |
368 DeliverNetworkResponse(); | 367 DeliverNetworkResponse(); |
369 return; | 368 return; |
370 } | 369 } |
371 | 370 |
372 ContinueMaybeLoadSubResource(); | 371 ContinueMaybeLoadSubResource(); |
373 } | 372 } |
374 | 373 |
375 } // namespace appcache | 374 } // namespace appcache |
OLD | NEW |