OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 "content/browser/appcache/appcache_update_job.h" | 5 #include "content/browser/appcache/appcache_update_job.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/bind_helpers.h" | 8 #include "base/bind_helpers.h" |
9 #include "base/compiler_specific.h" | 9 #include "base/compiler_specific.h" |
10 #include "base/location.h" | 10 #include "base/location.h" |
(...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
179 void AppCacheUpdateJob::URLFetcher::OnReceivedRedirect( | 179 void AppCacheUpdateJob::URLFetcher::OnReceivedRedirect( |
180 net::URLRequest* request, | 180 net::URLRequest* request, |
181 const net::RedirectInfo& redirect_info, | 181 const net::RedirectInfo& redirect_info, |
182 bool* defer_redirect) { | 182 bool* defer_redirect) { |
183 DCHECK_EQ(request_.get(), request); | 183 DCHECK_EQ(request_.get(), request); |
184 // Redirect is not allowed by the update process. | 184 // Redirect is not allowed by the update process. |
185 job_->MadeProgress(); | 185 job_->MadeProgress(); |
186 redirect_response_code_ = request->GetResponseCode(); | 186 redirect_response_code_ = request->GetResponseCode(); |
187 request->Cancel(); | 187 request->Cancel(); |
188 result_ = REDIRECT_ERROR; | 188 result_ = REDIRECT_ERROR; |
189 OnResponseCompleted(); | 189 OnResponseCompleted(net::ERR_ABORTED); |
190 } | 190 } |
191 | 191 |
192 void AppCacheUpdateJob::URLFetcher::OnResponseStarted( | 192 void AppCacheUpdateJob::URLFetcher::OnResponseStarted(net::URLRequest* request, |
193 net::URLRequest *request) { | 193 int net_error) { |
194 DCHECK_EQ(request_.get(), request); | 194 DCHECK_EQ(request_.get(), request); |
| 195 DCHECK_NE(net::ERR_IO_PENDING, net_error); |
| 196 |
195 int response_code = -1; | 197 int response_code = -1; |
196 if (request->status().is_success()) { | 198 if (net_error == net::OK) { |
197 response_code = request->GetResponseCode(); | 199 response_code = request->GetResponseCode(); |
198 job_->MadeProgress(); | 200 job_->MadeProgress(); |
199 } | 201 } |
200 | 202 |
201 if ((response_code / 100) != 2) { | 203 if ((response_code / 100) != 2) { |
202 if (response_code > 0) | 204 if (response_code > 0) |
203 result_ = SERVER_ERROR; | 205 result_ = SERVER_ERROR; |
204 else | 206 else |
205 result_ = NETWORK_ERROR; | 207 result_ = NETWORK_ERROR; |
206 OnResponseCompleted(); | 208 OnResponseCompleted(net_error); |
207 return; | 209 return; |
208 } | 210 } |
209 | 211 |
210 if (url_.SchemeIsCryptographic()) { | 212 if (url_.SchemeIsCryptographic()) { |
211 // Do not cache content with cert errors. | 213 // Do not cache content with cert errors. |
212 // Also, we willfully violate the HTML5 spec at this point in order | 214 // Also, we willfully violate the HTML5 spec at this point in order |
213 // to support the appcaching of cross-origin HTTPS resources. | 215 // to support the appcaching of cross-origin HTTPS resources. |
214 // We've opted for a milder constraint and allow caching unless | 216 // We've opted for a milder constraint and allow caching unless |
215 // the resource has a "no-store" header. A spec change has been | 217 // the resource has a "no-store" header. A spec change has been |
216 // requested on the whatwg list. | 218 // requested on the whatwg list. |
217 // See http://code.google.com/p/chromium/issues/detail?id=69594 | 219 // See http://code.google.com/p/chromium/issues/detail?id=69594 |
218 // TODO(michaeln): Consider doing this for cross-origin HTTP too. | 220 // TODO(michaeln): Consider doing this for cross-origin HTTP too. |
219 const net::HttpNetworkSession::Params* session_params = | 221 const net::HttpNetworkSession::Params* session_params = |
220 request->context()->GetNetworkSessionParams(); | 222 request->context()->GetNetworkSessionParams(); |
221 bool ignore_cert_errors = session_params && | 223 bool ignore_cert_errors = session_params && |
222 session_params->ignore_certificate_errors; | 224 session_params->ignore_certificate_errors; |
223 if ((net::IsCertStatusError(request->ssl_info().cert_status) && | 225 if ((net::IsCertStatusError(request->ssl_info().cert_status) && |
224 !ignore_cert_errors) || | 226 !ignore_cert_errors) || |
225 (url_.GetOrigin() != job_->manifest_url_.GetOrigin() && | 227 (url_.GetOrigin() != job_->manifest_url_.GetOrigin() && |
226 request->response_headers()-> | 228 request->response_headers()-> |
227 HasHeaderValue("cache-control", "no-store"))) { | 229 HasHeaderValue("cache-control", "no-store"))) { |
228 DCHECK_EQ(-1, redirect_response_code_); | 230 DCHECK_EQ(-1, redirect_response_code_); |
229 request->Cancel(); | 231 request->Cancel(); |
230 result_ = SECURITY_ERROR; | 232 result_ = SECURITY_ERROR; |
231 OnResponseCompleted(); | 233 OnResponseCompleted(net::ERR_ABORTED); |
232 return; | 234 return; |
233 } | 235 } |
234 } | 236 } |
235 | 237 |
236 // Write response info to storage for URL fetches. Wait for async write | 238 // Write response info to storage for URL fetches. Wait for async write |
237 // completion before reading any response data. | 239 // completion before reading any response data. |
238 if (fetch_type_ == URL_FETCH || fetch_type_ == MASTER_ENTRY_FETCH) { | 240 if (fetch_type_ == URL_FETCH || fetch_type_ == MASTER_ENTRY_FETCH) { |
239 response_writer_.reset(job_->CreateResponseWriter()); | 241 response_writer_.reset(job_->CreateResponseWriter()); |
240 scoped_refptr<HttpResponseInfoIOBuffer> io_buffer( | 242 scoped_refptr<HttpResponseInfoIOBuffer> io_buffer( |
241 new HttpResponseInfoIOBuffer( | 243 new HttpResponseInfoIOBuffer( |
242 new net::HttpResponseInfo(request->response_info()))); | 244 new net::HttpResponseInfo(request->response_info()))); |
243 response_writer_->WriteInfo( | 245 response_writer_->WriteInfo( |
244 io_buffer.get(), | 246 io_buffer.get(), |
245 base::Bind(&URLFetcher::OnWriteComplete, base::Unretained(this))); | 247 base::Bind(&URLFetcher::OnWriteComplete, base::Unretained(this))); |
246 } else { | 248 } else { |
247 ReadResponseData(); | 249 ReadResponseData(); |
248 } | 250 } |
249 } | 251 } |
250 | 252 |
251 void AppCacheUpdateJob::URLFetcher::OnReadCompleted( | 253 void AppCacheUpdateJob::URLFetcher::OnReadCompleted( |
252 net::URLRequest* request, int bytes_read) { | 254 net::URLRequest* request, int bytes_read) { |
| 255 DCHECK_NE(net::ERR_IO_PENDING, bytes_read); |
253 DCHECK_EQ(request_.get(), request); | 256 DCHECK_EQ(request_.get(), request); |
254 bool data_consumed = true; | 257 bool data_consumed = true; |
255 if (request->status().is_success() && bytes_read > 0) { | 258 if (bytes_read > 0) { |
256 job_->MadeProgress(); | 259 job_->MadeProgress(); |
257 data_consumed = ConsumeResponseData(bytes_read); | 260 data_consumed = ConsumeResponseData(bytes_read); |
258 if (data_consumed) { | 261 if (data_consumed) { |
259 bytes_read = 0; | 262 while (true) { |
260 while (request->Read(buffer_.get(), kBufferSize, &bytes_read)) { | 263 bytes_read = request->Read(buffer_.get(), kBufferSize); |
261 if (bytes_read > 0) { | 264 if (bytes_read <= 0) |
262 data_consumed = ConsumeResponseData(bytes_read); | |
263 if (!data_consumed) | |
264 break; // wait for async data processing, then read more | |
265 } else { | |
266 break; | 265 break; |
267 } | 266 data_consumed = ConsumeResponseData(bytes_read); |
| 267 if (!data_consumed) |
| 268 break; |
268 } | 269 } |
269 } | 270 } |
270 } | 271 } |
271 if (data_consumed && !request->status().is_io_pending()) { | 272 |
| 273 if (data_consumed && bytes_read != net::ERR_IO_PENDING) { |
272 DCHECK_EQ(UPDATE_OK, result_); | 274 DCHECK_EQ(UPDATE_OK, result_); |
273 OnResponseCompleted(); | 275 OnResponseCompleted(bytes_read); |
274 } | 276 } |
275 } | 277 } |
276 | 278 |
277 void AppCacheUpdateJob::URLFetcher::AddConditionalHeaders( | 279 void AppCacheUpdateJob::URLFetcher::AddConditionalHeaders( |
278 const net::HttpResponseHeaders* headers) { | 280 const net::HttpResponseHeaders* headers) { |
279 DCHECK(request_); | 281 DCHECK(request_); |
280 DCHECK(headers); | 282 DCHECK(headers); |
281 net::HttpRequestHeaders extra_headers; | 283 net::HttpRequestHeaders extra_headers; |
282 | 284 |
283 // Add If-Modified-Since header if response info has Last-Modified header. | 285 // Add If-Modified-Since header if response info has Last-Modified header. |
(...skipping 14 matching lines...) Expand all Loading... |
298 etag_value); | 300 etag_value); |
299 } | 301 } |
300 if (!extra_headers.IsEmpty()) | 302 if (!extra_headers.IsEmpty()) |
301 request_->SetExtraRequestHeaders(extra_headers); | 303 request_->SetExtraRequestHeaders(extra_headers); |
302 } | 304 } |
303 | 305 |
304 void AppCacheUpdateJob::URLFetcher::OnWriteComplete(int result) { | 306 void AppCacheUpdateJob::URLFetcher::OnWriteComplete(int result) { |
305 if (result < 0) { | 307 if (result < 0) { |
306 request_->Cancel(); | 308 request_->Cancel(); |
307 result_ = DISKCACHE_ERROR; | 309 result_ = DISKCACHE_ERROR; |
308 OnResponseCompleted(); | 310 OnResponseCompleted(net::ERR_ABORTED); |
309 return; | 311 return; |
310 } | 312 } |
311 ReadResponseData(); | 313 ReadResponseData(); |
312 } | 314 } |
313 | 315 |
314 void AppCacheUpdateJob::URLFetcher::ReadResponseData() { | 316 void AppCacheUpdateJob::URLFetcher::ReadResponseData() { |
315 InternalUpdateState state = job_->internal_state_; | 317 InternalUpdateState state = job_->internal_state_; |
316 if (state == CACHE_FAILURE || state == CANCELLED || state == COMPLETED) | 318 if (state == CACHE_FAILURE || state == CANCELLED || state == COMPLETED) |
317 return; | 319 return; |
318 int bytes_read = 0; | 320 int bytes_read = request_->Read(buffer_.get(), kBufferSize); |
319 request_->Read(buffer_.get(), kBufferSize, &bytes_read); | 321 if (bytes_read != net::ERR_IO_PENDING) |
320 OnReadCompleted(request_.get(), bytes_read); | 322 OnReadCompleted(request_.get(), bytes_read); |
321 } | 323 } |
322 | 324 |
323 // Returns false if response data is processed asynchronously, in which | 325 // Returns false if response data is processed asynchronously, in which |
324 // case ReadResponseData will be invoked when it is safe to continue | 326 // case ReadResponseData will be invoked when it is safe to continue |
325 // reading more response data from the request. | 327 // reading more response data from the request. |
326 bool AppCacheUpdateJob::URLFetcher::ConsumeResponseData(int bytes_read) { | 328 bool AppCacheUpdateJob::URLFetcher::ConsumeResponseData(int bytes_read) { |
327 DCHECK_GT(bytes_read, 0); | 329 DCHECK_GT(bytes_read, 0); |
328 switch (fetch_type_) { | 330 switch (fetch_type_) { |
329 case MANIFEST_FETCH: | 331 case MANIFEST_FETCH: |
330 case MANIFEST_REFETCH: | 332 case MANIFEST_REFETCH: |
331 manifest_data_.append(buffer_->data(), bytes_read); | 333 manifest_data_.append(buffer_->data(), bytes_read); |
332 break; | 334 break; |
333 case URL_FETCH: | 335 case URL_FETCH: |
334 case MASTER_ENTRY_FETCH: | 336 case MASTER_ENTRY_FETCH: |
335 DCHECK(response_writer_.get()); | 337 DCHECK(response_writer_.get()); |
336 response_writer_->WriteData( | 338 response_writer_->WriteData( |
337 buffer_.get(), | 339 buffer_.get(), |
338 bytes_read, | 340 bytes_read, |
339 base::Bind(&URLFetcher::OnWriteComplete, base::Unretained(this))); | 341 base::Bind(&URLFetcher::OnWriteComplete, base::Unretained(this))); |
340 return false; // wait for async write completion to continue reading | 342 return false; // wait for async write completion to continue reading |
341 default: | 343 default: |
342 NOTREACHED(); | 344 NOTREACHED(); |
343 } | 345 } |
344 return true; | 346 return true; |
345 } | 347 } |
346 | 348 |
347 void AppCacheUpdateJob::URLFetcher::OnResponseCompleted() { | 349 void AppCacheUpdateJob::URLFetcher::OnResponseCompleted(int net_error) { |
348 if (request_->status().is_success()) | 350 if (net_error == net::OK) |
349 job_->MadeProgress(); | 351 job_->MadeProgress(); |
350 | 352 |
351 // Retry for 503s where retry-after is 0. | 353 // Retry for 503s where retry-after is 0. |
352 if (request_->status().is_success() && | 354 if (net_error == net::OK && request_->GetResponseCode() == 503 && |
353 request_->GetResponseCode() == 503 && | |
354 MaybeRetryRequest()) { | 355 MaybeRetryRequest()) { |
355 return; | 356 return; |
356 } | 357 } |
357 | 358 |
358 switch (fetch_type_) { | 359 switch (fetch_type_) { |
359 case MANIFEST_FETCH: | 360 case MANIFEST_FETCH: |
360 job_->HandleManifestFetchCompleted(this); | 361 job_->HandleManifestFetchCompleted(this, net_error); |
361 break; | 362 break; |
362 case URL_FETCH: | 363 case URL_FETCH: |
363 job_->HandleUrlFetchCompleted(this); | 364 job_->HandleUrlFetchCompleted(this, net_error); |
364 break; | 365 break; |
365 case MASTER_ENTRY_FETCH: | 366 case MASTER_ENTRY_FETCH: |
366 job_->HandleMasterEntryFetchCompleted(this); | 367 job_->HandleMasterEntryFetchCompleted(this, net_error); |
367 break; | 368 break; |
368 case MANIFEST_REFETCH: | 369 case MANIFEST_REFETCH: |
369 job_->HandleManifestRefetchCompleted(this); | 370 job_->HandleManifestRefetchCompleted(this, net_error); |
370 break; | 371 break; |
371 default: | 372 default: |
372 NOTREACHED(); | 373 NOTREACHED(); |
373 } | 374 } |
374 | 375 |
375 delete this; | 376 delete this; |
376 } | 377 } |
377 | 378 |
378 bool AppCacheUpdateJob::URLFetcher::MaybeRetryRequest() { | 379 bool AppCacheUpdateJob::URLFetcher::MaybeRetryRequest() { |
379 if (retry_503_attempts_ >= kMax503Retries || | 380 if (retry_503_attempts_ >= kMax503Retries || |
(...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
572 return; | 573 return; |
573 } | 574 } |
574 | 575 |
575 DCHECK(internal_state_ == REFETCH_MANIFEST); | 576 DCHECK(internal_state_ == REFETCH_MANIFEST); |
576 DCHECK(manifest_response_info_.get()); | 577 DCHECK(manifest_response_info_.get()); |
577 manifest_fetcher_->set_existing_response_headers( | 578 manifest_fetcher_->set_existing_response_headers( |
578 manifest_response_info_->headers.get()); | 579 manifest_response_info_->headers.get()); |
579 manifest_fetcher_->Start(); | 580 manifest_fetcher_->Start(); |
580 } | 581 } |
581 | 582 |
582 | 583 void AppCacheUpdateJob::HandleManifestFetchCompleted(URLFetcher* fetcher, |
583 void AppCacheUpdateJob::HandleManifestFetchCompleted( | 584 int net_error) { |
584 URLFetcher* fetcher) { | |
585 DCHECK_EQ(internal_state_, FETCH_MANIFEST); | 585 DCHECK_EQ(internal_state_, FETCH_MANIFEST); |
586 DCHECK_EQ(manifest_fetcher_, fetcher); | 586 DCHECK_EQ(manifest_fetcher_, fetcher); |
| 587 |
587 manifest_fetcher_ = NULL; | 588 manifest_fetcher_ = NULL; |
588 | 589 |
589 net::URLRequest* request = fetcher->request(); | 590 net::URLRequest* request = fetcher->request(); |
590 int response_code = -1; | 591 int response_code = -1; |
591 bool is_valid_response_code = false; | 592 bool is_valid_response_code = false; |
592 if (request->status().is_success()) { | 593 if (net_error == net::OK) { |
593 response_code = request->GetResponseCode(); | 594 response_code = request->GetResponseCode(); |
594 is_valid_response_code = (response_code / 100 == 2); | 595 is_valid_response_code = (response_code / 100 == 2); |
595 | 596 |
596 std::string mime_type; | 597 std::string mime_type; |
597 request->GetMimeType(&mime_type); | 598 request->GetMimeType(&mime_type); |
598 manifest_has_valid_mime_type_ = (mime_type == "text/cache-manifest"); | 599 manifest_has_valid_mime_type_ = (mime_type == "text/cache-manifest"); |
599 } | 600 } |
600 | 601 |
601 if (is_valid_response_code) { | 602 if (is_valid_response_code) { |
602 manifest_data_ = fetcher->manifest_data(); | 603 manifest_data_ = fetcher->manifest_data(); |
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
710 LogConsoleMessageToAll(message); | 711 LogConsoleMessageToAll(message); |
711 } | 712 } |
712 | 713 |
713 group_->SetUpdateAppCacheStatus(AppCacheGroup::DOWNLOADING); | 714 group_->SetUpdateAppCacheStatus(AppCacheGroup::DOWNLOADING); |
714 NotifyAllAssociatedHosts(APPCACHE_DOWNLOADING_EVENT); | 715 NotifyAllAssociatedHosts(APPCACHE_DOWNLOADING_EVENT); |
715 FetchUrls(); | 716 FetchUrls(); |
716 FetchMasterEntries(); | 717 FetchMasterEntries(); |
717 MaybeCompleteUpdate(); // if not done, continues when async fetches complete | 718 MaybeCompleteUpdate(); // if not done, continues when async fetches complete |
718 } | 719 } |
719 | 720 |
720 void AppCacheUpdateJob::HandleUrlFetchCompleted(URLFetcher* fetcher) { | 721 void AppCacheUpdateJob::HandleUrlFetchCompleted(URLFetcher* fetcher, |
| 722 int net_error) { |
721 DCHECK(internal_state_ == DOWNLOADING); | 723 DCHECK(internal_state_ == DOWNLOADING); |
722 | 724 |
723 net::URLRequest* request = fetcher->request(); | 725 net::URLRequest* request = fetcher->request(); |
724 const GURL& url = request->original_url(); | 726 const GURL& url = request->original_url(); |
725 pending_url_fetches_.erase(url); | 727 pending_url_fetches_.erase(url); |
726 NotifyAllProgress(url); | 728 NotifyAllProgress(url); |
727 ++url_fetches_completed_; | 729 ++url_fetches_completed_; |
728 | 730 |
729 int response_code = request->status().is_success() | 731 int response_code = net_error == net::OK ? request->GetResponseCode() |
730 ? request->GetResponseCode() | 732 : fetcher->redirect_response_code(); |
731 : fetcher->redirect_response_code(); | |
732 | 733 |
733 AppCacheEntry& entry = url_file_list_.find(url)->second; | 734 AppCacheEntry& entry = url_file_list_.find(url)->second; |
734 | 735 |
735 if (response_code / 100 == 2) { | 736 if (response_code / 100 == 2) { |
736 // Associate storage with the new entry. | 737 // Associate storage with the new entry. |
737 DCHECK(fetcher->response_writer()); | 738 DCHECK(fetcher->response_writer()); |
738 entry.set_response_id(fetcher->response_writer()->response_id()); | 739 entry.set_response_id(fetcher->response_writer()->response_id()); |
739 entry.set_response_size(fetcher->response_writer()->amount_written()); | 740 entry.set_response_size(fetcher->response_writer()->amount_written()); |
740 if (!inprogress_cache_->AddOrModifyEntry(url, entry)) | 741 if (!inprogress_cache_->AddOrModifyEntry(url, entry)) |
741 duplicate_response_ids_.push_back(entry.response_id()); | 742 duplicate_response_ids_.push_back(entry.response_id()); |
742 | 743 |
743 // TODO(michaeln): Check for <html manifest=xxx> | 744 // TODO(michaeln): Check for <html manifest=xxx> |
744 // See http://code.google.com/p/chromium/issues/detail?id=97930 | 745 // See http://code.google.com/p/chromium/issues/detail?id=97930 |
745 // if (entry.IsMaster() && !(entry.IsExplicit() || fallback || intercept)) | 746 // if (entry.IsMaster() && !(entry.IsExplicit() || fallback || intercept)) |
746 // if (!manifestAttribute) skip it | 747 // if (!manifestAttribute) skip it |
747 | 748 |
748 // Foreign entries will be detected during cache selection. | 749 // Foreign entries will be detected during cache selection. |
749 // Note: 6.9.4, step 17.9 possible optimization: if resource is HTML or XML | 750 // Note: 6.9.4, step 17.9 possible optimization: if resource is HTML or XML |
750 // file whose root element is an html element with a manifest attribute | 751 // file whose root element is an html element with a manifest attribute |
751 // whose value doesn't match the manifest url of the application cache | 752 // whose value doesn't match the manifest url of the application cache |
752 // being processed, mark the entry as being foreign. | 753 // being processed, mark the entry as being foreign. |
753 } else { | 754 } else { |
754 VLOG(1) << "Request status: " << request->status().status() | 755 VLOG(1) << "Request error: " << net_error |
755 << " error: " << request->status().error() | |
756 << " response code: " << response_code; | 756 << " response code: " << response_code; |
757 if (entry.IsExplicit() || entry.IsFallback() || entry.IsIntercept()) { | 757 if (entry.IsExplicit() || entry.IsFallback() || entry.IsIntercept()) { |
758 if (response_code == 304 && fetcher->existing_entry().has_response_id()) { | 758 if (response_code == 304 && fetcher->existing_entry().has_response_id()) { |
759 // Keep the existing response. | 759 // Keep the existing response. |
760 entry.set_response_id(fetcher->existing_entry().response_id()); | 760 entry.set_response_id(fetcher->existing_entry().response_id()); |
761 entry.set_response_size(fetcher->existing_entry().response_size()); | 761 entry.set_response_size(fetcher->existing_entry().response_size()); |
762 inprogress_cache_->AddOrModifyEntry(url, entry); | 762 inprogress_cache_->AddOrModifyEntry(url, entry); |
763 } else { | 763 } else { |
764 const char kFormatString[] = "Resource fetch failed (%d) %s"; | 764 const char kFormatString[] = "Resource fetch failed (%d) %s"; |
765 std::string message = FormatUrlErrorMessage( | 765 std::string message = FormatUrlErrorMessage( |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
807 inprogress_cache_->AddOrModifyEntry(url, entry); | 807 inprogress_cache_->AddOrModifyEntry(url, entry); |
808 } | 808 } |
809 } | 809 } |
810 | 810 |
811 // Fetch another URL now that one request has completed. | 811 // Fetch another URL now that one request has completed. |
812 DCHECK(internal_state_ != CACHE_FAILURE); | 812 DCHECK(internal_state_ != CACHE_FAILURE); |
813 FetchUrls(); | 813 FetchUrls(); |
814 MaybeCompleteUpdate(); | 814 MaybeCompleteUpdate(); |
815 } | 815 } |
816 | 816 |
817 void AppCacheUpdateJob::HandleMasterEntryFetchCompleted( | 817 void AppCacheUpdateJob::HandleMasterEntryFetchCompleted(URLFetcher* fetcher, |
818 URLFetcher* fetcher) { | 818 int net_error) { |
819 DCHECK(internal_state_ == NO_UPDATE || internal_state_ == DOWNLOADING); | 819 DCHECK(internal_state_ == NO_UPDATE || internal_state_ == DOWNLOADING); |
820 | 820 |
821 // TODO(jennb): Handle downloads completing during cache failure when update | 821 // TODO(jennb): Handle downloads completing during cache failure when update |
822 // no longer fetches master entries directly. For now, we cancel all pending | 822 // no longer fetches master entries directly. For now, we cancel all pending |
823 // master entry fetches when entering cache failure state so this will never | 823 // master entry fetches when entering cache failure state so this will never |
824 // be called in CACHE_FAILURE state. | 824 // be called in CACHE_FAILURE state. |
825 | 825 |
826 net::URLRequest* request = fetcher->request(); | 826 net::URLRequest* request = fetcher->request(); |
827 const GURL& url = request->original_url(); | 827 const GURL& url = request->original_url(); |
828 master_entry_fetches_.erase(url); | 828 master_entry_fetches_.erase(url); |
829 ++master_entries_completed_; | 829 ++master_entries_completed_; |
830 | 830 |
831 int response_code = request->status().is_success() | 831 int response_code = net_error == net::OK ? request->GetResponseCode() : -1; |
832 ? request->GetResponseCode() : -1; | |
833 | 832 |
834 PendingMasters::iterator found = pending_master_entries_.find(url); | 833 PendingMasters::iterator found = pending_master_entries_.find(url); |
835 DCHECK(found != pending_master_entries_.end()); | 834 DCHECK(found != pending_master_entries_.end()); |
836 PendingHosts& hosts = found->second; | 835 PendingHosts& hosts = found->second; |
837 | 836 |
838 // Section 6.9.4. No update case: step 7.3, else step 22. | 837 // Section 6.9.4. No update case: step 7.3, else step 22. |
839 if (response_code / 100 == 2) { | 838 if (response_code / 100 == 2) { |
840 // Add fetched master entry to the appropriate cache. | 839 // Add fetched master entry to the appropriate cache. |
841 AppCache* cache = inprogress_cache_.get() ? inprogress_cache_.get() | 840 AppCache* cache = inprogress_cache_.get() ? inprogress_cache_.get() |
842 : group_->newest_complete_cache(); | 841 : group_->newest_complete_cache(); |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
904 return; | 903 return; |
905 } | 904 } |
906 } | 905 } |
907 } | 906 } |
908 | 907 |
909 DCHECK(internal_state_ != CACHE_FAILURE); | 908 DCHECK(internal_state_ != CACHE_FAILURE); |
910 FetchMasterEntries(); | 909 FetchMasterEntries(); |
911 MaybeCompleteUpdate(); | 910 MaybeCompleteUpdate(); |
912 } | 911 } |
913 | 912 |
914 void AppCacheUpdateJob::HandleManifestRefetchCompleted( | 913 void AppCacheUpdateJob::HandleManifestRefetchCompleted(URLFetcher* fetcher, |
915 URLFetcher* fetcher) { | 914 int net_error) { |
916 DCHECK(internal_state_ == REFETCH_MANIFEST); | 915 DCHECK(internal_state_ == REFETCH_MANIFEST); |
917 DCHECK(manifest_fetcher_ == fetcher); | 916 DCHECK(manifest_fetcher_ == fetcher); |
918 manifest_fetcher_ = NULL; | 917 manifest_fetcher_ = NULL; |
919 | 918 |
920 net::URLRequest* request = fetcher->request(); | 919 int response_code = |
921 int response_code = request->status().is_success() | 920 net_error == net::OK ? fetcher->request()->GetResponseCode() : -1; |
922 ? request->GetResponseCode() : -1; | |
923 if (response_code == 304 || manifest_data_ == fetcher->manifest_data()) { | 921 if (response_code == 304 || manifest_data_ == fetcher->manifest_data()) { |
924 // Only need to store response in storage if manifest is not already | 922 // Only need to store response in storage if manifest is not already |
925 // an entry in the cache. | 923 // an entry in the cache. |
926 AppCacheEntry* entry = inprogress_cache_->GetEntry(manifest_url_); | 924 AppCacheEntry* entry = inprogress_cache_->GetEntry(manifest_url_); |
927 if (entry) { | 925 if (entry) { |
928 entry->add_types(AppCacheEntry::MANIFEST); | 926 entry->add_types(AppCacheEntry::MANIFEST); |
929 StoreGroupAndCache(); | 927 StoreGroupAndCache(); |
930 } else { | 928 } else { |
931 manifest_response_writer_.reset(CreateResponseWriter()); | 929 manifest_response_writer_.reset(CreateResponseWriter()); |
932 scoped_refptr<HttpResponseInfoIOBuffer> io_buffer( | 930 scoped_refptr<HttpResponseInfoIOBuffer> io_buffer( |
933 new HttpResponseInfoIOBuffer(manifest_response_info_.release())); | 931 new HttpResponseInfoIOBuffer(manifest_response_info_.release())); |
934 manifest_response_writer_->WriteInfo( | 932 manifest_response_writer_->WriteInfo( |
935 io_buffer.get(), | 933 io_buffer.get(), |
936 base::Bind(&AppCacheUpdateJob::OnManifestInfoWriteComplete, | 934 base::Bind(&AppCacheUpdateJob::OnManifestInfoWriteComplete, |
937 base::Unretained(this))); | 935 base::Unretained(this))); |
938 } | 936 } |
939 } else { | 937 } else { |
940 VLOG(1) << "Request status: " << request->status().status() | 938 VLOG(1) << "Request error: " << net_error |
941 << " error: " << request->status().error() | |
942 << " response code: " << response_code; | 939 << " response code: " << response_code; |
943 ScheduleUpdateRetry(kRerunDelayMs); | 940 ScheduleUpdateRetry(kRerunDelayMs); |
944 if (response_code == 200) { | 941 if (response_code == 200) { |
945 HandleCacheFailure(AppCacheErrorDetails("Manifest changed during update", | 942 HandleCacheFailure(AppCacheErrorDetails("Manifest changed during update", |
946 APPCACHE_CHANGED_ERROR, | 943 APPCACHE_CHANGED_ERROR, |
947 GURL(), | 944 GURL(), |
948 0, | 945 0, |
949 false /*is_cross_origin*/), | 946 false /*is_cross_origin*/), |
950 MANIFEST_ERROR, | 947 MANIFEST_ERROR, |
951 GURL()); | 948 GURL()); |
(...skipping 756 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1708 // on this object after we've posted a task to delete ourselves. | 1705 // on this object after we've posted a task to delete ourselves. |
1709 if (group_) { | 1706 if (group_) { |
1710 group_->SetUpdateAppCacheStatus(AppCacheGroup::IDLE); | 1707 group_->SetUpdateAppCacheStatus(AppCacheGroup::IDLE); |
1711 group_ = NULL; | 1708 group_ = NULL; |
1712 } | 1709 } |
1713 | 1710 |
1714 base::ThreadTaskRunnerHandle::Get()->DeleteSoon(FROM_HERE, this); | 1711 base::ThreadTaskRunnerHandle::Get()->DeleteSoon(FROM_HERE, this); |
1715 } | 1712 } |
1716 | 1713 |
1717 } // namespace content | 1714 } // namespace content |
OLD | NEW |