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

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: Rebased and review feedback Created 6 years, 9 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) {
jsbell 2014/03/27 19:30:43 Since I was already passing the failed resource UR
435 // 6.9.4 cache failure steps 2-8. 434 // 6.9.4 cache failure steps 2-8.
436 DCHECK(internal_state_ != CACHE_FAILURE); 435 DCHECK(internal_state_ != CACHE_FAILURE);
437 DCHECK(!error_message.empty()); 436 DCHECK(!error_details.message.empty());
438 DCHECK(result != UPDATE_OK); 437 DCHECK(result != UPDATE_OK);
439 internal_state_ = CACHE_FAILURE; 438 internal_state_ = CACHE_FAILURE;
440 LogHistogramStats(result, failed_resource_url); 439 LogHistogramStats(result, error_details.url);
441 CancelAllUrlFetches(); 440 CancelAllUrlFetches();
442 CancelAllMasterEntryFetches(error_message); 441 CancelAllMasterEntryFetches(error_details);
443 NotifyAllError(error_message); 442 NotifyAllError(error_details);
444 DiscardInprogressCache(); 443 DiscardInprogressCache();
445 internal_state_ = COMPLETED; 444 internal_state_ = COMPLETED;
446 DeleteSoon(); // To unwind the stack prior to deletion. 445 DeleteSoon(); // To unwind the stack prior to deletion.
447 } 446 }
448 447
449 void AppCacheUpdateJob::FetchManifest(bool is_first_fetch) { 448 void AppCacheUpdateJob::FetchManifest(bool is_first_fetch) {
450 DCHECK(!manifest_fetcher_); 449 DCHECK(!manifest_fetcher_);
451 manifest_fetcher_ = new URLFetcher( 450 manifest_fetcher_ = new URLFetcher(
452 manifest_url_, 451 manifest_url_,
453 is_first_fetch ? URLFetcher::MANIFEST_FETCH : 452 is_first_fetch ? URLFetcher::MANIFEST_FETCH :
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
494 manifest_response_info_.reset( 493 manifest_response_info_.reset(
495 new net::HttpResponseInfo(request->response_info())); 494 new net::HttpResponseInfo(request->response_info()));
496 if (update_type_ == UPGRADE_ATTEMPT) 495 if (update_type_ == UPGRADE_ATTEMPT)
497 CheckIfManifestChanged(); // continues asynchronously 496 CheckIfManifestChanged(); // continues asynchronously
498 else 497 else
499 ContinueHandleManifestFetchCompleted(true); 498 ContinueHandleManifestFetchCompleted(true);
500 } else if (response_code == 304 && update_type_ == UPGRADE_ATTEMPT) { 499 } else if (response_code == 304 && update_type_ == UPGRADE_ATTEMPT) {
501 ContinueHandleManifestFetchCompleted(false); 500 ContinueHandleManifestFetchCompleted(false);
502 } else if ((response_code == 404 || response_code == 410) && 501 } else if ((response_code == 404 || response_code == 410) &&
503 update_type_ == UPGRADE_ATTEMPT) { 502 update_type_ == UPGRADE_ATTEMPT) {
504 storage_->MakeGroupObsolete(group_, this); // async 503 storage_->MakeGroupObsolete(group_, this, response_code); // async
505 } else { 504 } else {
506 const char* kFormatString = "Manifest fetch failed (%d) %s"; 505 const char* kFormatString = "Manifest fetch failed (%d) %s";
507 std::string message = FormatUrlErrorMessage( 506 std::string message = FormatUrlErrorMessage(
508 kFormatString, manifest_url_, fetcher->result(), response_code); 507 kFormatString, manifest_url_, fetcher->result(), response_code);
509 HandleCacheFailure(message, fetcher->result(), GURL()); 508 HandleCacheFailure(ErrorDetails(message,
509 appcache::MANIFEST_ERROR,
510 manifest_url_,
jsbell 2014/03/27 19:30:43 Here the manifest URL is passed through instead of
511 response_code,
512 false /*is_cross_origin*/),
513 fetcher->result());
510 } 514 }
511 } 515 }
512 516
513 void AppCacheUpdateJob::OnGroupMadeObsolete(AppCacheGroup* group, 517 void AppCacheUpdateJob::OnGroupMadeObsolete(AppCacheGroup* group,
514 bool success) { 518 bool success,
519 int response_code) {
515 DCHECK(master_entry_fetches_.empty()); 520 DCHECK(master_entry_fetches_.empty());
516 CancelAllMasterEntryFetches("The cache has been made obsolete, " 521 CancelAllMasterEntryFetches(ErrorDetails(
517 "the manifest file returned 404 or 410"); 522 "The cache has been made obsolete, "
523 "the manifest file returned 404 or 410",
524 appcache::MANIFEST_ERROR,
525 GURL(),
526 response_code,
527 false /*is_cross_origin*/));
518 if (success) { 528 if (success) {
519 DCHECK(group->is_obsolete()); 529 DCHECK(group->is_obsolete());
520 NotifyAllAssociatedHosts(OBSOLETE_EVENT); 530 NotifyAllAssociatedHosts(OBSOLETE_EVENT);
521 internal_state_ = COMPLETED; 531 internal_state_ = COMPLETED;
522 MaybeCompleteUpdate(); 532 MaybeCompleteUpdate();
523 } else { 533 } else {
524 // Treat failure to mark group obsolete as a cache failure. 534 // Treat failure to mark group obsolete as a cache failure.
525 HandleCacheFailure("Failed to mark the cache as obsolete", 535 HandleCacheFailure(ErrorDetails("Failed to mark the cache as obsolete",
526 DB_ERROR, GURL()); 536 UNKNOWN_ERROR,
537 GURL(),
538 0,
539 false /*is_cross_origin*/),
540 DB_ERROR);
527 } 541 }
528 } 542 }
529 543
530 void AppCacheUpdateJob::ContinueHandleManifestFetchCompleted(bool changed) { 544 void AppCacheUpdateJob::ContinueHandleManifestFetchCompleted(bool changed) {
531 DCHECK(internal_state_ == FETCH_MANIFEST); 545 DCHECK(internal_state_ == FETCH_MANIFEST);
532 546
533 if (!changed) { 547 if (!changed) {
534 DCHECK(update_type_ == UPGRADE_ATTEMPT); 548 DCHECK(update_type_ == UPGRADE_ATTEMPT);
535 internal_state_ = NO_UPDATE; 549 internal_state_ = NO_UPDATE;
536 550
537 // Wait for pending master entries to download. 551 // Wait for pending master entries to download.
538 FetchMasterEntries(); 552 FetchMasterEntries();
539 MaybeCompleteUpdate(); // if not done, run async 6.9.4 step 7 substeps 553 MaybeCompleteUpdate(); // if not done, run async 6.9.4 step 7 substeps
540 return; 554 return;
541 } 555 }
542 556
543 Manifest manifest; 557 Manifest manifest;
544 if (!ParseManifest(manifest_url_, manifest_data_.data(), 558 if (!ParseManifest(manifest_url_, manifest_data_.data(),
545 manifest_data_.length(), manifest)) { 559 manifest_data_.length(), manifest)) {
546 const char* kFormatString = "Failed to parse manifest %s"; 560 const char* kFormatString = "Failed to parse manifest %s";
547 const std::string message = base::StringPrintf(kFormatString, 561 const std::string message = base::StringPrintf(kFormatString,
548 manifest_url_.spec().c_str()); 562 manifest_url_.spec().c_str());
549 HandleCacheFailure(message, MANIFEST_ERROR, GURL()); 563 HandleCacheFailure(
564 ErrorDetails(
565 message, SIGNATURE_ERROR, GURL(), 0, false /*is_cross_origin*/),
566 MANIFEST_ERROR);
550 VLOG(1) << message; 567 VLOG(1) << message;
551 return; 568 return;
552 } 569 }
553 570
554 // Proceed with update process. Section 6.9.4 steps 8-20. 571 // Proceed with update process. Section 6.9.4 steps 8-20.
555 internal_state_ = DOWNLOADING; 572 internal_state_ = DOWNLOADING;
556 inprogress_cache_ = new AppCache(storage_, storage_->NewCacheId()); 573 inprogress_cache_ = new AppCache(storage_, storage_->NewCacheId());
557 BuildUrlFileList(manifest); 574 BuildUrlFileList(manifest);
558 inprogress_cache_->InitializeWithManifest(&manifest); 575 inprogress_cache_->InitializeWithManifest(&manifest);
559 576
(...skipping 18 matching lines...) Expand all
578 void AppCacheUpdateJob::HandleUrlFetchCompleted(URLFetcher* fetcher) { 595 void AppCacheUpdateJob::HandleUrlFetchCompleted(URLFetcher* fetcher) {
579 DCHECK(internal_state_ == DOWNLOADING); 596 DCHECK(internal_state_ == DOWNLOADING);
580 597
581 net::URLRequest* request = fetcher->request(); 598 net::URLRequest* request = fetcher->request();
582 const GURL& url = request->original_url(); 599 const GURL& url = request->original_url();
583 pending_url_fetches_.erase(url); 600 pending_url_fetches_.erase(url);
584 NotifyAllProgress(url); 601 NotifyAllProgress(url);
585 ++url_fetches_completed_; 602 ++url_fetches_completed_;
586 603
587 int response_code = request->status().is_success() 604 int response_code = request->status().is_success()
588 ? request->GetResponseCode() : -1; 605 ? request->GetResponseCode()
606 : fetcher->canceled_response_code();
589 AppCacheEntry& entry = url_file_list_.find(url)->second; 607 AppCacheEntry& entry = url_file_list_.find(url)->second;
590 608
591 if (response_code / 100 == 2) { 609 if (response_code / 100 == 2) {
592 // Associate storage with the new entry. 610 // Associate storage with the new entry.
593 DCHECK(fetcher->response_writer()); 611 DCHECK(fetcher->response_writer());
594 entry.set_response_id(fetcher->response_writer()->response_id()); 612 entry.set_response_id(fetcher->response_writer()->response_id());
595 entry.set_response_size(fetcher->response_writer()->amount_written()); 613 entry.set_response_size(fetcher->response_writer()->amount_written());
596 if (!inprogress_cache_->AddOrModifyEntry(url, entry)) 614 if (!inprogress_cache_->AddOrModifyEntry(url, entry))
597 duplicate_response_ids_.push_back(entry.response_id()); 615 duplicate_response_ids_.push_back(entry.response_id());
598 616
(...skipping 14 matching lines...) Expand all
613 if (entry.IsExplicit() || entry.IsFallback() || entry.IsIntercept()) { 631 if (entry.IsExplicit() || entry.IsFallback() || entry.IsIntercept()) {
614 if (response_code == 304 && fetcher->existing_entry().has_response_id()) { 632 if (response_code == 304 && fetcher->existing_entry().has_response_id()) {
615 // Keep the existing response. 633 // Keep the existing response.
616 entry.set_response_id(fetcher->existing_entry().response_id()); 634 entry.set_response_id(fetcher->existing_entry().response_id());
617 entry.set_response_size(fetcher->existing_entry().response_size()); 635 entry.set_response_size(fetcher->existing_entry().response_size());
618 inprogress_cache_->AddOrModifyEntry(url, entry); 636 inprogress_cache_->AddOrModifyEntry(url, entry);
619 } else { 637 } else {
620 const char* kFormatString = "Resource fetch failed (%d) %s"; 638 const char* kFormatString = "Resource fetch failed (%d) %s";
621 std::string message = FormatUrlErrorMessage( 639 std::string message = FormatUrlErrorMessage(
622 kFormatString, url, fetcher->result(), response_code); 640 kFormatString, url, fetcher->result(), response_code);
623 HandleCacheFailure(message, fetcher->result(), url); 641 ResultType result = fetcher->result();
642 bool is_cross_origin = url.GetOrigin() != manifest_url_.GetOrigin();
643 switch (result) {
644 case DISKCACHE_ERROR:
645 HandleCacheFailure(
646 ErrorDetails(
647 message, UNKNOWN_ERROR, GURL(), 0, is_cross_origin),
jsbell 2014/03/27 19:30:43 Here an empty URL is passed through instead of the
648 result);
649 break;
650 case NETWORK_ERROR:
651 HandleCacheFailure(
652 ErrorDetails(message, RESOURCE_ERROR, url, 0, is_cross_origin),
653 result);
654 break;
655 default:
656 HandleCacheFailure(ErrorDetails(message,
657 RESOURCE_ERROR,
658 url,
659 response_code,
660 is_cross_origin),
661 result);
662 break;
663 }
624 return; 664 return;
625 } 665 }
626 } else if (response_code == 404 || response_code == 410) { 666 } else if (response_code == 404 || response_code == 410) {
627 // Entry is skipped. They are dropped from the cache. 667 // Entry is skipped. They are dropped from the cache.
628 } else if (update_type_ == UPGRADE_ATTEMPT && 668 } else if (update_type_ == UPGRADE_ATTEMPT &&
629 fetcher->existing_entry().has_response_id()) { 669 fetcher->existing_entry().has_response_id()) {
630 // Keep the existing response. 670 // Keep the existing response.
631 // TODO(michaeln): Not sure this is a good idea. This is spec compliant 671 // 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 672 // 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. 673 // 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()) 738 if (inprogress_cache_.get())
699 host->AssociateNoCache(GURL()); 739 host->AssociateNoCache(GURL());
700 740
701 host->RemoveObserver(this); 741 host->RemoveObserver(this);
702 } 742 }
703 hosts.clear(); 743 hosts.clear();
704 744
705 const char* kFormatString = "Manifest fetch failed (%d) %s"; 745 const char* kFormatString = "Manifest fetch failed (%d) %s";
706 std::string message = FormatUrlErrorMessage( 746 std::string message = FormatUrlErrorMessage(
707 kFormatString, request->url(), fetcher->result(), response_code); 747 kFormatString, request->url(), fetcher->result(), response_code);
708 host_notifier.SendErrorNotifications(message); 748 host_notifier.SendErrorNotifications(
749 ErrorDetails(message,
750 appcache::MANIFEST_ERROR,
751 request->url(),
752 response_code,
753 false /*is_cross_origin*/));
709 754
710 // In downloading case, update result is different if all master entries 755 // In downloading case, update result is different if all master entries
711 // failed vs. only some failing. 756 // failed vs. only some failing.
712 if (inprogress_cache_.get()) { 757 if (inprogress_cache_.get()) {
713 // Only count successful downloads to know if all master entries failed. 758 // Only count successful downloads to know if all master entries failed.
714 pending_master_entries_.erase(found); 759 pending_master_entries_.erase(found);
715 --master_entries_completed_; 760 --master_entries_completed_;
716 761
717 // Section 6.9.4, step 22.3. 762 // Section 6.9.4, step 22.3.
718 if (update_type_ == CACHE_ATTEMPT && pending_master_entries_.empty()) { 763 if (update_type_ == CACHE_ATTEMPT && pending_master_entries_.empty()) {
719 HandleCacheFailure(message, fetcher->result(), GURL()); 764 HandleCacheFailure(ErrorDetails(message,
765 appcache::MANIFEST_ERROR,
766 request->url(),
jsbell 2014/03/27 19:30:43 Here the request URL is passed through instead of
767 response_code,
768 false /*is_cross_origin*/),
769 fetcher->result());
720 return; 770 return;
721 } 771 }
722 } 772 }
723 } 773 }
724 774
725 DCHECK(internal_state_ != CACHE_FAILURE); 775 DCHECK(internal_state_ != CACHE_FAILURE);
726 FetchMasterEntries(); 776 FetchMasterEntries();
727 MaybeCompleteUpdate(); 777 MaybeCompleteUpdate();
728 } 778 }
729 779
(...skipping 21 matching lines...) Expand all
751 io_buffer.get(), 801 io_buffer.get(),
752 base::Bind(&AppCacheUpdateJob::OnManifestInfoWriteComplete, 802 base::Bind(&AppCacheUpdateJob::OnManifestInfoWriteComplete,
753 base::Unretained(this))); 803 base::Unretained(this)));
754 } 804 }
755 } else { 805 } else {
756 VLOG(1) << "Request status: " << request->status().status() 806 VLOG(1) << "Request status: " << request->status().status()
757 << " error: " << request->status().error() 807 << " error: " << request->status().error()
758 << " response code: " << response_code; 808 << " response code: " << response_code;
759 ScheduleUpdateRetry(kRerunDelayMs); 809 ScheduleUpdateRetry(kRerunDelayMs);
760 if (response_code == 200) { 810 if (response_code == 200) {
761 HandleCacheFailure( 811 HandleCacheFailure(ErrorDetails("Manifest changed during update",
762 "Manifest changed during update", MANIFEST_ERROR, GURL()); 812 CHANGED_ERROR,
813 GURL(),
814 0,
815 false /*is_cross_origin*/),
816 MANIFEST_ERROR);
763 } else { 817 } else {
764 const char* kFormatString = "Manifest re-fetch failed (%d) %s"; 818 const char* kFormatString = "Manifest re-fetch failed (%d) %s";
765 std::string message = FormatUrlErrorMessage( 819 std::string message = FormatUrlErrorMessage(
766 kFormatString, manifest_url_, fetcher->result(), response_code); 820 kFormatString, manifest_url_, fetcher->result(), response_code);
767 HandleCacheFailure(message, fetcher->result(), GURL()); 821 HandleCacheFailure(ErrorDetails(message,
822 appcache::MANIFEST_ERROR,
823 GURL(),
824 response_code,
825 false /*is_cross_origin*/),
826 fetcher->result());
768 } 827 }
769 } 828 }
770 } 829 }
771 830
772 void AppCacheUpdateJob::OnManifestInfoWriteComplete(int result) { 831 void AppCacheUpdateJob::OnManifestInfoWriteComplete(int result) {
773 if (result > 0) { 832 if (result > 0) {
774 scoped_refptr<net::StringIOBuffer> io_buffer( 833 scoped_refptr<net::StringIOBuffer> io_buffer(
775 new net::StringIOBuffer(manifest_data_)); 834 new net::StringIOBuffer(manifest_data_));
776 manifest_response_writer_->WriteData( 835 manifest_response_writer_->WriteData(
777 io_buffer.get(), 836 io_buffer.get(),
778 manifest_data_.length(), 837 manifest_data_.length(),
779 base::Bind(&AppCacheUpdateJob::OnManifestDataWriteComplete, 838 base::Bind(&AppCacheUpdateJob::OnManifestDataWriteComplete,
780 base::Unretained(this))); 839 base::Unretained(this)));
781 } else { 840 } else {
782 HandleCacheFailure("Failed to write the manifest headers to storage", 841 HandleCacheFailure(
783 DISKCACHE_ERROR, GURL()); 842 ErrorDetails("Failed to write the manifest headers to storage",
843 UNKNOWN_ERROR,
844 GURL(),
845 0,
846 false /*is_cross_origin*/),
847 DISKCACHE_ERROR);
784 } 848 }
785 } 849 }
786 850
787 void AppCacheUpdateJob::OnManifestDataWriteComplete(int result) { 851 void AppCacheUpdateJob::OnManifestDataWriteComplete(int result) {
788 if (result > 0) { 852 if (result > 0) {
789 AppCacheEntry entry(AppCacheEntry::MANIFEST, 853 AppCacheEntry entry(AppCacheEntry::MANIFEST,
790 manifest_response_writer_->response_id(), 854 manifest_response_writer_->response_id(),
791 manifest_response_writer_->amount_written()); 855 manifest_response_writer_->amount_written());
792 if (!inprogress_cache_->AddOrModifyEntry(manifest_url_, entry)) 856 if (!inprogress_cache_->AddOrModifyEntry(manifest_url_, entry))
793 duplicate_response_ids_.push_back(entry.response_id()); 857 duplicate_response_ids_.push_back(entry.response_id());
794 StoreGroupAndCache(); 858 StoreGroupAndCache();
795 } else { 859 } else {
796 HandleCacheFailure("Failed to write the manifest data to storage", 860 HandleCacheFailure(
797 DISKCACHE_ERROR, GURL()); 861 ErrorDetails("Failed to write the manifest data to storage",
862 UNKNOWN_ERROR,
863 GURL(),
864 0,
865 false /*is_cross_origin*/),
866 DISKCACHE_ERROR);
798 } 867 }
799 } 868 }
800 869
801 void AppCacheUpdateJob::StoreGroupAndCache() { 870 void AppCacheUpdateJob::StoreGroupAndCache() {
802 DCHECK(stored_state_ == UNSTORED); 871 DCHECK(stored_state_ == UNSTORED);
803 stored_state_ = STORING; 872 stored_state_ = STORING;
804 scoped_refptr<AppCache> newest_cache; 873 scoped_refptr<AppCache> newest_cache;
805 if (inprogress_cache_.get()) 874 if (inprogress_cache_.get())
806 newest_cache.swap(inprogress_cache_); 875 newest_cache.swap(inprogress_cache_);
807 else 876 else
(...skipping 15 matching lines...) Expand all
823 MaybeCompleteUpdate(); // will definitely complete 892 MaybeCompleteUpdate(); // will definitely complete
824 } else { 893 } else {
825 stored_state_ = UNSTORED; 894 stored_state_ = UNSTORED;
826 895
827 // Restore inprogress_cache_ to get the proper events delivered 896 // Restore inprogress_cache_ to get the proper events delivered
828 // and the proper cleanup to occur. 897 // and the proper cleanup to occur.
829 if (newest_cache != group->newest_complete_cache()) 898 if (newest_cache != group->newest_complete_cache())
830 inprogress_cache_ = newest_cache; 899 inprogress_cache_ = newest_cache;
831 900
832 ResultType result = DB_ERROR; 901 ResultType result = DB_ERROR;
902 ErrorReason reason = UNKNOWN_ERROR;
833 std::string message("Failed to commit new cache to storage"); 903 std::string message("Failed to commit new cache to storage");
834 if (would_exceed_quota) { 904 if (would_exceed_quota) {
835 message.append(", would exceed quota"); 905 message.append(", would exceed quota");
836 result = QUOTA_ERROR; 906 result = QUOTA_ERROR;
907 reason = appcache::QUOTA_ERROR;
837 } 908 }
838 HandleCacheFailure(message, result, GURL()); 909 HandleCacheFailure(
910 ErrorDetails(message, reason, GURL(), 0, false /*is_cross_origin*/),
911 result);
839 } 912 }
840 } 913 }
841 914
842 void AppCacheUpdateJob::NotifySingleHost(AppCacheHost* host, 915 void AppCacheUpdateJob::NotifySingleHost(AppCacheHost* host,
843 EventID event_id) { 916 EventID event_id) {
844 std::vector<int> ids(1, host->host_id()); 917 std::vector<int> ids(1, host->host_id());
845 host->frontend()->OnEventRaised(ids, event_id); 918 host->frontend()->OnEventRaised(ids, event_id);
846 } 919 }
847 920
848 void AppCacheUpdateJob::NotifyAllAssociatedHosts(EventID event_id) { 921 void AppCacheUpdateJob::NotifyAllAssociatedHosts(EventID event_id) {
849 HostNotifier host_notifier; 922 HostNotifier host_notifier;
850 AddAllAssociatedHostsToNotifier(&host_notifier); 923 AddAllAssociatedHostsToNotifier(&host_notifier);
851 host_notifier.SendNotifications(event_id); 924 host_notifier.SendNotifications(event_id);
852 } 925 }
853 926
854 void AppCacheUpdateJob::NotifyAllProgress(const GURL& url) { 927 void AppCacheUpdateJob::NotifyAllProgress(const GURL& url) {
855 HostNotifier host_notifier; 928 HostNotifier host_notifier;
856 AddAllAssociatedHostsToNotifier(&host_notifier); 929 AddAllAssociatedHostsToNotifier(&host_notifier);
857 host_notifier.SendProgressNotifications( 930 host_notifier.SendProgressNotifications(
858 url, url_file_list_.size(), url_fetches_completed_); 931 url, url_file_list_.size(), url_fetches_completed_);
859 } 932 }
860 933
861 void AppCacheUpdateJob::NotifyAllFinalProgress() { 934 void AppCacheUpdateJob::NotifyAllFinalProgress() {
862 DCHECK(url_file_list_.size() == url_fetches_completed_); 935 DCHECK(url_file_list_.size() == url_fetches_completed_);
863 NotifyAllProgress(GURL()); 936 NotifyAllProgress(GURL());
864 } 937 }
865 938
866 void AppCacheUpdateJob::NotifyAllError(const std::string& error_message) { 939 void AppCacheUpdateJob::NotifyAllError(const ErrorDetails& details) {
867 HostNotifier host_notifier; 940 HostNotifier host_notifier;
868 AddAllAssociatedHostsToNotifier(&host_notifier); 941 AddAllAssociatedHostsToNotifier(&host_notifier);
869 host_notifier.SendErrorNotifications(error_message); 942 host_notifier.SendErrorNotifications(details);
870 } 943 }
871 944
872 void AppCacheUpdateJob::AddAllAssociatedHostsToNotifier( 945 void AppCacheUpdateJob::AddAllAssociatedHostsToNotifier(
873 HostNotifier* host_notifier) { 946 HostNotifier* host_notifier) {
874 // Collect hosts so we only send one notification per frontend. 947 // 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 948 // A host can only be associated with a single cache so no need to worry
876 // about duplicate hosts being added to the notifier. 949 // about duplicate hosts being added to the notifier.
877 if (inprogress_cache_.get()) { 950 if (inprogress_cache_.get()) {
878 DCHECK(internal_state_ == DOWNLOADING || internal_state_ == CACHE_FAILURE); 951 DCHECK(internal_state_ == DOWNLOADING || internal_state_ == CACHE_FAILURE);
879 host_notifier->AddHosts(inprogress_cache_->associated_hosts()); 952 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); 986 DCHECK(update_type_ == UPGRADE_ATTEMPT);
914 AppCacheEntry* entry = NULL; 987 AppCacheEntry* entry = NULL;
915 if (group_->newest_complete_cache()) 988 if (group_->newest_complete_cache())
916 entry = group_->newest_complete_cache()->GetEntry(manifest_url_); 989 entry = group_->newest_complete_cache()->GetEntry(manifest_url_);
917 if (!entry) { 990 if (!entry) {
918 // TODO(michaeln): This is just a bandaid to avoid a crash. 991 // TODO(michaeln): This is just a bandaid to avoid a crash.
919 // http://code.google.com/p/chromium/issues/detail?id=95101 992 // http://code.google.com/p/chromium/issues/detail?id=95101
920 if (service_->storage() == storage_) { 993 if (service_->storage() == storage_) {
921 // Use a local variable because service_ is reset in HandleCacheFailure. 994 // Use a local variable because service_ is reset in HandleCacheFailure.
922 AppCacheService* service = service_; 995 AppCacheService* service = service_;
923 HandleCacheFailure("Manifest entry not found in existing cache", 996 HandleCacheFailure(
924 DB_ERROR, GURL()); 997 ErrorDetails("Manifest entry not found in existing cache",
998 UNKNOWN_ERROR,
999 GURL(),
1000 0,
1001 false /*is_cross_origin*/),
1002 DB_ERROR);
925 AppCacheHistograms::AddMissingManifestEntrySample(); 1003 AppCacheHistograms::AddMissingManifestEntrySample();
926 service->DeleteAppCacheGroup(manifest_url_, net::CompletionCallback()); 1004 service->DeleteAppCacheGroup(manifest_url_, net::CompletionCallback());
927 } 1005 }
928 return; 1006 return;
929 } 1007 }
930 1008
931 // Load manifest data from storage to compare against fetched manifest. 1009 // Load manifest data from storage to compare against fetched manifest.
932 manifest_response_reader_.reset( 1010 manifest_response_reader_.reset(
933 storage_->CreateResponseReader(manifest_url_, 1011 storage_->CreateResponseReader(manifest_url_,
934 group_->group_id(), 1012 group_->group_id(),
(...skipping 220 matching lines...) Expand 10 before | Expand all | Expand 10 after
1155 url, URLFetcher::MASTER_ENTRY_FETCH, this); 1233 url, URLFetcher::MASTER_ENTRY_FETCH, this);
1156 fetcher->Start(); 1234 fetcher->Start();
1157 master_entry_fetches_.insert(PendingUrlFetches::value_type(url, fetcher)); 1235 master_entry_fetches_.insert(PendingUrlFetches::value_type(url, fetcher));
1158 } 1236 }
1159 1237
1160 master_entries_to_fetch_.erase(master_entries_to_fetch_.begin()); 1238 master_entries_to_fetch_.erase(master_entries_to_fetch_.begin());
1161 } 1239 }
1162 } 1240 }
1163 1241
1164 void AppCacheUpdateJob::CancelAllMasterEntryFetches( 1242 void AppCacheUpdateJob::CancelAllMasterEntryFetches(
1165 const std::string& error_message) { 1243 const ErrorDetails& error_details) {
1166 // For now, cancel all in-progress fetches for master entries and pretend 1244 // For now, cancel all in-progress fetches for master entries and pretend
1167 // all master entries fetches have completed. 1245 // all master entries fetches have completed.
1168 // TODO(jennb): Delete this when update no longer fetches master entries 1246 // TODO(jennb): Delete this when update no longer fetches master entries
1169 // directly. 1247 // directly.
1170 1248
1171 // Cancel all in-progress fetches. 1249 // Cancel all in-progress fetches.
1172 for (PendingUrlFetches::iterator it = master_entry_fetches_.begin(); 1250 for (PendingUrlFetches::iterator it = master_entry_fetches_.begin();
1173 it != master_entry_fetches_.end(); ++it) { 1251 it != master_entry_fetches_.end(); ++it) {
1174 delete it->second; 1252 delete it->second;
1175 master_entries_to_fetch_.insert(it->first); // back in unfetched list 1253 master_entries_to_fetch_.insert(it->first); // back in unfetched list
(...skipping 15 matching lines...) Expand all
1191 host_it != hosts.end(); ++host_it) { 1269 host_it != hosts.end(); ++host_it) {
1192 AppCacheHost* host = *host_it; 1270 AppCacheHost* host = *host_it;
1193 host->AssociateNoCache(GURL()); 1271 host->AssociateNoCache(GURL());
1194 host_notifier.AddHost(host); 1272 host_notifier.AddHost(host);
1195 host->RemoveObserver(this); 1273 host->RemoveObserver(this);
1196 } 1274 }
1197 hosts.clear(); 1275 hosts.clear();
1198 1276
1199 master_entries_to_fetch_.erase(master_entries_to_fetch_.begin()); 1277 master_entries_to_fetch_.erase(master_entries_to_fetch_.begin());
1200 } 1278 }
1201 host_notifier.SendErrorNotifications(error_message); 1279 host_notifier.SendErrorNotifications(error_details);
1202 } 1280 }
1203 1281
1204 bool AppCacheUpdateJob::MaybeLoadFromNewestCache(const GURL& url, 1282 bool AppCacheUpdateJob::MaybeLoadFromNewestCache(const GURL& url,
1205 AppCacheEntry& entry) { 1283 AppCacheEntry& entry) {
1206 if (update_type_ != UPGRADE_ATTEMPT) 1284 if (update_type_ != UPGRADE_ATTEMPT)
1207 return false; 1285 return false;
1208 1286
1209 AppCache* newest = group_->newest_complete_cache(); 1287 AppCache* newest = group_->newest_complete_cache();
1210 AppCacheEntry* copy_me = newest->GetEntry(url); 1288 AppCacheEntry* copy_me = newest->GetEntry(url);
1211 if (!copy_me || !copy_me->has_response_id()) 1289 if (!copy_me || !copy_me->has_response_id())
(...skipping 255 matching lines...) Expand 10 before | Expand all | Expand 10 after
1467 1545
1468 // Break the connection with the group so the group cannot call delete 1546 // 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. 1547 // on this object after we've posted a task to delete ourselves.
1470 group_->SetUpdateStatus(AppCacheGroup::IDLE); 1548 group_->SetUpdateStatus(AppCacheGroup::IDLE);
1471 group_ = NULL; 1549 group_ = NULL;
1472 1550
1473 base::MessageLoop::current()->DeleteSoon(FROM_HERE, this); 1551 base::MessageLoop::current()->DeleteSoon(FROM_HERE, this);
1474 } 1552 }
1475 1553
1476 } // namespace appcache 1554 } // 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