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 "webkit/browser/appcache/appcache_update_job.h" | 5 #include "webkit/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/message_loop/message_loop.h" | 10 #include "base/message_loop/message_loop.h" |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
69 void SendProgressNotifications( | 69 void SendProgressNotifications( |
70 const GURL& url, int num_total, int num_complete) { | 70 const GURL& url, int num_total, int num_complete) { |
71 for (NotifyHostMap::iterator it = hosts_to_notify.begin(); | 71 for (NotifyHostMap::iterator it = hosts_to_notify.begin(); |
72 it != hosts_to_notify.end(); ++it) { | 72 it != hosts_to_notify.end(); ++it) { |
73 AppCacheFrontend* frontend = it->first; | 73 AppCacheFrontend* frontend = it->first; |
74 frontend->OnProgressEventRaised(it->second, url, | 74 frontend->OnProgressEventRaised(it->second, url, |
75 num_total, num_complete); | 75 num_total, num_complete); |
76 } | 76 } |
77 } | 77 } |
78 | 78 |
79 void SendErrorNotifications(const std::string& error_message) { | 79 void SendErrorNotifications(const ErrorDetails& details) { |
80 DCHECK(!error_message.empty()); | 80 DCHECK(!details.message.empty()); |
81 for (NotifyHostMap::iterator it = hosts_to_notify.begin(); | 81 for (NotifyHostMap::iterator it = hosts_to_notify.begin(); |
82 it != hosts_to_notify.end(); ++it) { | 82 it != hosts_to_notify.end(); ++it) { |
83 AppCacheFrontend* frontend = it->first; | 83 AppCacheFrontend* frontend = it->first; |
84 frontend->OnErrorEventRaised(it->second, error_message); | 84 frontend->OnErrorEventRaised(it->second, details); |
85 } | 85 } |
86 } | 86 } |
87 | 87 |
88 private: | 88 private: |
89 NotifyHostMap hosts_to_notify; | 89 NotifyHostMap hosts_to_notify; |
90 }; | 90 }; |
91 | 91 |
92 AppCacheUpdateJob::UrlToFetch::UrlToFetch(const GURL& url, | 92 AppCacheUpdateJob::UrlToFetch::UrlToFetch(const GURL& url, |
93 bool checked, | 93 bool checked, |
94 AppCacheResponseInfo* info) | 94 AppCacheResponseInfo* info) |
(...skipping 10 matching lines...) Expand all Loading... | |
105 // data out to the disk cache. | 105 // data out to the disk cache. |
106 AppCacheUpdateJob::URLFetcher::URLFetcher(const GURL& url, | 106 AppCacheUpdateJob::URLFetcher::URLFetcher(const GURL& url, |
107 FetchType fetch_type, | 107 FetchType fetch_type, |
108 AppCacheUpdateJob* job) | 108 AppCacheUpdateJob* job) |
109 : url_(url), | 109 : url_(url), |
110 job_(job), | 110 job_(job), |
111 fetch_type_(fetch_type), | 111 fetch_type_(fetch_type), |
112 retry_503_attempts_(0), | 112 retry_503_attempts_(0), |
113 buffer_(new net::IOBuffer(kBufferSize)), | 113 buffer_(new net::IOBuffer(kBufferSize)), |
114 request_(job->service_->request_context() | 114 request_(job->service_->request_context() |
115 ->CreateRequest(url, net::DEFAULT_PRIORITY, this, NULL)), | 115 ->CreateRequest(url, net::DEFAULT_PRIORITY, this, NULL)), |
116 result_(UPDATE_OK) {} | 116 result_(UPDATE_OK), |
117 canceled_response_code_(-1) {} | |
michaeln
2014/03/27 01:05:37
redirect_response_code_ might be a better name?
jsbell
2014/03/27 19:23:23
Done.
| |
117 | 118 |
118 AppCacheUpdateJob::URLFetcher::~URLFetcher() { | 119 AppCacheUpdateJob::URLFetcher::~URLFetcher() { |
119 } | 120 } |
120 | 121 |
121 void AppCacheUpdateJob::URLFetcher::Start() { | 122 void AppCacheUpdateJob::URLFetcher::Start() { |
122 request_->set_first_party_for_cookies(job_->manifest_url_); | 123 request_->set_first_party_for_cookies(job_->manifest_url_); |
123 request_->SetLoadFlags(request_->load_flags() | | 124 request_->SetLoadFlags(request_->load_flags() | |
124 net::LOAD_DISABLE_INTERCEPT); | 125 net::LOAD_DISABLE_INTERCEPT); |
125 if (existing_response_headers_.get()) | 126 if (existing_response_headers_.get()) |
126 AddConditionalHeaders(existing_response_headers_.get()); | 127 AddConditionalHeaders(existing_response_headers_.get()); |
127 request_->Start(); | 128 request_->Start(); |
128 } | 129 } |
129 | 130 |
130 void AppCacheUpdateJob::URLFetcher::OnReceivedRedirect( | 131 void AppCacheUpdateJob::URLFetcher::OnReceivedRedirect( |
131 net::URLRequest* request, const GURL& new_url, bool* defer_redirect) { | 132 net::URLRequest* request, const GURL& new_url, bool* defer_redirect) { |
132 DCHECK(request_ == request); | 133 DCHECK(request_ == request); |
133 // Redirect is not allowed by the update process. | 134 // Redirect is not allowed by the update process. |
135 canceled_response_code_ = request->GetResponseCode(); | |
134 request->Cancel(); | 136 request->Cancel(); |
135 result_ = REDIRECT_ERROR; | 137 result_ = REDIRECT_ERROR; |
136 OnResponseCompleted(); | 138 OnResponseCompleted(); |
137 } | 139 } |
138 | 140 |
139 void AppCacheUpdateJob::URLFetcher::OnResponseStarted( | 141 void AppCacheUpdateJob::URLFetcher::OnResponseStarted( |
140 net::URLRequest *request) { | 142 net::URLRequest *request) { |
141 DCHECK(request == request_); | 143 DCHECK(request == request_); |
142 int response_code = -1; | 144 int response_code = -1; |
143 if (request->status().is_success()) | 145 if (request->status().is_success()) |
144 response_code = request->GetResponseCode(); | 146 response_code = request->GetResponseCode(); |
145 if ((response_code / 100) == 2) { | 147 if ((response_code / 100) == 2) { |
146 | 148 |
147 // See http://code.google.com/p/chromium/issues/detail?id=69594 | 149 // See http://code.google.com/p/chromium/issues/detail?id=69594 |
148 // We willfully violate the HTML5 spec at this point in order | 150 // We willfully violate the HTML5 spec at this point in order |
149 // to support the appcaching of cross-origin HTTPS resources. | 151 // to support the appcaching of cross-origin HTTPS resources. |
150 // We've opted for a milder constraint and allow caching unless | 152 // We've opted for a milder constraint and allow caching unless |
151 // the resource has a "no-store" header. A spec change has been | 153 // the resource has a "no-store" header. A spec change has been |
152 // requested on the whatwg list. | 154 // requested on the whatwg list. |
153 // TODO(michaeln): Consider doing this for cross-origin HTTP resources too. | 155 // TODO(michaeln): Consider doing this for cross-origin HTTP resources too. |
154 if (url_.SchemeIsSecure() && | 156 if (url_.SchemeIsSecure() && |
155 url_.GetOrigin() != job_->manifest_url_.GetOrigin()) { | 157 url_.GetOrigin() != job_->manifest_url_.GetOrigin()) { |
156 if (request->response_headers()-> | 158 if (request->response_headers()-> |
157 HasHeaderValue("cache-control", "no-store")) { | 159 HasHeaderValue("cache-control", "no-store")) { |
160 DCHECK_EQ(-1, canceled_response_code_); | |
158 request->Cancel(); | 161 request->Cancel(); |
159 result_ = SERVER_ERROR; // Not the best match? | 162 result_ = SERVER_ERROR; // Not the best match? |
160 OnResponseCompleted(); | 163 OnResponseCompleted(); |
161 return; | 164 return; |
162 } | 165 } |
163 } | 166 } |
164 | 167 |
165 // Write response info to storage for URL fetches. Wait for async write | 168 // Write response info to storage for URL fetches. Wait for async write |
166 // completion before reading any response data. | 169 // completion before reading any response data. |
167 if (fetch_type_ == URL_FETCH || fetch_type_ == MASTER_ENTRY_FETCH) { | 170 if (fetch_type_ == URL_FETCH || fetch_type_ == MASTER_ENTRY_FETCH) { |
(...skipping 245 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
413 } | 416 } |
414 | 417 |
415 AppCacheResponseWriter* AppCacheUpdateJob::CreateResponseWriter() { | 418 AppCacheResponseWriter* AppCacheUpdateJob::CreateResponseWriter() { |
416 AppCacheResponseWriter* writer = | 419 AppCacheResponseWriter* writer = |
417 storage_->CreateResponseWriter(manifest_url_, | 420 storage_->CreateResponseWriter(manifest_url_, |
418 group_->group_id()); | 421 group_->group_id()); |
419 stored_response_ids_.push_back(writer->response_id()); | 422 stored_response_ids_.push_back(writer->response_id()); |
420 return writer; | 423 return writer; |
421 } | 424 } |
422 | 425 |
423 void AppCacheUpdateJob::HandleCacheFailure( | 426 void AppCacheUpdateJob::HandleCacheFailure(const ErrorDetails& error_details, |
424 const std::string& error_message, | 427 ResultType result) { |
425 ResultType result) { | |
426 // 6.9.4 cache failure steps 2-8. | 428 // 6.9.4 cache failure steps 2-8. |
427 DCHECK(internal_state_ != CACHE_FAILURE); | 429 DCHECK(internal_state_ != CACHE_FAILURE); |
428 DCHECK(!error_message.empty()); | 430 DCHECK(!error_details.message.empty()); |
429 DCHECK(result != UPDATE_OK); | 431 DCHECK(result != UPDATE_OK); |
430 internal_state_ = CACHE_FAILURE; | 432 internal_state_ = CACHE_FAILURE; |
431 CancelAllUrlFetches(); | 433 CancelAllUrlFetches(); |
432 CancelAllMasterEntryFetches(error_message); | 434 CancelAllMasterEntryFetches(error_details); |
433 NotifyAllError(error_message); | 435 NotifyAllError(error_details); |
434 DiscardInprogressCache(); | 436 DiscardInprogressCache(); |
435 internal_state_ = COMPLETED; | 437 internal_state_ = COMPLETED; |
436 AppCacheHistograms::CountUpdateJobResult( | 438 AppCacheHistograms::CountUpdateJobResult( |
437 result, manifest_url_.GetOrigin()); | 439 result, manifest_url_.GetOrigin()); |
438 DeleteSoon(); // To unwind the stack prior to deletion. | 440 DeleteSoon(); // To unwind the stack prior to deletion. |
439 } | 441 } |
440 | 442 |
441 void AppCacheUpdateJob::FetchManifest(bool is_first_fetch) { | 443 void AppCacheUpdateJob::FetchManifest(bool is_first_fetch) { |
442 DCHECK(!manifest_fetcher_); | 444 DCHECK(!manifest_fetcher_); |
443 manifest_fetcher_ = new URLFetcher( | 445 manifest_fetcher_ = new URLFetcher( |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
486 manifest_response_info_.reset( | 488 manifest_response_info_.reset( |
487 new net::HttpResponseInfo(request->response_info())); | 489 new net::HttpResponseInfo(request->response_info())); |
488 if (update_type_ == UPGRADE_ATTEMPT) | 490 if (update_type_ == UPGRADE_ATTEMPT) |
489 CheckIfManifestChanged(); // continues asynchronously | 491 CheckIfManifestChanged(); // continues asynchronously |
490 else | 492 else |
491 ContinueHandleManifestFetchCompleted(true); | 493 ContinueHandleManifestFetchCompleted(true); |
492 } else if (response_code == 304 && update_type_ == UPGRADE_ATTEMPT) { | 494 } else if (response_code == 304 && update_type_ == UPGRADE_ATTEMPT) { |
493 ContinueHandleManifestFetchCompleted(false); | 495 ContinueHandleManifestFetchCompleted(false); |
494 } else if ((response_code == 404 || response_code == 410) && | 496 } else if ((response_code == 404 || response_code == 410) && |
495 update_type_ == UPGRADE_ATTEMPT) { | 497 update_type_ == UPGRADE_ATTEMPT) { |
496 storage_->MakeGroupObsolete(group_, this); // async | 498 storage_->MakeGroupObsolete(group_, this, response_code); // async |
497 } else { | 499 } else { |
498 const char* kFormatString = "Manifest fetch failed (%d) %s"; | 500 const char* kFormatString = "Manifest fetch failed (%d) %s"; |
499 std::string message = FormatUrlErrorMessage( | 501 std::string message = FormatUrlErrorMessage( |
500 kFormatString, manifest_url_, fetcher->result(), response_code); | 502 kFormatString, manifest_url_, fetcher->result(), response_code); |
501 HandleCacheFailure(message, fetcher->result()); | 503 HandleCacheFailure(ErrorDetails(message, |
504 appcache::MANIFEST_ERROR, | |
505 manifest_url_, | |
506 response_code, | |
507 false /*is_cross_origin*/), | |
508 fetcher->result()); | |
502 } | 509 } |
503 } | 510 } |
504 | 511 |
505 void AppCacheUpdateJob::OnGroupMadeObsolete(AppCacheGroup* group, | 512 void AppCacheUpdateJob::OnGroupMadeObsolete(AppCacheGroup* group, |
506 bool success) { | 513 bool success, |
514 int response_code) { | |
507 DCHECK(master_entry_fetches_.empty()); | 515 DCHECK(master_entry_fetches_.empty()); |
508 CancelAllMasterEntryFetches("The cache has been made obsolete, " | 516 CancelAllMasterEntryFetches(ErrorDetails( |
509 "the manifest file returned 404 or 410"); | 517 "The cache has been made obsolete, " |
518 "the manifest file returned 404 or 410", | |
519 appcache::MANIFEST_ERROR, | |
520 GURL(), | |
521 response_code, | |
522 false /*is_cross_origin*/)); | |
510 if (success) { | 523 if (success) { |
511 DCHECK(group->is_obsolete()); | 524 DCHECK(group->is_obsolete()); |
512 NotifyAllAssociatedHosts(OBSOLETE_EVENT); | 525 NotifyAllAssociatedHosts(OBSOLETE_EVENT); |
513 internal_state_ = COMPLETED; | 526 internal_state_ = COMPLETED; |
514 MaybeCompleteUpdate(); | 527 MaybeCompleteUpdate(); |
515 } else { | 528 } else { |
516 // Treat failure to mark group obsolete as a cache failure. | 529 // Treat failure to mark group obsolete as a cache failure. |
517 HandleCacheFailure("Failed to mark the cache as obsolete", DB_ERROR); | 530 HandleCacheFailure(ErrorDetails("Failed to mark the cache as obsolete", |
531 UNKNOWN_ERROR, | |
532 GURL(), | |
533 0, | |
534 false /*is_cross_origin*/), | |
535 DB_ERROR); | |
518 } | 536 } |
519 } | 537 } |
520 | 538 |
521 void AppCacheUpdateJob::ContinueHandleManifestFetchCompleted(bool changed) { | 539 void AppCacheUpdateJob::ContinueHandleManifestFetchCompleted(bool changed) { |
522 DCHECK(internal_state_ == FETCH_MANIFEST); | 540 DCHECK(internal_state_ == FETCH_MANIFEST); |
523 | 541 |
524 if (!changed) { | 542 if (!changed) { |
525 DCHECK(update_type_ == UPGRADE_ATTEMPT); | 543 DCHECK(update_type_ == UPGRADE_ATTEMPT); |
526 internal_state_ = NO_UPDATE; | 544 internal_state_ = NO_UPDATE; |
527 | 545 |
528 // Wait for pending master entries to download. | 546 // Wait for pending master entries to download. |
529 FetchMasterEntries(); | 547 FetchMasterEntries(); |
530 MaybeCompleteUpdate(); // if not done, run async 6.9.4 step 7 substeps | 548 MaybeCompleteUpdate(); // if not done, run async 6.9.4 step 7 substeps |
531 return; | 549 return; |
532 } | 550 } |
533 | 551 |
534 Manifest manifest; | 552 Manifest manifest; |
535 if (!ParseManifest(manifest_url_, manifest_data_.data(), | 553 if (!ParseManifest(manifest_url_, manifest_data_.data(), |
536 manifest_data_.length(), manifest)) { | 554 manifest_data_.length(), manifest)) { |
537 const char* kFormatString = "Failed to parse manifest %s"; | 555 const char* kFormatString = "Failed to parse manifest %s"; |
538 const std::string message = base::StringPrintf(kFormatString, | 556 const std::string message = base::StringPrintf(kFormatString, |
539 manifest_url_.spec().c_str()); | 557 manifest_url_.spec().c_str()); |
540 HandleCacheFailure(message, MANIFEST_ERROR); | 558 HandleCacheFailure( |
559 ErrorDetails( | |
560 message, SIGNATURE_ERROR, GURL(), 0, false /*is_cross_origin*/), | |
561 MANIFEST_ERROR); | |
541 VLOG(1) << message; | 562 VLOG(1) << message; |
542 return; | 563 return; |
543 } | 564 } |
544 | 565 |
545 // Proceed with update process. Section 6.9.4 steps 8-20. | 566 // Proceed with update process. Section 6.9.4 steps 8-20. |
546 internal_state_ = DOWNLOADING; | 567 internal_state_ = DOWNLOADING; |
547 inprogress_cache_ = new AppCache(storage_, storage_->NewCacheId()); | 568 inprogress_cache_ = new AppCache(storage_, storage_->NewCacheId()); |
548 BuildUrlFileList(manifest); | 569 BuildUrlFileList(manifest); |
549 inprogress_cache_->InitializeWithManifest(&manifest); | 570 inprogress_cache_->InitializeWithManifest(&manifest); |
550 | 571 |
(...skipping 18 matching lines...) Expand all Loading... | |
569 void AppCacheUpdateJob::HandleUrlFetchCompleted(URLFetcher* fetcher) { | 590 void AppCacheUpdateJob::HandleUrlFetchCompleted(URLFetcher* fetcher) { |
570 DCHECK(internal_state_ == DOWNLOADING); | 591 DCHECK(internal_state_ == DOWNLOADING); |
571 | 592 |
572 net::URLRequest* request = fetcher->request(); | 593 net::URLRequest* request = fetcher->request(); |
573 const GURL& url = request->original_url(); | 594 const GURL& url = request->original_url(); |
574 pending_url_fetches_.erase(url); | 595 pending_url_fetches_.erase(url); |
575 NotifyAllProgress(url); | 596 NotifyAllProgress(url); |
576 ++url_fetches_completed_; | 597 ++url_fetches_completed_; |
577 | 598 |
578 int response_code = request->status().is_success() | 599 int response_code = request->status().is_success() |
579 ? request->GetResponseCode() : -1; | 600 ? request->GetResponseCode() |
601 : fetcher->canceled_response_code(); | |
580 AppCacheEntry& entry = url_file_list_.find(url)->second; | 602 AppCacheEntry& entry = url_file_list_.find(url)->second; |
581 | 603 |
582 if (response_code / 100 == 2) { | 604 if (response_code / 100 == 2) { |
583 // Associate storage with the new entry. | 605 // Associate storage with the new entry. |
584 DCHECK(fetcher->response_writer()); | 606 DCHECK(fetcher->response_writer()); |
585 entry.set_response_id(fetcher->response_writer()->response_id()); | 607 entry.set_response_id(fetcher->response_writer()->response_id()); |
586 entry.set_response_size(fetcher->response_writer()->amount_written()); | 608 entry.set_response_size(fetcher->response_writer()->amount_written()); |
587 if (!inprogress_cache_->AddOrModifyEntry(url, entry)) | 609 if (!inprogress_cache_->AddOrModifyEntry(url, entry)) |
588 duplicate_response_ids_.push_back(entry.response_id()); | 610 duplicate_response_ids_.push_back(entry.response_id()); |
589 | 611 |
(...skipping 14 matching lines...) Expand all Loading... | |
604 if (entry.IsExplicit() || entry.IsFallback() || entry.IsIntercept()) { | 626 if (entry.IsExplicit() || entry.IsFallback() || entry.IsIntercept()) { |
605 if (response_code == 304 && fetcher->existing_entry().has_response_id()) { | 627 if (response_code == 304 && fetcher->existing_entry().has_response_id()) { |
606 // Keep the existing response. | 628 // Keep the existing response. |
607 entry.set_response_id(fetcher->existing_entry().response_id()); | 629 entry.set_response_id(fetcher->existing_entry().response_id()); |
608 entry.set_response_size(fetcher->existing_entry().response_size()); | 630 entry.set_response_size(fetcher->existing_entry().response_size()); |
609 inprogress_cache_->AddOrModifyEntry(url, entry); | 631 inprogress_cache_->AddOrModifyEntry(url, entry); |
610 } else { | 632 } else { |
611 const char* kFormatString = "Resource fetch failed (%d) %s"; | 633 const char* kFormatString = "Resource fetch failed (%d) %s"; |
612 std::string message = FormatUrlErrorMessage( | 634 std::string message = FormatUrlErrorMessage( |
613 kFormatString, url, fetcher->result(), response_code); | 635 kFormatString, url, fetcher->result(), response_code); |
614 HandleCacheFailure(message, fetcher->result()); | 636 ResultType result = fetcher->result(); |
637 bool is_cross_origin = url.GetOrigin() != manifest_url_.GetOrigin(); | |
638 switch (result) { | |
639 case DISKCACHE_ERROR: | |
640 HandleCacheFailure( | |
641 ErrorDetails( | |
642 message, UNKNOWN_ERROR, GURL(), 0, is_cross_origin), | |
643 result); | |
644 break; | |
645 case NETWORK_ERROR: | |
646 HandleCacheFailure( | |
647 ErrorDetails(message, RESOURCE_ERROR, url, 0, is_cross_origin), | |
648 result); | |
649 break; | |
650 default: | |
651 HandleCacheFailure(ErrorDetails(message, | |
652 RESOURCE_ERROR, | |
653 url, | |
654 response_code, | |
655 is_cross_origin), | |
656 result); | |
657 break; | |
658 } | |
615 return; | 659 return; |
616 } | 660 } |
617 } else if (response_code == 404 || response_code == 410) { | 661 } else if (response_code == 404 || response_code == 410) { |
618 // Entry is skipped. They are dropped from the cache. | 662 // Entry is skipped. They are dropped from the cache. |
619 } else if (update_type_ == UPGRADE_ATTEMPT && | 663 } else if (update_type_ == UPGRADE_ATTEMPT && |
620 fetcher->existing_entry().has_response_id()) { | 664 fetcher->existing_entry().has_response_id()) { |
621 // Keep the existing response. | 665 // Keep the existing response. |
622 // TODO(michaeln): Not sure this is a good idea. This is spec compliant | 666 // TODO(michaeln): Not sure this is a good idea. This is spec compliant |
623 // but the old resource may or may not be compatible with the new contents | 667 // but the old resource may or may not be compatible with the new contents |
624 // of the cache. Impossible to know one way or the other. | 668 // of the cache. Impossible to know one way or the other. |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
689 if (inprogress_cache_.get()) | 733 if (inprogress_cache_.get()) |
690 host->AssociateNoCache(GURL()); | 734 host->AssociateNoCache(GURL()); |
691 | 735 |
692 host->RemoveObserver(this); | 736 host->RemoveObserver(this); |
693 } | 737 } |
694 hosts.clear(); | 738 hosts.clear(); |
695 | 739 |
696 const char* kFormatString = "Manifest fetch failed (%d) %s"; | 740 const char* kFormatString = "Manifest fetch failed (%d) %s"; |
697 std::string message = FormatUrlErrorMessage( | 741 std::string message = FormatUrlErrorMessage( |
698 kFormatString, request->url(), fetcher->result(), response_code); | 742 kFormatString, request->url(), fetcher->result(), response_code); |
699 host_notifier.SendErrorNotifications(message); | 743 host_notifier.SendErrorNotifications( |
744 ErrorDetails(message, | |
745 appcache::MANIFEST_ERROR, | |
746 request->url(), | |
747 response_code, | |
748 false /*is_cross_origin*/)); | |
700 | 749 |
701 // In downloading case, update result is different if all master entries | 750 // In downloading case, update result is different if all master entries |
702 // failed vs. only some failing. | 751 // failed vs. only some failing. |
703 if (inprogress_cache_.get()) { | 752 if (inprogress_cache_.get()) { |
704 // Only count successful downloads to know if all master entries failed. | 753 // Only count successful downloads to know if all master entries failed. |
705 pending_master_entries_.erase(found); | 754 pending_master_entries_.erase(found); |
706 --master_entries_completed_; | 755 --master_entries_completed_; |
707 | 756 |
708 // Section 6.9.4, step 22.3. | 757 // Section 6.9.4, step 22.3. |
709 if (update_type_ == CACHE_ATTEMPT && pending_master_entries_.empty()) { | 758 if (update_type_ == CACHE_ATTEMPT && pending_master_entries_.empty()) { |
710 HandleCacheFailure(message, fetcher->result()); | 759 HandleCacheFailure(ErrorDetails(message, |
760 appcache::MANIFEST_ERROR, | |
761 request->url(), | |
762 response_code, | |
763 false /*is_cross_origin*/), | |
764 fetcher->result()); | |
711 return; | 765 return; |
712 } | 766 } |
713 } | 767 } |
714 } | 768 } |
715 | 769 |
716 DCHECK(internal_state_ != CACHE_FAILURE); | 770 DCHECK(internal_state_ != CACHE_FAILURE); |
717 FetchMasterEntries(); | 771 FetchMasterEntries(); |
718 MaybeCompleteUpdate(); | 772 MaybeCompleteUpdate(); |
719 } | 773 } |
720 | 774 |
(...skipping 21 matching lines...) Expand all Loading... | |
742 io_buffer.get(), | 796 io_buffer.get(), |
743 base::Bind(&AppCacheUpdateJob::OnManifestInfoWriteComplete, | 797 base::Bind(&AppCacheUpdateJob::OnManifestInfoWriteComplete, |
744 base::Unretained(this))); | 798 base::Unretained(this))); |
745 } | 799 } |
746 } else { | 800 } else { |
747 VLOG(1) << "Request status: " << request->status().status() | 801 VLOG(1) << "Request status: " << request->status().status() |
748 << " error: " << request->status().error() | 802 << " error: " << request->status().error() |
749 << " response code: " << response_code; | 803 << " response code: " << response_code; |
750 ScheduleUpdateRetry(kRerunDelayMs); | 804 ScheduleUpdateRetry(kRerunDelayMs); |
751 if (response_code == 200) { | 805 if (response_code == 200) { |
752 HandleCacheFailure("Manifest changed during update", MANIFEST_ERROR); | 806 HandleCacheFailure(ErrorDetails("Manifest changed during update", |
807 CHANGED_ERROR, | |
808 GURL(), | |
809 0, | |
810 false /*is_cross_origin*/), | |
811 MANIFEST_ERROR); | |
753 } else { | 812 } else { |
754 const char* kFormatString = "Manifest re-fetch failed (%d) %s"; | 813 const char* kFormatString = "Manifest re-fetch failed (%d) %s"; |
755 std::string message = FormatUrlErrorMessage( | 814 std::string message = FormatUrlErrorMessage( |
756 kFormatString, manifest_url_, fetcher->result(), response_code); | 815 kFormatString, manifest_url_, fetcher->result(), response_code); |
757 HandleCacheFailure(message, fetcher->result()); | 816 HandleCacheFailure(ErrorDetails(message, |
817 appcache::MANIFEST_ERROR, | |
818 GURL(), | |
819 response_code, | |
820 false /*is_cross_origin*/), | |
821 fetcher->result()); | |
758 } | 822 } |
759 } | 823 } |
760 } | 824 } |
761 | 825 |
762 void AppCacheUpdateJob::OnManifestInfoWriteComplete(int result) { | 826 void AppCacheUpdateJob::OnManifestInfoWriteComplete(int result) { |
763 if (result > 0) { | 827 if (result > 0) { |
764 scoped_refptr<net::StringIOBuffer> io_buffer( | 828 scoped_refptr<net::StringIOBuffer> io_buffer( |
765 new net::StringIOBuffer(manifest_data_)); | 829 new net::StringIOBuffer(manifest_data_)); |
766 manifest_response_writer_->WriteData( | 830 manifest_response_writer_->WriteData( |
767 io_buffer.get(), | 831 io_buffer.get(), |
768 manifest_data_.length(), | 832 manifest_data_.length(), |
769 base::Bind(&AppCacheUpdateJob::OnManifestDataWriteComplete, | 833 base::Bind(&AppCacheUpdateJob::OnManifestDataWriteComplete, |
770 base::Unretained(this))); | 834 base::Unretained(this))); |
771 } else { | 835 } else { |
772 HandleCacheFailure("Failed to write the manifest headers to storage", | 836 HandleCacheFailure( |
773 DISKCACHE_ERROR); | 837 ErrorDetails("Failed to write the manifest headers to storage", |
838 UNKNOWN_ERROR, | |
839 GURL(), | |
840 0, | |
841 false /*is_cross_origin*/), | |
842 DISKCACHE_ERROR); | |
774 } | 843 } |
775 } | 844 } |
776 | 845 |
777 void AppCacheUpdateJob::OnManifestDataWriteComplete(int result) { | 846 void AppCacheUpdateJob::OnManifestDataWriteComplete(int result) { |
778 if (result > 0) { | 847 if (result > 0) { |
779 AppCacheEntry entry(AppCacheEntry::MANIFEST, | 848 AppCacheEntry entry(AppCacheEntry::MANIFEST, |
780 manifest_response_writer_->response_id(), | 849 manifest_response_writer_->response_id(), |
781 manifest_response_writer_->amount_written()); | 850 manifest_response_writer_->amount_written()); |
782 if (!inprogress_cache_->AddOrModifyEntry(manifest_url_, entry)) | 851 if (!inprogress_cache_->AddOrModifyEntry(manifest_url_, entry)) |
783 duplicate_response_ids_.push_back(entry.response_id()); | 852 duplicate_response_ids_.push_back(entry.response_id()); |
784 StoreGroupAndCache(); | 853 StoreGroupAndCache(); |
785 } else { | 854 } else { |
786 HandleCacheFailure("Failed to write the manifest data to storage", | 855 HandleCacheFailure( |
787 DISKCACHE_ERROR); | 856 ErrorDetails("Failed to write the manifest data to storage", |
857 UNKNOWN_ERROR, | |
858 GURL(), | |
859 0, | |
860 false /*is_cross_origin*/), | |
861 DISKCACHE_ERROR); | |
788 } | 862 } |
789 } | 863 } |
790 | 864 |
791 void AppCacheUpdateJob::StoreGroupAndCache() { | 865 void AppCacheUpdateJob::StoreGroupAndCache() { |
792 DCHECK(stored_state_ == UNSTORED); | 866 DCHECK(stored_state_ == UNSTORED); |
793 stored_state_ = STORING; | 867 stored_state_ = STORING; |
794 scoped_refptr<AppCache> newest_cache; | 868 scoped_refptr<AppCache> newest_cache; |
795 if (inprogress_cache_.get()) | 869 if (inprogress_cache_.get()) |
796 newest_cache.swap(inprogress_cache_); | 870 newest_cache.swap(inprogress_cache_); |
797 else | 871 else |
(...skipping 15 matching lines...) Expand all Loading... | |
813 MaybeCompleteUpdate(); // will definitely complete | 887 MaybeCompleteUpdate(); // will definitely complete |
814 } else { | 888 } else { |
815 stored_state_ = UNSTORED; | 889 stored_state_ = UNSTORED; |
816 | 890 |
817 // Restore inprogress_cache_ to get the proper events delivered | 891 // Restore inprogress_cache_ to get the proper events delivered |
818 // and the proper cleanup to occur. | 892 // and the proper cleanup to occur. |
819 if (newest_cache != group->newest_complete_cache()) | 893 if (newest_cache != group->newest_complete_cache()) |
820 inprogress_cache_ = newest_cache; | 894 inprogress_cache_ = newest_cache; |
821 | 895 |
822 ResultType result = DB_ERROR; | 896 ResultType result = DB_ERROR; |
897 ErrorReason reason = UNKNOWN_ERROR; | |
823 std::string message("Failed to commit new cache to storage"); | 898 std::string message("Failed to commit new cache to storage"); |
824 if (would_exceed_quota) { | 899 if (would_exceed_quota) { |
825 message.append(", would exceed quota"); | 900 message.append(", would exceed quota"); |
826 result = QUOTA_ERROR; | 901 result = QUOTA_ERROR; |
902 reason = appcache::QUOTA_ERROR; | |
827 } | 903 } |
828 HandleCacheFailure(message, result); | 904 HandleCacheFailure( |
905 ErrorDetails(message, reason, GURL(), 0, false /*is_cross_origin*/), | |
906 result); | |
829 } | 907 } |
830 } | 908 } |
831 | 909 |
832 void AppCacheUpdateJob::NotifySingleHost(AppCacheHost* host, | 910 void AppCacheUpdateJob::NotifySingleHost(AppCacheHost* host, |
833 EventID event_id) { | 911 EventID event_id) { |
834 std::vector<int> ids(1, host->host_id()); | 912 std::vector<int> ids(1, host->host_id()); |
835 host->frontend()->OnEventRaised(ids, event_id); | 913 host->frontend()->OnEventRaised(ids, event_id); |
836 } | 914 } |
837 | 915 |
838 void AppCacheUpdateJob::NotifyAllAssociatedHosts(EventID event_id) { | 916 void AppCacheUpdateJob::NotifyAllAssociatedHosts(EventID event_id) { |
839 HostNotifier host_notifier; | 917 HostNotifier host_notifier; |
840 AddAllAssociatedHostsToNotifier(&host_notifier); | 918 AddAllAssociatedHostsToNotifier(&host_notifier); |
841 host_notifier.SendNotifications(event_id); | 919 host_notifier.SendNotifications(event_id); |
842 } | 920 } |
843 | 921 |
844 void AppCacheUpdateJob::NotifyAllProgress(const GURL& url) { | 922 void AppCacheUpdateJob::NotifyAllProgress(const GURL& url) { |
845 HostNotifier host_notifier; | 923 HostNotifier host_notifier; |
846 AddAllAssociatedHostsToNotifier(&host_notifier); | 924 AddAllAssociatedHostsToNotifier(&host_notifier); |
847 host_notifier.SendProgressNotifications( | 925 host_notifier.SendProgressNotifications( |
848 url, url_file_list_.size(), url_fetches_completed_); | 926 url, url_file_list_.size(), url_fetches_completed_); |
849 } | 927 } |
850 | 928 |
851 void AppCacheUpdateJob::NotifyAllFinalProgress() { | 929 void AppCacheUpdateJob::NotifyAllFinalProgress() { |
852 DCHECK(url_file_list_.size() == url_fetches_completed_); | 930 DCHECK(url_file_list_.size() == url_fetches_completed_); |
853 NotifyAllProgress(GURL()); | 931 NotifyAllProgress(GURL()); |
854 } | 932 } |
855 | 933 |
856 void AppCacheUpdateJob::NotifyAllError(const std::string& error_message) { | 934 void AppCacheUpdateJob::NotifyAllError(const ErrorDetails& details) { |
857 HostNotifier host_notifier; | 935 HostNotifier host_notifier; |
858 AddAllAssociatedHostsToNotifier(&host_notifier); | 936 AddAllAssociatedHostsToNotifier(&host_notifier); |
859 host_notifier.SendErrorNotifications(error_message); | 937 host_notifier.SendErrorNotifications(details); |
860 } | 938 } |
861 | 939 |
862 void AppCacheUpdateJob::AddAllAssociatedHostsToNotifier( | 940 void AppCacheUpdateJob::AddAllAssociatedHostsToNotifier( |
863 HostNotifier* host_notifier) { | 941 HostNotifier* host_notifier) { |
864 // Collect hosts so we only send one notification per frontend. | 942 // Collect hosts so we only send one notification per frontend. |
865 // A host can only be associated with a single cache so no need to worry | 943 // A host can only be associated with a single cache so no need to worry |
866 // about duplicate hosts being added to the notifier. | 944 // about duplicate hosts being added to the notifier. |
867 if (inprogress_cache_.get()) { | 945 if (inprogress_cache_.get()) { |
868 DCHECK(internal_state_ == DOWNLOADING || internal_state_ == CACHE_FAILURE); | 946 DCHECK(internal_state_ == DOWNLOADING || internal_state_ == CACHE_FAILURE); |
869 host_notifier->AddHosts(inprogress_cache_->associated_hosts()); | 947 host_notifier->AddHosts(inprogress_cache_->associated_hosts()); |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
903 DCHECK(update_type_ == UPGRADE_ATTEMPT); | 981 DCHECK(update_type_ == UPGRADE_ATTEMPT); |
904 AppCacheEntry* entry = NULL; | 982 AppCacheEntry* entry = NULL; |
905 if (group_->newest_complete_cache()) | 983 if (group_->newest_complete_cache()) |
906 entry = group_->newest_complete_cache()->GetEntry(manifest_url_); | 984 entry = group_->newest_complete_cache()->GetEntry(manifest_url_); |
907 if (!entry) { | 985 if (!entry) { |
908 // TODO(michaeln): This is just a bandaid to avoid a crash. | 986 // TODO(michaeln): This is just a bandaid to avoid a crash. |
909 // http://code.google.com/p/chromium/issues/detail?id=95101 | 987 // http://code.google.com/p/chromium/issues/detail?id=95101 |
910 if (service_->storage() == storage_) { | 988 if (service_->storage() == storage_) { |
911 // Use a local variable because service_ is reset in HandleCacheFailure. | 989 // Use a local variable because service_ is reset in HandleCacheFailure. |
912 AppCacheService* service = service_; | 990 AppCacheService* service = service_; |
913 HandleCacheFailure("Manifest entry not found in existing cache", | 991 HandleCacheFailure( |
914 DB_ERROR); | 992 ErrorDetails("Manifest entry not found in existing cache", |
993 UNKNOWN_ERROR, | |
994 GURL(), | |
995 0, | |
996 false /*is_cross_origin*/), | |
997 DB_ERROR); | |
915 AppCacheHistograms::AddMissingManifestEntrySample(); | 998 AppCacheHistograms::AddMissingManifestEntrySample(); |
916 service->DeleteAppCacheGroup(manifest_url_, net::CompletionCallback()); | 999 service->DeleteAppCacheGroup(manifest_url_, net::CompletionCallback()); |
917 } | 1000 } |
918 return; | 1001 return; |
919 } | 1002 } |
920 | 1003 |
921 // Load manifest data from storage to compare against fetched manifest. | 1004 // Load manifest data from storage to compare against fetched manifest. |
922 manifest_response_reader_.reset( | 1005 manifest_response_reader_.reset( |
923 storage_->CreateResponseReader(manifest_url_, | 1006 storage_->CreateResponseReader(manifest_url_, |
924 group_->group_id(), | 1007 group_->group_id(), |
(...skipping 220 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1145 url, URLFetcher::MASTER_ENTRY_FETCH, this); | 1228 url, URLFetcher::MASTER_ENTRY_FETCH, this); |
1146 fetcher->Start(); | 1229 fetcher->Start(); |
1147 master_entry_fetches_.insert(PendingUrlFetches::value_type(url, fetcher)); | 1230 master_entry_fetches_.insert(PendingUrlFetches::value_type(url, fetcher)); |
1148 } | 1231 } |
1149 | 1232 |
1150 master_entries_to_fetch_.erase(master_entries_to_fetch_.begin()); | 1233 master_entries_to_fetch_.erase(master_entries_to_fetch_.begin()); |
1151 } | 1234 } |
1152 } | 1235 } |
1153 | 1236 |
1154 void AppCacheUpdateJob::CancelAllMasterEntryFetches( | 1237 void AppCacheUpdateJob::CancelAllMasterEntryFetches( |
1155 const std::string& error_message) { | 1238 const ErrorDetails& error_details) { |
1156 // For now, cancel all in-progress fetches for master entries and pretend | 1239 // For now, cancel all in-progress fetches for master entries and pretend |
1157 // all master entries fetches have completed. | 1240 // all master entries fetches have completed. |
1158 // TODO(jennb): Delete this when update no longer fetches master entries | 1241 // TODO(jennb): Delete this when update no longer fetches master entries |
1159 // directly. | 1242 // directly. |
1160 | 1243 |
1161 // Cancel all in-progress fetches. | 1244 // Cancel all in-progress fetches. |
1162 for (PendingUrlFetches::iterator it = master_entry_fetches_.begin(); | 1245 for (PendingUrlFetches::iterator it = master_entry_fetches_.begin(); |
1163 it != master_entry_fetches_.end(); ++it) { | 1246 it != master_entry_fetches_.end(); ++it) { |
1164 delete it->second; | 1247 delete it->second; |
1165 master_entries_to_fetch_.insert(it->first); // back in unfetched list | 1248 master_entries_to_fetch_.insert(it->first); // back in unfetched list |
(...skipping 15 matching lines...) Expand all Loading... | |
1181 host_it != hosts.end(); ++host_it) { | 1264 host_it != hosts.end(); ++host_it) { |
1182 AppCacheHost* host = *host_it; | 1265 AppCacheHost* host = *host_it; |
1183 host->AssociateNoCache(GURL()); | 1266 host->AssociateNoCache(GURL()); |
1184 host_notifier.AddHost(host); | 1267 host_notifier.AddHost(host); |
1185 host->RemoveObserver(this); | 1268 host->RemoveObserver(this); |
1186 } | 1269 } |
1187 hosts.clear(); | 1270 hosts.clear(); |
1188 | 1271 |
1189 master_entries_to_fetch_.erase(master_entries_to_fetch_.begin()); | 1272 master_entries_to_fetch_.erase(master_entries_to_fetch_.begin()); |
1190 } | 1273 } |
1191 host_notifier.SendErrorNotifications(error_message); | 1274 host_notifier.SendErrorNotifications(error_details); |
1192 } | 1275 } |
1193 | 1276 |
1194 bool AppCacheUpdateJob::MaybeLoadFromNewestCache(const GURL& url, | 1277 bool AppCacheUpdateJob::MaybeLoadFromNewestCache(const GURL& url, |
1195 AppCacheEntry& entry) { | 1278 AppCacheEntry& entry) { |
1196 if (update_type_ != UPGRADE_ATTEMPT) | 1279 if (update_type_ != UPGRADE_ATTEMPT) |
1197 return false; | 1280 return false; |
1198 | 1281 |
1199 AppCache* newest = group_->newest_complete_cache(); | 1282 AppCache* newest = group_->newest_complete_cache(); |
1200 AppCacheEntry* copy_me = newest->GetEntry(url); | 1283 AppCacheEntry* copy_me = newest->GetEntry(url); |
1201 if (!copy_me || !copy_me->has_response_id()) | 1284 if (!copy_me || !copy_me->has_response_id()) |
(...skipping 223 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1425 | 1508 |
1426 // Break the connection with the group so the group cannot call delete | 1509 // Break the connection with the group so the group cannot call delete |
1427 // on this object after we've posted a task to delete ourselves. | 1510 // on this object after we've posted a task to delete ourselves. |
1428 group_->SetUpdateStatus(AppCacheGroup::IDLE); | 1511 group_->SetUpdateStatus(AppCacheGroup::IDLE); |
1429 group_ = NULL; | 1512 group_ = NULL; |
1430 | 1513 |
1431 base::MessageLoop::current()->DeleteSoon(FROM_HERE, this); | 1514 base::MessageLoop::current()->DeleteSoon(FROM_HERE, this); |
1432 } | 1515 } |
1433 | 1516 |
1434 } // namespace appcache | 1517 } // namespace appcache |
OLD | NEW |