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

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