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

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

Issue 165613002: Add UMA stats for AppCacheUpdateJob results. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 6 years, 10 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"
11 #include "base/strings/string_util.h" 11 #include "base/strings/string_util.h"
12 #include "base/strings/stringprintf.h" 12 #include "base/strings/stringprintf.h"
13 #include "net/base/io_buffer.h" 13 #include "net/base/io_buffer.h"
14 #include "net/base/load_flags.h" 14 #include "net/base/load_flags.h"
15 #include "net/base/net_errors.h" 15 #include "net/base/net_errors.h"
16 #include "net/base/request_priority.h" 16 #include "net/base/request_priority.h"
17 #include "net/http/http_request_headers.h" 17 #include "net/http/http_request_headers.h"
18 #include "net/http/http_response_headers.h" 18 #include "net/http/http_response_headers.h"
19 #include "net/url_request/url_request_context.h" 19 #include "net/url_request/url_request_context.h"
20 #include "webkit/browser/appcache/appcache_group.h" 20 #include "webkit/browser/appcache/appcache_group.h"
21 #include "webkit/browser/appcache/appcache_histograms.h" 21 #include "webkit/browser/appcache/appcache_histograms.h"
22 22
23 namespace appcache { 23 namespace appcache {
24 24
25 static const int kBufferSize = 32768; 25 static const int kBufferSize = 32768;
26 static const size_t kMaxConcurrentUrlFetches = 2; 26 static const size_t kMaxConcurrentUrlFetches = 2;
27 static const int kMax503Retries = 3; 27 static const int kMax503Retries = 3;
28 28
29 static std::string FormatUrlErrorMessage(
30 const char* format, const GURL& url,
31 AppCacheUpdateJob::ResultType error,
32 int response_code) {
33 // Show the net response code if we have one.
34 int code = response_code;
35 if (error != AppCacheUpdateJob::SERVER_ERROR)
36 code = static_cast<int>(error);
37 return base::StringPrintf(format, code, url.spec().c_str());
38 }
39
29 // Helper class for collecting hosts per frontend when sending notifications 40 // Helper class for collecting hosts per frontend when sending notifications
30 // so that only one notification is sent for all hosts using the same frontend. 41 // so that only one notification is sent for all hosts using the same frontend.
31 class HostNotifier { 42 class HostNotifier {
32 public: 43 public:
33 typedef std::vector<int> HostIds; 44 typedef std::vector<int> HostIds;
34 typedef std::map<AppCacheFrontend*, HostIds> NotifyHostMap; 45 typedef std::map<AppCacheFrontend*, HostIds> NotifyHostMap;
35 46
36 // Caller is responsible for ensuring there will be no duplicate hosts. 47 // Caller is responsible for ensuring there will be no duplicate hosts.
37 void AddHost(AppCacheHost* host) { 48 void AddHost(AppCacheHost* host) {
38 std::pair<NotifyHostMap::iterator , bool> ret = hosts_to_notify.insert( 49 std::pair<NotifyHostMap::iterator , bool> ret = hosts_to_notify.insert(
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
94 // data out to the disk cache. 105 // data out to the disk cache.
95 AppCacheUpdateJob::URLFetcher::URLFetcher(const GURL& url, 106 AppCacheUpdateJob::URLFetcher::URLFetcher(const GURL& url,
96 FetchType fetch_type, 107 FetchType fetch_type,
97 AppCacheUpdateJob* job) 108 AppCacheUpdateJob* job)
98 : url_(url), 109 : url_(url),
99 job_(job), 110 job_(job),
100 fetch_type_(fetch_type), 111 fetch_type_(fetch_type),
101 retry_503_attempts_(0), 112 retry_503_attempts_(0),
102 buffer_(new net::IOBuffer(kBufferSize)), 113 buffer_(new net::IOBuffer(kBufferSize)),
103 request_(job->service_->request_context() 114 request_(job->service_->request_context()
104 ->CreateRequest(url, net::DEFAULT_PRIORITY, this)) {} 115 ->CreateRequest(url, net::DEFAULT_PRIORITY, this)),
116 result_(UPDATE_OK) {}
105 117
106 AppCacheUpdateJob::URLFetcher::~URLFetcher() { 118 AppCacheUpdateJob::URLFetcher::~URLFetcher() {
107 } 119 }
108 120
109 void AppCacheUpdateJob::URLFetcher::Start() { 121 void AppCacheUpdateJob::URLFetcher::Start() {
110 request_->set_first_party_for_cookies(job_->manifest_url_); 122 request_->set_first_party_for_cookies(job_->manifest_url_);
111 request_->SetLoadFlags(request_->load_flags() | 123 request_->SetLoadFlags(request_->load_flags() |
112 net::LOAD_DISABLE_INTERCEPT); 124 net::LOAD_DISABLE_INTERCEPT);
113 if (existing_response_headers_.get()) 125 if (existing_response_headers_.get())
114 AddConditionalHeaders(existing_response_headers_.get()); 126 AddConditionalHeaders(existing_response_headers_.get());
115 request_->Start(); 127 request_->Start();
116 } 128 }
117 129
118 void AppCacheUpdateJob::URLFetcher::OnReceivedRedirect( 130 void AppCacheUpdateJob::URLFetcher::OnReceivedRedirect(
119 net::URLRequest* request, const GURL& new_url, bool* defer_redirect) { 131 net::URLRequest* request, const GURL& new_url, bool* defer_redirect) {
120 DCHECK(request_ == request); 132 DCHECK(request_ == request);
121 // Redirect is not allowed by the update process. 133 // Redirect is not allowed by the update process.
122 request->Cancel(); 134 request->Cancel();
135 result_ = REDIRECT_ERROR;
123 OnResponseCompleted(); 136 OnResponseCompleted();
124 } 137 }
125 138
126 void AppCacheUpdateJob::URLFetcher::OnResponseStarted( 139 void AppCacheUpdateJob::URLFetcher::OnResponseStarted(
127 net::URLRequest *request) { 140 net::URLRequest *request) {
128 DCHECK(request == request_); 141 DCHECK(request == request_);
129 if (request->status().is_success() && 142 int response_code = -1;
130 (request->GetResponseCode() / 100) == 2) { 143 if (request->status().is_success())
144 response_code = request->GetResponseCode();
145 if ((response_code / 100) == 2) {
131 146
132 // See http://code.google.com/p/chromium/issues/detail?id=69594 147 // See http://code.google.com/p/chromium/issues/detail?id=69594
133 // We willfully violate the HTML5 spec at this point in order 148 // We willfully violate the HTML5 spec at this point in order
134 // to support the appcaching of cross-origin HTTPS resources. 149 // to support the appcaching of cross-origin HTTPS resources.
135 // We've opted for a milder constraint and allow caching unless 150 // We've opted for a milder constraint and allow caching unless
136 // the resource has a "no-store" header. A spec change has been 151 // the resource has a "no-store" header. A spec change has been
137 // requested on the whatwg list. 152 // requested on the whatwg list.
138 // TODO(michaeln): Consider doing this for cross-origin HTTP resources too. 153 // TODO(michaeln): Consider doing this for cross-origin HTTP resources too.
139 if (url_.SchemeIsSecure() && 154 if (url_.SchemeIsSecure() &&
140 url_.GetOrigin() != job_->manifest_url_.GetOrigin()) { 155 url_.GetOrigin() != job_->manifest_url_.GetOrigin()) {
141 if (request->response_headers()-> 156 if (request->response_headers()->
142 HasHeaderValue("cache-control", "no-store")) { 157 HasHeaderValue("cache-control", "no-store")) {
143 request->Cancel(); 158 request->Cancel();
159 result_ = SERVER_ERROR; // ??
144 OnResponseCompleted(); 160 OnResponseCompleted();
145 return; 161 return;
146 } 162 }
147 } 163 }
148 164
149 // Write response info to storage for URL fetches. Wait for async write 165 // Write response info to storage for URL fetches. Wait for async write
150 // completion before reading any response data. 166 // completion before reading any response data.
151 if (fetch_type_ == URL_FETCH || fetch_type_ == MASTER_ENTRY_FETCH) { 167 if (fetch_type_ == URL_FETCH || fetch_type_ == MASTER_ENTRY_FETCH) {
152 response_writer_.reset(job_->CreateResponseWriter()); 168 response_writer_.reset(job_->CreateResponseWriter());
153 scoped_refptr<HttpResponseInfoIOBuffer> io_buffer( 169 scoped_refptr<HttpResponseInfoIOBuffer> io_buffer(
154 new HttpResponseInfoIOBuffer( 170 new HttpResponseInfoIOBuffer(
155 new net::HttpResponseInfo(request->response_info()))); 171 new net::HttpResponseInfo(request->response_info())));
156 response_writer_->WriteInfo( 172 response_writer_->WriteInfo(
157 io_buffer.get(), 173 io_buffer.get(),
158 base::Bind(&URLFetcher::OnWriteComplete, base::Unretained(this))); 174 base::Bind(&URLFetcher::OnWriteComplete, base::Unretained(this)));
159 } else { 175 } else {
160 ReadResponseData(); 176 ReadResponseData();
161 } 177 }
162 } else { 178 } else {
179 if (response_code > 0)
180 result_ = SERVER_ERROR;
181 else
182 result_ = NETWORK_ERROR;
163 OnResponseCompleted(); 183 OnResponseCompleted();
164 } 184 }
165 } 185 }
166 186
167 void AppCacheUpdateJob::URLFetcher::OnReadCompleted( 187 void AppCacheUpdateJob::URLFetcher::OnReadCompleted(
168 net::URLRequest* request, int bytes_read) { 188 net::URLRequest* request, int bytes_read) {
169 DCHECK(request_ == request); 189 DCHECK(request_ == request);
170 bool data_consumed = true; 190 bool data_consumed = true;
171 if (request->status().is_success() && bytes_read > 0) { 191 if (request->status().is_success() && bytes_read > 0) {
172 data_consumed = ConsumeResponseData(bytes_read); 192 data_consumed = ConsumeResponseData(bytes_read);
173 if (data_consumed) { 193 if (data_consumed) {
174 bytes_read = 0; 194 bytes_read = 0;
175 while (request->Read(buffer_.get(), kBufferSize, &bytes_read)) { 195 while (request->Read(buffer_.get(), kBufferSize, &bytes_read)) {
176 if (bytes_read > 0) { 196 if (bytes_read > 0) {
177 data_consumed = ConsumeResponseData(bytes_read); 197 data_consumed = ConsumeResponseData(bytes_read);
178 if (!data_consumed) 198 if (!data_consumed)
179 break; // wait for async data processing, then read more 199 break; // wait for async data processing, then read more
180 } else { 200 } else {
181 break; 201 break;
182 } 202 }
183 } 203 }
184 } 204 }
185 } 205 }
186 if (data_consumed && !request->status().is_io_pending()) 206 if (data_consumed && !request->status().is_io_pending()) {
207 DCHECK_EQ(UPDATE_OK, result_);
187 OnResponseCompleted(); 208 OnResponseCompleted();
209 }
188 } 210 }
189 211
190 void AppCacheUpdateJob::URLFetcher::AddConditionalHeaders( 212 void AppCacheUpdateJob::URLFetcher::AddConditionalHeaders(
191 const net::HttpResponseHeaders* headers) { 213 const net::HttpResponseHeaders* headers) {
192 DCHECK(request_.get() && headers); 214 DCHECK(request_.get() && headers);
193 net::HttpRequestHeaders extra_headers; 215 net::HttpRequestHeaders extra_headers;
194 216
195 // Add If-Modified-Since header if response info has Last-Modified header. 217 // Add If-Modified-Since header if response info has Last-Modified header.
196 const std::string last_modified = "Last-Modified"; 218 const std::string last_modified = "Last-Modified";
197 std::string last_modified_value; 219 std::string last_modified_value;
(...skipping 11 matching lines...) Expand all
209 extra_headers.SetHeader(net::HttpRequestHeaders::kIfNoneMatch, 231 extra_headers.SetHeader(net::HttpRequestHeaders::kIfNoneMatch,
210 etag_value); 232 etag_value);
211 } 233 }
212 if (!extra_headers.IsEmpty()) 234 if (!extra_headers.IsEmpty())
213 request_->SetExtraRequestHeaders(extra_headers); 235 request_->SetExtraRequestHeaders(extra_headers);
214 } 236 }
215 237
216 void AppCacheUpdateJob::URLFetcher::OnWriteComplete(int result) { 238 void AppCacheUpdateJob::URLFetcher::OnWriteComplete(int result) {
217 if (result < 0) { 239 if (result < 0) {
218 request_->Cancel(); 240 request_->Cancel();
241 result_ = DISKCACHE_ERROR;
219 OnResponseCompleted(); 242 OnResponseCompleted();
220 return; 243 return;
221 } 244 }
222 ReadResponseData(); 245 ReadResponseData();
223 } 246 }
224 247
225 void AppCacheUpdateJob::URLFetcher::ReadResponseData() { 248 void AppCacheUpdateJob::URLFetcher::ReadResponseData() {
226 InternalUpdateState state = job_->internal_state_; 249 InternalUpdateState state = job_->internal_state_;
227 if (state == CACHE_FAILURE || state == CANCELLED || state == COMPLETED) 250 if (state == CACHE_FAILURE || state == CANCELLED || state == COMPLETED)
228 return; 251 return;
(...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after
389 } 412 }
390 413
391 AppCacheResponseWriter* AppCacheUpdateJob::CreateResponseWriter() { 414 AppCacheResponseWriter* AppCacheUpdateJob::CreateResponseWriter() {
392 AppCacheResponseWriter* writer = 415 AppCacheResponseWriter* writer =
393 storage_->CreateResponseWriter(manifest_url_, 416 storage_->CreateResponseWriter(manifest_url_,
394 group_->group_id()); 417 group_->group_id());
395 stored_response_ids_.push_back(writer->response_id()); 418 stored_response_ids_.push_back(writer->response_id());
396 return writer; 419 return writer;
397 } 420 }
398 421
399 void AppCacheUpdateJob::HandleCacheFailure(const std::string& error_message) { 422 void AppCacheUpdateJob::HandleCacheFailure(
423 const std::string& error_message,
424 ResultType result) {
400 // 6.9.4 cache failure steps 2-8. 425 // 6.9.4 cache failure steps 2-8.
401 DCHECK(internal_state_ != CACHE_FAILURE); 426 DCHECK(internal_state_ != CACHE_FAILURE);
402 DCHECK(!error_message.empty()); 427 DCHECK(!error_message.empty());
403 internal_state_ = CACHE_FAILURE; 428 internal_state_ = CACHE_FAILURE;
404 CancelAllUrlFetches(); 429 CancelAllUrlFetches();
405 CancelAllMasterEntryFetches(error_message); 430 CancelAllMasterEntryFetches(error_message);
406 NotifyAllError(error_message); 431 NotifyAllError(error_message);
407 DiscardInprogressCache(); 432 DiscardInprogressCache();
408 internal_state_ = COMPLETED; 433 internal_state_ = COMPLETED;
434 AppCacheHistograms::CountUpdateJobResult(result);
409 DeleteSoon(); // To unwind the stack prior to deletion. 435 DeleteSoon(); // To unwind the stack prior to deletion.
410 } 436 }
411 437
412 void AppCacheUpdateJob::FetchManifest(bool is_first_fetch) { 438 void AppCacheUpdateJob::FetchManifest(bool is_first_fetch) {
413 DCHECK(!manifest_fetcher_); 439 DCHECK(!manifest_fetcher_);
414 manifest_fetcher_ = new URLFetcher( 440 manifest_fetcher_ = new URLFetcher(
415 manifest_url_, 441 manifest_url_,
416 is_first_fetch ? URLFetcher::MANIFEST_FETCH : 442 is_first_fetch ? URLFetcher::MANIFEST_FETCH :
417 URLFetcher::MANIFEST_REFETCH, 443 URLFetcher::MANIFEST_REFETCH,
418 this); 444 this);
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
460 CheckIfManifestChanged(); // continues asynchronously 486 CheckIfManifestChanged(); // continues asynchronously
461 else 487 else
462 ContinueHandleManifestFetchCompleted(true); 488 ContinueHandleManifestFetchCompleted(true);
463 } else if (response_code == 304 && update_type_ == UPGRADE_ATTEMPT) { 489 } else if (response_code == 304 && update_type_ == UPGRADE_ATTEMPT) {
464 ContinueHandleManifestFetchCompleted(false); 490 ContinueHandleManifestFetchCompleted(false);
465 } else if ((response_code == 404 || response_code == 410) && 491 } else if ((response_code == 404 || response_code == 410) &&
466 update_type_ == UPGRADE_ATTEMPT) { 492 update_type_ == UPGRADE_ATTEMPT) {
467 storage_->MakeGroupObsolete(group_, this); // async 493 storage_->MakeGroupObsolete(group_, this); // async
468 } else { 494 } else {
469 const char* kFormatString = "Manifest fetch failed (%d) %s"; 495 const char* kFormatString = "Manifest fetch failed (%d) %s";
470 std::string message = base::StringPrintf(kFormatString, response_code, 496 std::string message = FormatUrlErrorMessage(
471 manifest_url_.spec().c_str()); 497 kFormatString, manifest_url_, fetcher->result(), response_code);
472 HandleCacheFailure(message); 498 HandleCacheFailure(message, fetcher->result());
473 } 499 }
474 } 500 }
475 501
476 void AppCacheUpdateJob::OnGroupMadeObsolete(AppCacheGroup* group, 502 void AppCacheUpdateJob::OnGroupMadeObsolete(AppCacheGroup* group,
477 bool success) { 503 bool success) {
478 DCHECK(master_entry_fetches_.empty()); 504 DCHECK(master_entry_fetches_.empty());
479 CancelAllMasterEntryFetches("The cache has been made obsolete, " 505 CancelAllMasterEntryFetches("The cache has been made obsolete, "
480 "the manifest file returned 404 or 410"); 506 "the manifest file returned 404 or 410");
481 if (success) { 507 if (success) {
482 DCHECK(group->is_obsolete()); 508 DCHECK(group->is_obsolete());
483 NotifyAllAssociatedHosts(OBSOLETE_EVENT); 509 NotifyAllAssociatedHosts(OBSOLETE_EVENT);
484 internal_state_ = COMPLETED; 510 internal_state_ = COMPLETED;
485 MaybeCompleteUpdate(); 511 MaybeCompleteUpdate();
486 } else { 512 } else {
487 // Treat failure to mark group obsolete as a cache failure. 513 // Treat failure to mark group obsolete as a cache failure.
488 HandleCacheFailure("Failed to mark the cache as obsolete"); 514 HandleCacheFailure("Failed to mark the cache as obsolete", DB_ERROR);
489 } 515 }
490 } 516 }
491 517
492 void AppCacheUpdateJob::ContinueHandleManifestFetchCompleted(bool changed) { 518 void AppCacheUpdateJob::ContinueHandleManifestFetchCompleted(bool changed) {
493 DCHECK(internal_state_ == FETCH_MANIFEST); 519 DCHECK(internal_state_ == FETCH_MANIFEST);
494 520
495 if (!changed) { 521 if (!changed) {
496 DCHECK(update_type_ == UPGRADE_ATTEMPT); 522 DCHECK(update_type_ == UPGRADE_ATTEMPT);
497 internal_state_ = NO_UPDATE; 523 internal_state_ = NO_UPDATE;
498 524
499 // Wait for pending master entries to download. 525 // Wait for pending master entries to download.
500 FetchMasterEntries(); 526 FetchMasterEntries();
501 MaybeCompleteUpdate(); // if not done, run async 6.9.4 step 7 substeps 527 MaybeCompleteUpdate(); // if not done, run async 6.9.4 step 7 substeps
502 return; 528 return;
503 } 529 }
504 530
505 Manifest manifest; 531 Manifest manifest;
506 if (!ParseManifest(manifest_url_, manifest_data_.data(), 532 if (!ParseManifest(manifest_url_, manifest_data_.data(),
507 manifest_data_.length(), manifest)) { 533 manifest_data_.length(), manifest)) {
508 const char* kFormatString = "Failed to parse manifest %s"; 534 const char* kFormatString = "Failed to parse manifest %s";
509 const std::string message = base::StringPrintf(kFormatString, 535 const std::string message = base::StringPrintf(kFormatString,
510 manifest_url_.spec().c_str()); 536 manifest_url_.spec().c_str());
511 HandleCacheFailure(message); 537 HandleCacheFailure(message, MANIFEST_ERROR);
512 VLOG(1) << message; 538 VLOG(1) << message;
513 return; 539 return;
514 } 540 }
515 541
516 // Proceed with update process. Section 6.9.4 steps 8-20. 542 // Proceed with update process. Section 6.9.4 steps 8-20.
517 internal_state_ = DOWNLOADING; 543 internal_state_ = DOWNLOADING;
518 inprogress_cache_ = new AppCache(storage_, storage_->NewCacheId()); 544 inprogress_cache_ = new AppCache(storage_, storage_->NewCacheId());
519 BuildUrlFileList(manifest); 545 BuildUrlFileList(manifest);
520 inprogress_cache_->InitializeWithManifest(&manifest); 546 inprogress_cache_->InitializeWithManifest(&manifest);
521 547
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
573 << " error: " << request->status().error() 599 << " error: " << request->status().error()
574 << " response code: " << response_code; 600 << " response code: " << response_code;
575 if (entry.IsExplicit() || entry.IsFallback() || entry.IsIntercept()) { 601 if (entry.IsExplicit() || entry.IsFallback() || entry.IsIntercept()) {
576 if (response_code == 304 && fetcher->existing_entry().has_response_id()) { 602 if (response_code == 304 && fetcher->existing_entry().has_response_id()) {
577 // Keep the existing response. 603 // Keep the existing response.
578 entry.set_response_id(fetcher->existing_entry().response_id()); 604 entry.set_response_id(fetcher->existing_entry().response_id());
579 entry.set_response_size(fetcher->existing_entry().response_size()); 605 entry.set_response_size(fetcher->existing_entry().response_size());
580 inprogress_cache_->AddOrModifyEntry(url, entry); 606 inprogress_cache_->AddOrModifyEntry(url, entry);
581 } else { 607 } else {
582 const char* kFormatString = "Resource fetch failed (%d) %s"; 608 const char* kFormatString = "Resource fetch failed (%d) %s";
583 const std::string message = base::StringPrintf(kFormatString, 609 std::string message = FormatUrlErrorMessage(
584 response_code, url.spec().c_str()); 610 kFormatString, url, fetcher->result(), response_code);
585 HandleCacheFailure(message); 611 HandleCacheFailure(message, fetcher->result());
586 return; 612 return;
587 } 613 }
588 } else if (response_code == 404 || response_code == 410) { 614 } else if (response_code == 404 || response_code == 410) {
589 // Entry is skipped. They are dropped from the cache. 615 // Entry is skipped. They are dropped from the cache.
590 } else if (update_type_ == UPGRADE_ATTEMPT && 616 } else if (update_type_ == UPGRADE_ATTEMPT &&
591 fetcher->existing_entry().has_response_id()) { 617 fetcher->existing_entry().has_response_id()) {
592 // Keep the existing response. 618 // Keep the existing response.
593 // TODO(michaeln): Not sure this is a good idea. This is spec compliant 619 // TODO(michaeln): Not sure this is a good idea. This is spec compliant
594 // but the old resource may or may not be compatible with the new contents 620 // but the old resource may or may not be compatible with the new contents
595 // of the cache. Impossible to know one way or the other. 621 // of the cache. Impossible to know one way or the other.
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
657 host_notifier.AddHost(host); 683 host_notifier.AddHost(host);
658 684
659 // In downloading case, disassociate host from inprogress cache. 685 // In downloading case, disassociate host from inprogress cache.
660 if (inprogress_cache_.get()) 686 if (inprogress_cache_.get())
661 host->AssociateNoCache(GURL()); 687 host->AssociateNoCache(GURL());
662 688
663 host->RemoveObserver(this); 689 host->RemoveObserver(this);
664 } 690 }
665 hosts.clear(); 691 hosts.clear();
666 692
667 const char* kFormatString = "Master entry fetch failed (%d) %s"; 693 const char* kFormatString = "Manifest fetch failed (%d) %s";
668 const std::string message = base::StringPrintf(kFormatString, 694 std::string message = FormatUrlErrorMessage(
669 response_code, request->url().spec().c_str()); 695 kFormatString, request->url(), fetcher->result(), response_code);
670 host_notifier.SendErrorNotifications(message); 696 host_notifier.SendErrorNotifications(message);
671 697
672 // In downloading case, update result is different if all master entries 698 // In downloading case, update result is different if all master entries
673 // failed vs. only some failing. 699 // failed vs. only some failing.
674 if (inprogress_cache_.get()) { 700 if (inprogress_cache_.get()) {
675 // Only count successful downloads to know if all master entries failed. 701 // Only count successful downloads to know if all master entries failed.
676 pending_master_entries_.erase(found); 702 pending_master_entries_.erase(found);
677 --master_entries_completed_; 703 --master_entries_completed_;
678 704
679 // Section 6.9.4, step 22.3. 705 // Section 6.9.4, step 22.3.
680 if (update_type_ == CACHE_ATTEMPT && pending_master_entries_.empty()) { 706 if (update_type_ == CACHE_ATTEMPT && pending_master_entries_.empty()) {
681 HandleCacheFailure(message); 707 DCHECK(fetcher->result() != UPDATE_OK);
michaeln 2014/02/14 23:42:06 i'll put this dcheck in HandleCacheFailure()
708 HandleCacheFailure(message, fetcher->result());
682 return; 709 return;
683 } 710 }
684 } 711 }
685 } 712 }
686 713
687 DCHECK(internal_state_ != CACHE_FAILURE); 714 DCHECK(internal_state_ != CACHE_FAILURE);
688 FetchMasterEntries(); 715 FetchMasterEntries();
689 MaybeCompleteUpdate(); 716 MaybeCompleteUpdate();
690 } 717 }
691 718
(...skipping 20 matching lines...) Expand all
712 manifest_response_writer_->WriteInfo( 739 manifest_response_writer_->WriteInfo(
713 io_buffer.get(), 740 io_buffer.get(),
714 base::Bind(&AppCacheUpdateJob::OnManifestInfoWriteComplete, 741 base::Bind(&AppCacheUpdateJob::OnManifestInfoWriteComplete,
715 base::Unretained(this))); 742 base::Unretained(this)));
716 } 743 }
717 } else { 744 } else {
718 VLOG(1) << "Request status: " << request->status().status() 745 VLOG(1) << "Request status: " << request->status().status()
719 << " error: " << request->status().error() 746 << " error: " << request->status().error()
720 << " response code: " << response_code; 747 << " response code: " << response_code;
721 ScheduleUpdateRetry(kRerunDelayMs); 748 ScheduleUpdateRetry(kRerunDelayMs);
722 HandleCacheFailure("Manifest changed during update, scheduling retry"); 749 if (response_code == 200) {
750 HandleCacheFailure("Manifest changed during update", MANIFEST_ERROR);
751 } else {
752 const char* kFormatString = "Manifest re-fetch failed (%d) %s";
753 std::string message = FormatUrlErrorMessage(
754 kFormatString, manifest_url_, fetcher->result(), response_code);
755 HandleCacheFailure(message, fetcher->result());
756 }
723 } 757 }
724 } 758 }
725 759
726 void AppCacheUpdateJob::OnManifestInfoWriteComplete(int result) { 760 void AppCacheUpdateJob::OnManifestInfoWriteComplete(int result) {
727 if (result > 0) { 761 if (result > 0) {
728 scoped_refptr<net::StringIOBuffer> io_buffer( 762 scoped_refptr<net::StringIOBuffer> io_buffer(
729 new net::StringIOBuffer(manifest_data_)); 763 new net::StringIOBuffer(manifest_data_));
730 manifest_response_writer_->WriteData( 764 manifest_response_writer_->WriteData(
731 io_buffer.get(), 765 io_buffer.get(),
732 manifest_data_.length(), 766 manifest_data_.length(),
733 base::Bind(&AppCacheUpdateJob::OnManifestDataWriteComplete, 767 base::Bind(&AppCacheUpdateJob::OnManifestDataWriteComplete,
734 base::Unretained(this))); 768 base::Unretained(this)));
735 } else { 769 } else {
736 HandleCacheFailure("Failed to write the manifest headers to storage"); 770 HandleCacheFailure("Failed to write the manifest headers to storage",
771 DISKCACHE_ERROR);
737 } 772 }
738 } 773 }
739 774
740 void AppCacheUpdateJob::OnManifestDataWriteComplete(int result) { 775 void AppCacheUpdateJob::OnManifestDataWriteComplete(int result) {
741 if (result > 0) { 776 if (result > 0) {
742 AppCacheEntry entry(AppCacheEntry::MANIFEST, 777 AppCacheEntry entry(AppCacheEntry::MANIFEST,
743 manifest_response_writer_->response_id(), 778 manifest_response_writer_->response_id(),
744 manifest_response_writer_->amount_written()); 779 manifest_response_writer_->amount_written());
745 if (!inprogress_cache_->AddOrModifyEntry(manifest_url_, entry)) 780 if (!inprogress_cache_->AddOrModifyEntry(manifest_url_, entry))
746 duplicate_response_ids_.push_back(entry.response_id()); 781 duplicate_response_ids_.push_back(entry.response_id());
747 StoreGroupAndCache(); 782 StoreGroupAndCache();
748 } else { 783 } else {
749 HandleCacheFailure("Failed to write the manifest data to storage"); 784 HandleCacheFailure("Failed to write the manifest data to storage",
785 DISKCACHE_ERROR);
750 } 786 }
751 } 787 }
752 788
753 void AppCacheUpdateJob::StoreGroupAndCache() { 789 void AppCacheUpdateJob::StoreGroupAndCache() {
754 DCHECK(stored_state_ == UNSTORED); 790 DCHECK(stored_state_ == UNSTORED);
755 stored_state_ = STORING; 791 stored_state_ = STORING;
756 scoped_refptr<AppCache> newest_cache; 792 scoped_refptr<AppCache> newest_cache;
757 if (inprogress_cache_.get()) 793 if (inprogress_cache_.get())
758 newest_cache.swap(inprogress_cache_); 794 newest_cache.swap(inprogress_cache_);
759 else 795 else
(...skipping 12 matching lines...) Expand all
772 DCHECK(stored_state_ == STORING); 808 DCHECK(stored_state_ == STORING);
773 if (success) { 809 if (success) {
774 stored_state_ = STORED; 810 stored_state_ = STORED;
775 MaybeCompleteUpdate(); // will definitely complete 811 MaybeCompleteUpdate(); // will definitely complete
776 } else { 812 } else {
777 // Restore inprogress_cache_ to get the proper events delivered 813 // Restore inprogress_cache_ to get the proper events delivered
778 // and the proper cleanup to occur. 814 // and the proper cleanup to occur.
779 if (newest_cache != group->newest_complete_cache()) 815 if (newest_cache != group->newest_complete_cache())
780 inprogress_cache_ = newest_cache; 816 inprogress_cache_ = newest_cache;
781 817
818 ResultType result = DB_ERROR;
782 std::string message("Failed to commit new cache to storage"); 819 std::string message("Failed to commit new cache to storage");
783 if (would_exceed_quota) 820 if (would_exceed_quota) {
784 message.append(", would exceed quota"); 821 message.append(", would exceed quota");
785 HandleCacheFailure(message); 822 result = QUOTA_ERROR;
823 }
824 HandleCacheFailure(message, result);
786 } 825 }
787 } 826 }
788 827
789 void AppCacheUpdateJob::NotifySingleHost(AppCacheHost* host, 828 void AppCacheUpdateJob::NotifySingleHost(AppCacheHost* host,
790 EventID event_id) { 829 EventID event_id) {
791 std::vector<int> ids(1, host->host_id()); 830 std::vector<int> ids(1, host->host_id());
792 host->frontend()->OnEventRaised(ids, event_id); 831 host->frontend()->OnEventRaised(ids, event_id);
793 } 832 }
794 833
795 void AppCacheUpdateJob::NotifyAllAssociatedHosts(EventID event_id) { 834 void AppCacheUpdateJob::NotifyAllAssociatedHosts(EventID event_id) {
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
860 DCHECK(update_type_ == UPGRADE_ATTEMPT); 899 DCHECK(update_type_ == UPGRADE_ATTEMPT);
861 AppCacheEntry* entry = NULL; 900 AppCacheEntry* entry = NULL;
862 if (group_->newest_complete_cache()) 901 if (group_->newest_complete_cache())
863 entry = group_->newest_complete_cache()->GetEntry(manifest_url_); 902 entry = group_->newest_complete_cache()->GetEntry(manifest_url_);
864 if (!entry) { 903 if (!entry) {
865 // TODO(michaeln): This is just a bandaid to avoid a crash. 904 // TODO(michaeln): This is just a bandaid to avoid a crash.
866 // http://code.google.com/p/chromium/issues/detail?id=95101 905 // http://code.google.com/p/chromium/issues/detail?id=95101
867 if (service_->storage() == storage_) { 906 if (service_->storage() == storage_) {
868 // Use a local variable because service_ is reset in HandleCacheFailure. 907 // Use a local variable because service_ is reset in HandleCacheFailure.
869 AppCacheService* service = service_; 908 AppCacheService* service = service_;
870 HandleCacheFailure("Manifest entry not found in existing cache"); 909 HandleCacheFailure("Manifest entry not found in existing cache",
910 DB_ERROR);
871 AppCacheHistograms::AddMissingManifestEntrySample(); 911 AppCacheHistograms::AddMissingManifestEntrySample();
872 service->DeleteAppCacheGroup(manifest_url_, net::CompletionCallback()); 912 service->DeleteAppCacheGroup(manifest_url_, net::CompletionCallback());
873 } 913 }
874 return; 914 return;
875 } 915 }
876 916
877 // Load manifest data from storage to compare against fetched manifest. 917 // Load manifest data from storage to compare against fetched manifest.
878 manifest_response_reader_.reset( 918 manifest_response_reader_.reset(
879 storage_->CreateResponseReader(manifest_url_, 919 storage_->CreateResponseReader(manifest_url_,
880 group_->group_id(), 920 group_->group_id(),
(...skipping 383 matching lines...) Expand 10 before | Expand all | Expand 10 after
1264 break; 1304 break;
1265 case REFETCH_MANIFEST: 1305 case REFETCH_MANIFEST:
1266 DCHECK(stored_state_ == STORED); 1306 DCHECK(stored_state_ == STORED);
1267 NotifyAllFinalProgress(); 1307 NotifyAllFinalProgress();
1268 if (update_type_ == CACHE_ATTEMPT) 1308 if (update_type_ == CACHE_ATTEMPT)
1269 NotifyAllAssociatedHosts(CACHED_EVENT); 1309 NotifyAllAssociatedHosts(CACHED_EVENT);
1270 else 1310 else
1271 NotifyAllAssociatedHosts(UPDATE_READY_EVENT); 1311 NotifyAllAssociatedHosts(UPDATE_READY_EVENT);
1272 DiscardDuplicateResponses(); 1312 DiscardDuplicateResponses();
1273 internal_state_ = COMPLETED; 1313 internal_state_ = COMPLETED;
1314 AppCacheHistograms::CountUpdateJobResult(UPDATE_OK);
1274 break; 1315 break;
1275 case CACHE_FAILURE: 1316 case CACHE_FAILURE:
1276 NOTREACHED(); // See HandleCacheFailure 1317 NOTREACHED(); // See HandleCacheFailure
1277 break; 1318 break;
1278 default: 1319 default:
1279 break; 1320 break;
1280 } 1321 }
1281 1322
1282 // Let the stack unwind before deletion to make it less risky as this 1323 // Let the stack unwind before deletion to make it less risky as this
1283 // method is called from multiple places in this file. 1324 // method is called from multiple places in this file.
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
1367 1408
1368 // Break the connection with the group so the group cannot call delete 1409 // Break the connection with the group so the group cannot call delete
1369 // on this object after we've posted a task to delete ourselves. 1410 // on this object after we've posted a task to delete ourselves.
1370 group_->SetUpdateStatus(AppCacheGroup::IDLE); 1411 group_->SetUpdateStatus(AppCacheGroup::IDLE);
1371 group_ = NULL; 1412 group_ = NULL;
1372 1413
1373 base::MessageLoop::current()->DeleteSoon(FROM_HERE, this); 1414 base::MessageLoop::current()->DeleteSoon(FROM_HERE, this);
1374 } 1415 }
1375 1416
1376 } // namespace appcache 1417 } // namespace appcache
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698