Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(14)

Side by Side Diff: webkit/browser/appcache/appcache_update_job.cc

Issue 164933002: Expose details for appcache error events [Chromium] (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Restore failed_resource_url Created 6 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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 redirect_response_code_(-1) {}
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.
134 job_->MadeProgress();
135 request->Cancel(); 135 request->Cancel();
136 result_ = REDIRECT_ERROR; 136 result_ = REDIRECT_ERROR;
137 OnResponseCompleted(); 137 OnResponseCompleted();
138 } 138 }
139 139
140 void AppCacheUpdateJob::URLFetcher::OnResponseStarted( 140 void AppCacheUpdateJob::URLFetcher::OnResponseStarted(
141 net::URLRequest *request) { 141 net::URLRequest *request) {
142 DCHECK(request == request_); 142 DCHECK(request == request_);
143 int response_code = -1; 143 int response_code = -1;
144 if (request->status().is_success()) { 144 if (request->status().is_success()) {
145 response_code = request->GetResponseCode(); 145 response_code = request->GetResponseCode();
146 job_->MadeProgress(); 146 job_->MadeProgress();
147 } 147 }
148 if ((response_code / 100) == 2) { 148 if ((response_code / 100) == 2) {
149 149
150 // See http://code.google.com/p/chromium/issues/detail?id=69594 150 // See http://code.google.com/p/chromium/issues/detail?id=69594
151 // We willfully violate the HTML5 spec at this point in order 151 // We willfully violate the HTML5 spec at this point in order
152 // to support the appcaching of cross-origin HTTPS resources. 152 // to support the appcaching of cross-origin HTTPS resources.
153 // We've opted for a milder constraint and allow caching unless 153 // We've opted for a milder constraint and allow caching unless
154 // the resource has a "no-store" header. A spec change has been 154 // the resource has a "no-store" header. A spec change has been
155 // requested on the whatwg list. 155 // requested on the whatwg list.
156 // TODO(michaeln): Consider doing this for cross-origin HTTP resources too. 156 // TODO(michaeln): Consider doing this for cross-origin HTTP resources too.
157 if (url_.SchemeIsSecure() && 157 if (url_.SchemeIsSecure() &&
158 url_.GetOrigin() != job_->manifest_url_.GetOrigin()) { 158 url_.GetOrigin() != job_->manifest_url_.GetOrigin()) {
159 if (request->response_headers()-> 159 if (request->response_headers()->
160 HasHeaderValue("cache-control", "no-store")) { 160 HasHeaderValue("cache-control", "no-store")) {
161 DCHECK_EQ(-1, redirect_response_code_);
161 request->Cancel(); 162 request->Cancel();
162 result_ = SERVER_ERROR; // Not the best match? 163 result_ = SERVER_ERROR; // Not the best match?
163 OnResponseCompleted(); 164 OnResponseCompleted();
164 return; 165 return;
165 } 166 }
166 } 167 }
167 168
168 // Write response info to storage for URL fetches. Wait for async write 169 // Write response info to storage for URL fetches. Wait for async write
169 // completion before reading any response data. 170 // completion before reading any response data.
170 if (fetch_type_ == URL_FETCH || fetch_type_ == MASTER_ENTRY_FETCH) { 171 if (fetch_type_ == URL_FETCH || fetch_type_ == MASTER_ENTRY_FETCH) {
(...skipping 250 matching lines...) Expand 10 before | Expand all | Expand 10 after
421 } 422 }
422 423
423 AppCacheResponseWriter* AppCacheUpdateJob::CreateResponseWriter() { 424 AppCacheResponseWriter* AppCacheUpdateJob::CreateResponseWriter() {
424 AppCacheResponseWriter* writer = 425 AppCacheResponseWriter* writer =
425 storage_->CreateResponseWriter(manifest_url_, 426 storage_->CreateResponseWriter(manifest_url_,
426 group_->group_id()); 427 group_->group_id());
427 stored_response_ids_.push_back(writer->response_id()); 428 stored_response_ids_.push_back(writer->response_id());
428 return writer; 429 return writer;
429 } 430 }
430 431
431 void AppCacheUpdateJob::HandleCacheFailure( 432 void AppCacheUpdateJob::HandleCacheFailure(const ErrorDetails& error_details,
432 const std::string& error_message, 433 ResultType result,
433 ResultType result, 434 const GURL& failed_resource_url) {
434 const GURL& failed_resource_url) {
435 // 6.9.4 cache failure steps 2-8. 435 // 6.9.4 cache failure steps 2-8.
436 DCHECK(internal_state_ != CACHE_FAILURE); 436 DCHECK(internal_state_ != CACHE_FAILURE);
437 DCHECK(!error_message.empty()); 437 DCHECK(!error_details.message.empty());
438 DCHECK(result != UPDATE_OK); 438 DCHECK(result != UPDATE_OK);
439 internal_state_ = CACHE_FAILURE; 439 internal_state_ = CACHE_FAILURE;
440 LogHistogramStats(result, failed_resource_url); 440 LogHistogramStats(result, failed_resource_url);
441 CancelAllUrlFetches(); 441 CancelAllUrlFetches();
442 CancelAllMasterEntryFetches(error_message); 442 CancelAllMasterEntryFetches(error_details);
443 NotifyAllError(error_message); 443 NotifyAllError(error_details);
444 DiscardInprogressCache(); 444 DiscardInprogressCache();
445 internal_state_ = COMPLETED; 445 internal_state_ = COMPLETED;
446 DeleteSoon(); // To unwind the stack prior to deletion. 446 DeleteSoon(); // To unwind the stack prior to deletion.
447 } 447 }
448 448
449 void AppCacheUpdateJob::FetchManifest(bool is_first_fetch) { 449 void AppCacheUpdateJob::FetchManifest(bool is_first_fetch) {
450 DCHECK(!manifest_fetcher_); 450 DCHECK(!manifest_fetcher_);
451 manifest_fetcher_ = new URLFetcher( 451 manifest_fetcher_ = new URLFetcher(
452 manifest_url_, 452 manifest_url_,
453 is_first_fetch ? URLFetcher::MANIFEST_FETCH : 453 is_first_fetch ? URLFetcher::MANIFEST_FETCH :
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
494 manifest_response_info_.reset( 494 manifest_response_info_.reset(
495 new net::HttpResponseInfo(request->response_info())); 495 new net::HttpResponseInfo(request->response_info()));
496 if (update_type_ == UPGRADE_ATTEMPT) 496 if (update_type_ == UPGRADE_ATTEMPT)
497 CheckIfManifestChanged(); // continues asynchronously 497 CheckIfManifestChanged(); // continues asynchronously
498 else 498 else
499 ContinueHandleManifestFetchCompleted(true); 499 ContinueHandleManifestFetchCompleted(true);
500 } else if (response_code == 304 && update_type_ == UPGRADE_ATTEMPT) { 500 } else if (response_code == 304 && update_type_ == UPGRADE_ATTEMPT) {
501 ContinueHandleManifestFetchCompleted(false); 501 ContinueHandleManifestFetchCompleted(false);
502 } else if ((response_code == 404 || response_code == 410) && 502 } else if ((response_code == 404 || response_code == 410) &&
503 update_type_ == UPGRADE_ATTEMPT) { 503 update_type_ == UPGRADE_ATTEMPT) {
504 storage_->MakeGroupObsolete(group_, this); // async 504 storage_->MakeGroupObsolete(group_, this, response_code); // async
505 } else { 505 } else {
506 const char* kFormatString = "Manifest fetch failed (%d) %s"; 506 const char* kFormatString = "Manifest fetch failed (%d) %s";
507 std::string message = FormatUrlErrorMessage( 507 std::string message = FormatUrlErrorMessage(
508 kFormatString, manifest_url_, fetcher->result(), response_code); 508 kFormatString, manifest_url_, fetcher->result(), response_code);
509 HandleCacheFailure(message, fetcher->result(), GURL()); 509 HandleCacheFailure(ErrorDetails(message,
510 appcache::MANIFEST_ERROR,
511 manifest_url_,
512 response_code,
513 false /*is_cross_origin*/),
514 fetcher->result(),
515 GURL());
510 } 516 }
511 } 517 }
512 518
513 void AppCacheUpdateJob::OnGroupMadeObsolete(AppCacheGroup* group, 519 void AppCacheUpdateJob::OnGroupMadeObsolete(AppCacheGroup* group,
514 bool success) { 520 bool success,
521 int response_code) {
515 DCHECK(master_entry_fetches_.empty()); 522 DCHECK(master_entry_fetches_.empty());
516 CancelAllMasterEntryFetches("The cache has been made obsolete, " 523 CancelAllMasterEntryFetches(ErrorDetails(
517 "the manifest file returned 404 or 410"); 524 "The cache has been made obsolete, "
525 "the manifest file returned 404 or 410",
526 appcache::MANIFEST_ERROR,
527 GURL(),
528 response_code,
529 false /*is_cross_origin*/));
518 if (success) { 530 if (success) {
519 DCHECK(group->is_obsolete()); 531 DCHECK(group->is_obsolete());
520 NotifyAllAssociatedHosts(OBSOLETE_EVENT); 532 NotifyAllAssociatedHosts(OBSOLETE_EVENT);
521 internal_state_ = COMPLETED; 533 internal_state_ = COMPLETED;
522 MaybeCompleteUpdate(); 534 MaybeCompleteUpdate();
523 } else { 535 } else {
524 // Treat failure to mark group obsolete as a cache failure. 536 // Treat failure to mark group obsolete as a cache failure.
525 HandleCacheFailure("Failed to mark the cache as obsolete", 537 HandleCacheFailure(ErrorDetails("Failed to mark the cache as obsolete",
526 DB_ERROR, GURL()); 538 UNKNOWN_ERROR,
539 GURL(),
540 0,
541 false /*is_cross_origin*/),
542 DB_ERROR,
543 GURL());
527 } 544 }
528 } 545 }
529 546
530 void AppCacheUpdateJob::ContinueHandleManifestFetchCompleted(bool changed) { 547 void AppCacheUpdateJob::ContinueHandleManifestFetchCompleted(bool changed) {
531 DCHECK(internal_state_ == FETCH_MANIFEST); 548 DCHECK(internal_state_ == FETCH_MANIFEST);
532 549
533 if (!changed) { 550 if (!changed) {
534 DCHECK(update_type_ == UPGRADE_ATTEMPT); 551 DCHECK(update_type_ == UPGRADE_ATTEMPT);
535 internal_state_ = NO_UPDATE; 552 internal_state_ = NO_UPDATE;
536 553
537 // Wait for pending master entries to download. 554 // Wait for pending master entries to download.
538 FetchMasterEntries(); 555 FetchMasterEntries();
539 MaybeCompleteUpdate(); // if not done, run async 6.9.4 step 7 substeps 556 MaybeCompleteUpdate(); // if not done, run async 6.9.4 step 7 substeps
540 return; 557 return;
541 } 558 }
542 559
543 Manifest manifest; 560 Manifest manifest;
544 if (!ParseManifest(manifest_url_, manifest_data_.data(), 561 if (!ParseManifest(manifest_url_, manifest_data_.data(),
545 manifest_data_.length(), manifest)) { 562 manifest_data_.length(), manifest)) {
546 const char* kFormatString = "Failed to parse manifest %s"; 563 const char* kFormatString = "Failed to parse manifest %s";
547 const std::string message = base::StringPrintf(kFormatString, 564 const std::string message = base::StringPrintf(kFormatString,
548 manifest_url_.spec().c_str()); 565 manifest_url_.spec().c_str());
549 HandleCacheFailure(message, MANIFEST_ERROR, GURL()); 566 HandleCacheFailure(
567 ErrorDetails(
568 message, SIGNATURE_ERROR, GURL(), 0, false /*is_cross_origin*/),
569 MANIFEST_ERROR,
570 GURL());
550 VLOG(1) << message; 571 VLOG(1) << message;
551 return; 572 return;
552 } 573 }
553 574
554 // Proceed with update process. Section 6.9.4 steps 8-20. 575 // Proceed with update process. Section 6.9.4 steps 8-20.
555 internal_state_ = DOWNLOADING; 576 internal_state_ = DOWNLOADING;
556 inprogress_cache_ = new AppCache(storage_, storage_->NewCacheId()); 577 inprogress_cache_ = new AppCache(storage_, storage_->NewCacheId());
557 BuildUrlFileList(manifest); 578 BuildUrlFileList(manifest);
558 inprogress_cache_->InitializeWithManifest(&manifest); 579 inprogress_cache_->InitializeWithManifest(&manifest);
559 580
(...skipping 18 matching lines...) Expand all
578 void AppCacheUpdateJob::HandleUrlFetchCompleted(URLFetcher* fetcher) { 599 void AppCacheUpdateJob::HandleUrlFetchCompleted(URLFetcher* fetcher) {
579 DCHECK(internal_state_ == DOWNLOADING); 600 DCHECK(internal_state_ == DOWNLOADING);
580 601
581 net::URLRequest* request = fetcher->request(); 602 net::URLRequest* request = fetcher->request();
582 const GURL& url = request->original_url(); 603 const GURL& url = request->original_url();
583 pending_url_fetches_.erase(url); 604 pending_url_fetches_.erase(url);
584 NotifyAllProgress(url); 605 NotifyAllProgress(url);
585 ++url_fetches_completed_; 606 ++url_fetches_completed_;
586 607
587 int response_code = request->status().is_success() 608 int response_code = request->status().is_success()
588 ? request->GetResponseCode() : -1; 609 ? request->GetResponseCode()
610 : fetcher->canceled_response_code();
589 AppCacheEntry& entry = url_file_list_.find(url)->second; 611 AppCacheEntry& entry = url_file_list_.find(url)->second;
590 612
591 if (response_code / 100 == 2) { 613 if (response_code / 100 == 2) {
592 // Associate storage with the new entry. 614 // Associate storage with the new entry.
593 DCHECK(fetcher->response_writer()); 615 DCHECK(fetcher->response_writer());
594 entry.set_response_id(fetcher->response_writer()->response_id()); 616 entry.set_response_id(fetcher->response_writer()->response_id());
595 entry.set_response_size(fetcher->response_writer()->amount_written()); 617 entry.set_response_size(fetcher->response_writer()->amount_written());
596 if (!inprogress_cache_->AddOrModifyEntry(url, entry)) 618 if (!inprogress_cache_->AddOrModifyEntry(url, entry))
597 duplicate_response_ids_.push_back(entry.response_id()); 619 duplicate_response_ids_.push_back(entry.response_id());
598 620
(...skipping 14 matching lines...) Expand all
613 if (entry.IsExplicit() || entry.IsFallback() || entry.IsIntercept()) { 635 if (entry.IsExplicit() || entry.IsFallback() || entry.IsIntercept()) {
614 if (response_code == 304 && fetcher->existing_entry().has_response_id()) { 636 if (response_code == 304 && fetcher->existing_entry().has_response_id()) {
615 // Keep the existing response. 637 // Keep the existing response.
616 entry.set_response_id(fetcher->existing_entry().response_id()); 638 entry.set_response_id(fetcher->existing_entry().response_id());
617 entry.set_response_size(fetcher->existing_entry().response_size()); 639 entry.set_response_size(fetcher->existing_entry().response_size());
618 inprogress_cache_->AddOrModifyEntry(url, entry); 640 inprogress_cache_->AddOrModifyEntry(url, entry);
619 } else { 641 } else {
620 const char* kFormatString = "Resource fetch failed (%d) %s"; 642 const char* kFormatString = "Resource fetch failed (%d) %s";
621 std::string message = FormatUrlErrorMessage( 643 std::string message = FormatUrlErrorMessage(
622 kFormatString, url, fetcher->result(), response_code); 644 kFormatString, url, fetcher->result(), response_code);
623 HandleCacheFailure(message, fetcher->result(), url); 645 ResultType result = fetcher->result();
646 bool is_cross_origin = url.GetOrigin() != manifest_url_.GetOrigin();
647 switch (result) {
648 case DISKCACHE_ERROR:
649 HandleCacheFailure(
650 ErrorDetails(
651 message, UNKNOWN_ERROR, GURL(), 0, is_cross_origin),
652 result,
653 url);
654 break;
655 case NETWORK_ERROR:
656 HandleCacheFailure(
657 ErrorDetails(message, RESOURCE_ERROR, url, 0, is_cross_origin),
658 result,
659 url);
660 break;
661 default:
662 HandleCacheFailure(ErrorDetails(message,
663 RESOURCE_ERROR,
664 url,
665 response_code,
666 is_cross_origin),
667 result,
668 url);
669 break;
670 }
624 return; 671 return;
625 } 672 }
626 } else if (response_code == 404 || response_code == 410) { 673 } else if (response_code == 404 || response_code == 410) {
627 // Entry is skipped. They are dropped from the cache. 674 // Entry is skipped. They are dropped from the cache.
628 } else if (update_type_ == UPGRADE_ATTEMPT && 675 } else if (update_type_ == UPGRADE_ATTEMPT &&
629 fetcher->existing_entry().has_response_id()) { 676 fetcher->existing_entry().has_response_id()) {
630 // Keep the existing response. 677 // Keep the existing response.
631 // TODO(michaeln): Not sure this is a good idea. This is spec compliant 678 // TODO(michaeln): Not sure this is a good idea. This is spec compliant
632 // but the old resource may or may not be compatible with the new contents 679 // but the old resource may or may not be compatible with the new contents
633 // of the cache. Impossible to know one way or the other. 680 // of the cache. Impossible to know one way or the other.
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
698 if (inprogress_cache_.get()) 745 if (inprogress_cache_.get())
699 host->AssociateNoCache(GURL()); 746 host->AssociateNoCache(GURL());
700 747
701 host->RemoveObserver(this); 748 host->RemoveObserver(this);
702 } 749 }
703 hosts.clear(); 750 hosts.clear();
704 751
705 const char* kFormatString = "Manifest fetch failed (%d) %s"; 752 const char* kFormatString = "Manifest fetch failed (%d) %s";
706 std::string message = FormatUrlErrorMessage( 753 std::string message = FormatUrlErrorMessage(
707 kFormatString, request->url(), fetcher->result(), response_code); 754 kFormatString, request->url(), fetcher->result(), response_code);
708 host_notifier.SendErrorNotifications(message); 755 host_notifier.SendErrorNotifications(
756 ErrorDetails(message,
757 appcache::MANIFEST_ERROR,
758 request->url(),
759 response_code,
760 false /*is_cross_origin*/));
709 761
710 // In downloading case, update result is different if all master entries 762 // In downloading case, update result is different if all master entries
711 // failed vs. only some failing. 763 // failed vs. only some failing.
712 if (inprogress_cache_.get()) { 764 if (inprogress_cache_.get()) {
713 // Only count successful downloads to know if all master entries failed. 765 // Only count successful downloads to know if all master entries failed.
714 pending_master_entries_.erase(found); 766 pending_master_entries_.erase(found);
715 --master_entries_completed_; 767 --master_entries_completed_;
716 768
717 // Section 6.9.4, step 22.3. 769 // Section 6.9.4, step 22.3.
718 if (update_type_ == CACHE_ATTEMPT && pending_master_entries_.empty()) { 770 if (update_type_ == CACHE_ATTEMPT && pending_master_entries_.empty()) {
719 HandleCacheFailure(message, fetcher->result(), GURL()); 771 HandleCacheFailure(ErrorDetails(message,
772 appcache::MANIFEST_ERROR,
773 request->url(),
774 response_code,
775 false /*is_cross_origin*/),
776 fetcher->result(),
777 GURL());
720 return; 778 return;
721 } 779 }
722 } 780 }
723 } 781 }
724 782
725 DCHECK(internal_state_ != CACHE_FAILURE); 783 DCHECK(internal_state_ != CACHE_FAILURE);
726 FetchMasterEntries(); 784 FetchMasterEntries();
727 MaybeCompleteUpdate(); 785 MaybeCompleteUpdate();
728 } 786 }
729 787
(...skipping 21 matching lines...) Expand all
751 io_buffer.get(), 809 io_buffer.get(),
752 base::Bind(&AppCacheUpdateJob::OnManifestInfoWriteComplete, 810 base::Bind(&AppCacheUpdateJob::OnManifestInfoWriteComplete,
753 base::Unretained(this))); 811 base::Unretained(this)));
754 } 812 }
755 } else { 813 } else {
756 VLOG(1) << "Request status: " << request->status().status() 814 VLOG(1) << "Request status: " << request->status().status()
757 << " error: " << request->status().error() 815 << " error: " << request->status().error()
758 << " response code: " << response_code; 816 << " response code: " << response_code;
759 ScheduleUpdateRetry(kRerunDelayMs); 817 ScheduleUpdateRetry(kRerunDelayMs);
760 if (response_code == 200) { 818 if (response_code == 200) {
761 HandleCacheFailure( 819 HandleCacheFailure(ErrorDetails("Manifest changed during update",
762 "Manifest changed during update", MANIFEST_ERROR, GURL()); 820 CHANGED_ERROR,
821 GURL(),
822 0,
823 false /*is_cross_origin*/),
824 MANIFEST_ERROR,
825 GURL());
763 } else { 826 } else {
764 const char* kFormatString = "Manifest re-fetch failed (%d) %s"; 827 const char* kFormatString = "Manifest re-fetch failed (%d) %s";
765 std::string message = FormatUrlErrorMessage( 828 std::string message = FormatUrlErrorMessage(
766 kFormatString, manifest_url_, fetcher->result(), response_code); 829 kFormatString, manifest_url_, fetcher->result(), response_code);
767 HandleCacheFailure(message, fetcher->result(), GURL()); 830 HandleCacheFailure(ErrorDetails(message,
831 appcache::MANIFEST_ERROR,
832 GURL(),
833 response_code,
834 false /*is_cross_origin*/),
835 fetcher->result(),
836 GURL());
768 } 837 }
769 } 838 }
770 } 839 }
771 840
772 void AppCacheUpdateJob::OnManifestInfoWriteComplete(int result) { 841 void AppCacheUpdateJob::OnManifestInfoWriteComplete(int result) {
773 if (result > 0) { 842 if (result > 0) {
774 scoped_refptr<net::StringIOBuffer> io_buffer( 843 scoped_refptr<net::StringIOBuffer> io_buffer(
775 new net::StringIOBuffer(manifest_data_)); 844 new net::StringIOBuffer(manifest_data_));
776 manifest_response_writer_->WriteData( 845 manifest_response_writer_->WriteData(
777 io_buffer.get(), 846 io_buffer.get(),
778 manifest_data_.length(), 847 manifest_data_.length(),
779 base::Bind(&AppCacheUpdateJob::OnManifestDataWriteComplete, 848 base::Bind(&AppCacheUpdateJob::OnManifestDataWriteComplete,
780 base::Unretained(this))); 849 base::Unretained(this)));
781 } else { 850 } else {
782 HandleCacheFailure("Failed to write the manifest headers to storage", 851 HandleCacheFailure(
783 DISKCACHE_ERROR, GURL()); 852 ErrorDetails("Failed to write the manifest headers to storage",
853 UNKNOWN_ERROR,
854 GURL(),
855 0,
856 false /*is_cross_origin*/),
857 DISKCACHE_ERROR,
858 GURL());
784 } 859 }
785 } 860 }
786 861
787 void AppCacheUpdateJob::OnManifestDataWriteComplete(int result) { 862 void AppCacheUpdateJob::OnManifestDataWriteComplete(int result) {
788 if (result > 0) { 863 if (result > 0) {
789 AppCacheEntry entry(AppCacheEntry::MANIFEST, 864 AppCacheEntry entry(AppCacheEntry::MANIFEST,
790 manifest_response_writer_->response_id(), 865 manifest_response_writer_->response_id(),
791 manifest_response_writer_->amount_written()); 866 manifest_response_writer_->amount_written());
792 if (!inprogress_cache_->AddOrModifyEntry(manifest_url_, entry)) 867 if (!inprogress_cache_->AddOrModifyEntry(manifest_url_, entry))
793 duplicate_response_ids_.push_back(entry.response_id()); 868 duplicate_response_ids_.push_back(entry.response_id());
794 StoreGroupAndCache(); 869 StoreGroupAndCache();
795 } else { 870 } else {
796 HandleCacheFailure("Failed to write the manifest data to storage", 871 HandleCacheFailure(
797 DISKCACHE_ERROR, GURL()); 872 ErrorDetails("Failed to write the manifest data to storage",
873 UNKNOWN_ERROR,
874 GURL(),
875 0,
876 false /*is_cross_origin*/),
877 DISKCACHE_ERROR,
878 GURL());
798 } 879 }
799 } 880 }
800 881
801 void AppCacheUpdateJob::StoreGroupAndCache() { 882 void AppCacheUpdateJob::StoreGroupAndCache() {
802 DCHECK(stored_state_ == UNSTORED); 883 DCHECK(stored_state_ == UNSTORED);
803 stored_state_ = STORING; 884 stored_state_ = STORING;
804 scoped_refptr<AppCache> newest_cache; 885 scoped_refptr<AppCache> newest_cache;
805 if (inprogress_cache_.get()) 886 if (inprogress_cache_.get())
806 newest_cache.swap(inprogress_cache_); 887 newest_cache.swap(inprogress_cache_);
807 else 888 else
(...skipping 15 matching lines...) Expand all
823 MaybeCompleteUpdate(); // will definitely complete 904 MaybeCompleteUpdate(); // will definitely complete
824 } else { 905 } else {
825 stored_state_ = UNSTORED; 906 stored_state_ = UNSTORED;
826 907
827 // Restore inprogress_cache_ to get the proper events delivered 908 // Restore inprogress_cache_ to get the proper events delivered
828 // and the proper cleanup to occur. 909 // and the proper cleanup to occur.
829 if (newest_cache != group->newest_complete_cache()) 910 if (newest_cache != group->newest_complete_cache())
830 inprogress_cache_ = newest_cache; 911 inprogress_cache_ = newest_cache;
831 912
832 ResultType result = DB_ERROR; 913 ResultType result = DB_ERROR;
914 ErrorReason reason = UNKNOWN_ERROR;
833 std::string message("Failed to commit new cache to storage"); 915 std::string message("Failed to commit new cache to storage");
834 if (would_exceed_quota) { 916 if (would_exceed_quota) {
835 message.append(", would exceed quota"); 917 message.append(", would exceed quota");
836 result = QUOTA_ERROR; 918 result = QUOTA_ERROR;
919 reason = appcache::QUOTA_ERROR;
837 } 920 }
838 HandleCacheFailure(message, result, GURL()); 921 HandleCacheFailure(
922 ErrorDetails(message, reason, GURL(), 0, false /*is_cross_origin*/),
923 result,
924 GURL());
839 } 925 }
840 } 926 }
841 927
842 void AppCacheUpdateJob::NotifySingleHost(AppCacheHost* host, 928 void AppCacheUpdateJob::NotifySingleHost(AppCacheHost* host,
843 EventID event_id) { 929 EventID event_id) {
844 std::vector<int> ids(1, host->host_id()); 930 std::vector<int> ids(1, host->host_id());
845 host->frontend()->OnEventRaised(ids, event_id); 931 host->frontend()->OnEventRaised(ids, event_id);
846 } 932 }
847 933
848 void AppCacheUpdateJob::NotifyAllAssociatedHosts(EventID event_id) { 934 void AppCacheUpdateJob::NotifyAllAssociatedHosts(EventID event_id) {
849 HostNotifier host_notifier; 935 HostNotifier host_notifier;
850 AddAllAssociatedHostsToNotifier(&host_notifier); 936 AddAllAssociatedHostsToNotifier(&host_notifier);
851 host_notifier.SendNotifications(event_id); 937 host_notifier.SendNotifications(event_id);
852 } 938 }
853 939
854 void AppCacheUpdateJob::NotifyAllProgress(const GURL& url) { 940 void AppCacheUpdateJob::NotifyAllProgress(const GURL& url) {
855 HostNotifier host_notifier; 941 HostNotifier host_notifier;
856 AddAllAssociatedHostsToNotifier(&host_notifier); 942 AddAllAssociatedHostsToNotifier(&host_notifier);
857 host_notifier.SendProgressNotifications( 943 host_notifier.SendProgressNotifications(
858 url, url_file_list_.size(), url_fetches_completed_); 944 url, url_file_list_.size(), url_fetches_completed_);
859 } 945 }
860 946
861 void AppCacheUpdateJob::NotifyAllFinalProgress() { 947 void AppCacheUpdateJob::NotifyAllFinalProgress() {
862 DCHECK(url_file_list_.size() == url_fetches_completed_); 948 DCHECK(url_file_list_.size() == url_fetches_completed_);
863 NotifyAllProgress(GURL()); 949 NotifyAllProgress(GURL());
864 } 950 }
865 951
866 void AppCacheUpdateJob::NotifyAllError(const std::string& error_message) { 952 void AppCacheUpdateJob::NotifyAllError(const ErrorDetails& details) {
867 HostNotifier host_notifier; 953 HostNotifier host_notifier;
868 AddAllAssociatedHostsToNotifier(&host_notifier); 954 AddAllAssociatedHostsToNotifier(&host_notifier);
869 host_notifier.SendErrorNotifications(error_message); 955 host_notifier.SendErrorNotifications(details);
870 } 956 }
871 957
872 void AppCacheUpdateJob::AddAllAssociatedHostsToNotifier( 958 void AppCacheUpdateJob::AddAllAssociatedHostsToNotifier(
873 HostNotifier* host_notifier) { 959 HostNotifier* host_notifier) {
874 // Collect hosts so we only send one notification per frontend. 960 // Collect hosts so we only send one notification per frontend.
875 // A host can only be associated with a single cache so no need to worry 961 // A host can only be associated with a single cache so no need to worry
876 // about duplicate hosts being added to the notifier. 962 // about duplicate hosts being added to the notifier.
877 if (inprogress_cache_.get()) { 963 if (inprogress_cache_.get()) {
878 DCHECK(internal_state_ == DOWNLOADING || internal_state_ == CACHE_FAILURE); 964 DCHECK(internal_state_ == DOWNLOADING || internal_state_ == CACHE_FAILURE);
879 host_notifier->AddHosts(inprogress_cache_->associated_hosts()); 965 host_notifier->AddHosts(inprogress_cache_->associated_hosts());
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
913 DCHECK(update_type_ == UPGRADE_ATTEMPT); 999 DCHECK(update_type_ == UPGRADE_ATTEMPT);
914 AppCacheEntry* entry = NULL; 1000 AppCacheEntry* entry = NULL;
915 if (group_->newest_complete_cache()) 1001 if (group_->newest_complete_cache())
916 entry = group_->newest_complete_cache()->GetEntry(manifest_url_); 1002 entry = group_->newest_complete_cache()->GetEntry(manifest_url_);
917 if (!entry) { 1003 if (!entry) {
918 // TODO(michaeln): This is just a bandaid to avoid a crash. 1004 // TODO(michaeln): This is just a bandaid to avoid a crash.
919 // http://code.google.com/p/chromium/issues/detail?id=95101 1005 // http://code.google.com/p/chromium/issues/detail?id=95101
920 if (service_->storage() == storage_) { 1006 if (service_->storage() == storage_) {
921 // Use a local variable because service_ is reset in HandleCacheFailure. 1007 // Use a local variable because service_ is reset in HandleCacheFailure.
922 AppCacheService* service = service_; 1008 AppCacheService* service = service_;
923 HandleCacheFailure("Manifest entry not found in existing cache", 1009 HandleCacheFailure(
924 DB_ERROR, GURL()); 1010 ErrorDetails("Manifest entry not found in existing cache",
1011 UNKNOWN_ERROR,
1012 GURL(),
1013 0,
1014 false /*is_cross_origin*/),
1015 DB_ERROR,
1016 GURL());
925 AppCacheHistograms::AddMissingManifestEntrySample(); 1017 AppCacheHistograms::AddMissingManifestEntrySample();
926 service->DeleteAppCacheGroup(manifest_url_, net::CompletionCallback()); 1018 service->DeleteAppCacheGroup(manifest_url_, net::CompletionCallback());
927 } 1019 }
928 return; 1020 return;
929 } 1021 }
930 1022
931 // Load manifest data from storage to compare against fetched manifest. 1023 // Load manifest data from storage to compare against fetched manifest.
932 manifest_response_reader_.reset( 1024 manifest_response_reader_.reset(
933 storage_->CreateResponseReader(manifest_url_, 1025 storage_->CreateResponseReader(manifest_url_,
934 group_->group_id(), 1026 group_->group_id(),
(...skipping 220 matching lines...) Expand 10 before | Expand all | Expand 10 after
1155 url, URLFetcher::MASTER_ENTRY_FETCH, this); 1247 url, URLFetcher::MASTER_ENTRY_FETCH, this);
1156 fetcher->Start(); 1248 fetcher->Start();
1157 master_entry_fetches_.insert(PendingUrlFetches::value_type(url, fetcher)); 1249 master_entry_fetches_.insert(PendingUrlFetches::value_type(url, fetcher));
1158 } 1250 }
1159 1251
1160 master_entries_to_fetch_.erase(master_entries_to_fetch_.begin()); 1252 master_entries_to_fetch_.erase(master_entries_to_fetch_.begin());
1161 } 1253 }
1162 } 1254 }
1163 1255
1164 void AppCacheUpdateJob::CancelAllMasterEntryFetches( 1256 void AppCacheUpdateJob::CancelAllMasterEntryFetches(
1165 const std::string& error_message) { 1257 const ErrorDetails& error_details) {
1166 // For now, cancel all in-progress fetches for master entries and pretend 1258 // For now, cancel all in-progress fetches for master entries and pretend
1167 // all master entries fetches have completed. 1259 // all master entries fetches have completed.
1168 // TODO(jennb): Delete this when update no longer fetches master entries 1260 // TODO(jennb): Delete this when update no longer fetches master entries
1169 // directly. 1261 // directly.
1170 1262
1171 // Cancel all in-progress fetches. 1263 // Cancel all in-progress fetches.
1172 for (PendingUrlFetches::iterator it = master_entry_fetches_.begin(); 1264 for (PendingUrlFetches::iterator it = master_entry_fetches_.begin();
1173 it != master_entry_fetches_.end(); ++it) { 1265 it != master_entry_fetches_.end(); ++it) {
1174 delete it->second; 1266 delete it->second;
1175 master_entries_to_fetch_.insert(it->first); // back in unfetched list 1267 master_entries_to_fetch_.insert(it->first); // back in unfetched list
(...skipping 15 matching lines...) Expand all
1191 host_it != hosts.end(); ++host_it) { 1283 host_it != hosts.end(); ++host_it) {
1192 AppCacheHost* host = *host_it; 1284 AppCacheHost* host = *host_it;
1193 host->AssociateNoCache(GURL()); 1285 host->AssociateNoCache(GURL());
1194 host_notifier.AddHost(host); 1286 host_notifier.AddHost(host);
1195 host->RemoveObserver(this); 1287 host->RemoveObserver(this);
1196 } 1288 }
1197 hosts.clear(); 1289 hosts.clear();
1198 1290
1199 master_entries_to_fetch_.erase(master_entries_to_fetch_.begin()); 1291 master_entries_to_fetch_.erase(master_entries_to_fetch_.begin());
1200 } 1292 }
1201 host_notifier.SendErrorNotifications(error_message); 1293 host_notifier.SendErrorNotifications(error_details);
1202 } 1294 }
1203 1295
1204 bool AppCacheUpdateJob::MaybeLoadFromNewestCache(const GURL& url, 1296 bool AppCacheUpdateJob::MaybeLoadFromNewestCache(const GURL& url,
1205 AppCacheEntry& entry) { 1297 AppCacheEntry& entry) {
1206 if (update_type_ != UPGRADE_ATTEMPT) 1298 if (update_type_ != UPGRADE_ATTEMPT)
1207 return false; 1299 return false;
1208 1300
1209 AppCache* newest = group_->newest_complete_cache(); 1301 AppCache* newest = group_->newest_complete_cache();
1210 AppCacheEntry* copy_me = newest->GetEntry(url); 1302 AppCacheEntry* copy_me = newest->GetEntry(url);
1211 if (!copy_me || !copy_me->has_response_id()) 1303 if (!copy_me || !copy_me->has_response_id())
(...skipping 255 matching lines...) Expand 10 before | Expand all | Expand 10 after
1467 1559
1468 // Break the connection with the group so the group cannot call delete 1560 // Break the connection with the group so the group cannot call delete
1469 // on this object after we've posted a task to delete ourselves. 1561 // on this object after we've posted a task to delete ourselves.
1470 group_->SetUpdateStatus(AppCacheGroup::IDLE); 1562 group_->SetUpdateStatus(AppCacheGroup::IDLE);
1471 group_ = NULL; 1563 group_ = NULL;
1472 1564
1473 base::MessageLoop::current()->DeleteSoon(FROM_HERE, this); 1565 base::MessageLoop::current()->DeleteSoon(FROM_HERE, this);
1474 } 1566 }
1475 1567
1476 } // namespace appcache 1568 } // namespace appcache
OLDNEW
« no previous file with comments | « webkit/browser/appcache/appcache_update_job.h ('k') | webkit/browser/appcache/appcache_update_job_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698