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

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());
428 DCHECK(result != UPDATE_OK);
403 internal_state_ = CACHE_FAILURE; 429 internal_state_ = CACHE_FAILURE;
404 CancelAllUrlFetches(); 430 CancelAllUrlFetches();
405 CancelAllMasterEntryFetches(error_message); 431 CancelAllMasterEntryFetches(error_message);
406 NotifyAllError(error_message); 432 NotifyAllError(error_message);
407 DiscardInprogressCache(); 433 DiscardInprogressCache();
408 internal_state_ = COMPLETED; 434 internal_state_ = COMPLETED;
435 AppCacheHistograms::CountUpdateJobResult(
436 result, manifest_url_.GetOrigin());
409 DeleteSoon(); // To unwind the stack prior to deletion. 437 DeleteSoon(); // To unwind the stack prior to deletion.
410 } 438 }
411 439
412 void AppCacheUpdateJob::FetchManifest(bool is_first_fetch) { 440 void AppCacheUpdateJob::FetchManifest(bool is_first_fetch) {
413 DCHECK(!manifest_fetcher_); 441 DCHECK(!manifest_fetcher_);
414 manifest_fetcher_ = new URLFetcher( 442 manifest_fetcher_ = new URLFetcher(
415 manifest_url_, 443 manifest_url_,
416 is_first_fetch ? URLFetcher::MANIFEST_FETCH : 444 is_first_fetch ? URLFetcher::MANIFEST_FETCH :
417 URLFetcher::MANIFEST_REFETCH, 445 URLFetcher::MANIFEST_REFETCH,
418 this); 446 this);
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
460 CheckIfManifestChanged(); // continues asynchronously 488 CheckIfManifestChanged(); // continues asynchronously
461 else 489 else
462 ContinueHandleManifestFetchCompleted(true); 490 ContinueHandleManifestFetchCompleted(true);
463 } else if (response_code == 304 && update_type_ == UPGRADE_ATTEMPT) { 491 } else if (response_code == 304 && update_type_ == UPGRADE_ATTEMPT) {
464 ContinueHandleManifestFetchCompleted(false); 492 ContinueHandleManifestFetchCompleted(false);
465 } else if ((response_code == 404 || response_code == 410) && 493 } else if ((response_code == 404 || response_code == 410) &&
466 update_type_ == UPGRADE_ATTEMPT) { 494 update_type_ == UPGRADE_ATTEMPT) {
467 storage_->MakeGroupObsolete(group_, this); // async 495 storage_->MakeGroupObsolete(group_, this); // async
468 } else { 496 } else {
469 const char* kFormatString = "Manifest fetch failed (%d) %s"; 497 const char* kFormatString = "Manifest fetch failed (%d) %s";
470 std::string message = base::StringPrintf(kFormatString, response_code, 498 std::string message = FormatUrlErrorMessage(
471 manifest_url_.spec().c_str()); 499 kFormatString, manifest_url_, fetcher->result(), response_code);
472 HandleCacheFailure(message); 500 HandleCacheFailure(message, fetcher->result());
473 } 501 }
474 } 502 }
475 503
476 void AppCacheUpdateJob::OnGroupMadeObsolete(AppCacheGroup* group, 504 void AppCacheUpdateJob::OnGroupMadeObsolete(AppCacheGroup* group,
477 bool success) { 505 bool success) {
478 DCHECK(master_entry_fetches_.empty()); 506 DCHECK(master_entry_fetches_.empty());
479 CancelAllMasterEntryFetches("The cache has been made obsolete, " 507 CancelAllMasterEntryFetches("The cache has been made obsolete, "
480 "the manifest file returned 404 or 410"); 508 "the manifest file returned 404 or 410");
481 if (success) { 509 if (success) {
482 DCHECK(group->is_obsolete()); 510 DCHECK(group->is_obsolete());
483 NotifyAllAssociatedHosts(OBSOLETE_EVENT); 511 NotifyAllAssociatedHosts(OBSOLETE_EVENT);
484 internal_state_ = COMPLETED; 512 internal_state_ = COMPLETED;
485 MaybeCompleteUpdate(); 513 MaybeCompleteUpdate();
486 } else { 514 } else {
487 // Treat failure to mark group obsolete as a cache failure. 515 // Treat failure to mark group obsolete as a cache failure.
488 HandleCacheFailure("Failed to mark the cache as obsolete"); 516 HandleCacheFailure("Failed to mark the cache as obsolete", DB_ERROR);
489 } 517 }
490 } 518 }
491 519
492 void AppCacheUpdateJob::ContinueHandleManifestFetchCompleted(bool changed) { 520 void AppCacheUpdateJob::ContinueHandleManifestFetchCompleted(bool changed) {
493 DCHECK(internal_state_ == FETCH_MANIFEST); 521 DCHECK(internal_state_ == FETCH_MANIFEST);
494 522
495 if (!changed) { 523 if (!changed) {
496 DCHECK(update_type_ == UPGRADE_ATTEMPT); 524 DCHECK(update_type_ == UPGRADE_ATTEMPT);
497 internal_state_ = NO_UPDATE; 525 internal_state_ = NO_UPDATE;
498 526
499 // Wait for pending master entries to download. 527 // Wait for pending master entries to download.
500 FetchMasterEntries(); 528 FetchMasterEntries();
501 MaybeCompleteUpdate(); // if not done, run async 6.9.4 step 7 substeps 529 MaybeCompleteUpdate(); // if not done, run async 6.9.4 step 7 substeps
502 return; 530 return;
503 } 531 }
504 532
505 Manifest manifest; 533 Manifest manifest;
506 if (!ParseManifest(manifest_url_, manifest_data_.data(), 534 if (!ParseManifest(manifest_url_, manifest_data_.data(),
507 manifest_data_.length(), manifest)) { 535 manifest_data_.length(), manifest)) {
508 const char* kFormatString = "Failed to parse manifest %s"; 536 const char* kFormatString = "Failed to parse manifest %s";
509 const std::string message = base::StringPrintf(kFormatString, 537 const std::string message = base::StringPrintf(kFormatString,
510 manifest_url_.spec().c_str()); 538 manifest_url_.spec().c_str());
511 HandleCacheFailure(message); 539 HandleCacheFailure(message, MANIFEST_ERROR);
512 VLOG(1) << message; 540 VLOG(1) << message;
513 return; 541 return;
514 } 542 }
515 543
516 // Proceed with update process. Section 6.9.4 steps 8-20. 544 // Proceed with update process. Section 6.9.4 steps 8-20.
517 internal_state_ = DOWNLOADING; 545 internal_state_ = DOWNLOADING;
518 inprogress_cache_ = new AppCache(storage_, storage_->NewCacheId()); 546 inprogress_cache_ = new AppCache(storage_, storage_->NewCacheId());
519 BuildUrlFileList(manifest); 547 BuildUrlFileList(manifest);
520 inprogress_cache_->InitializeWithManifest(&manifest); 548 inprogress_cache_->InitializeWithManifest(&manifest);
521 549
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
573 << " error: " << request->status().error() 601 << " error: " << request->status().error()
574 << " response code: " << response_code; 602 << " response code: " << response_code;
575 if (entry.IsExplicit() || entry.IsFallback() || entry.IsIntercept()) { 603 if (entry.IsExplicit() || entry.IsFallback() || entry.IsIntercept()) {
576 if (response_code == 304 && fetcher->existing_entry().has_response_id()) { 604 if (response_code == 304 && fetcher->existing_entry().has_response_id()) {
577 // Keep the existing response. 605 // Keep the existing response.
578 entry.set_response_id(fetcher->existing_entry().response_id()); 606 entry.set_response_id(fetcher->existing_entry().response_id());
579 entry.set_response_size(fetcher->existing_entry().response_size()); 607 entry.set_response_size(fetcher->existing_entry().response_size());
580 inprogress_cache_->AddOrModifyEntry(url, entry); 608 inprogress_cache_->AddOrModifyEntry(url, entry);
581 } else { 609 } else {
582 const char* kFormatString = "Resource fetch failed (%d) %s"; 610 const char* kFormatString = "Resource fetch failed (%d) %s";
583 const std::string message = base::StringPrintf(kFormatString, 611 std::string message = FormatUrlErrorMessage(
584 response_code, url.spec().c_str()); 612 kFormatString, url, fetcher->result(), response_code);
585 HandleCacheFailure(message); 613 HandleCacheFailure(message, fetcher->result());
586 return; 614 return;
587 } 615 }
588 } else if (response_code == 404 || response_code == 410) { 616 } else if (response_code == 404 || response_code == 410) {
589 // Entry is skipped. They are dropped from the cache. 617 // Entry is skipped. They are dropped from the cache.
590 } else if (update_type_ == UPGRADE_ATTEMPT && 618 } else if (update_type_ == UPGRADE_ATTEMPT &&
591 fetcher->existing_entry().has_response_id()) { 619 fetcher->existing_entry().has_response_id()) {
592 // Keep the existing response. 620 // Keep the existing response.
593 // TODO(michaeln): Not sure this is a good idea. This is spec compliant 621 // 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 622 // 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. 623 // 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); 685 host_notifier.AddHost(host);
658 686
659 // In downloading case, disassociate host from inprogress cache. 687 // In downloading case, disassociate host from inprogress cache.
660 if (inprogress_cache_.get()) 688 if (inprogress_cache_.get())
661 host->AssociateNoCache(GURL()); 689 host->AssociateNoCache(GURL());
662 690
663 host->RemoveObserver(this); 691 host->RemoveObserver(this);
664 } 692 }
665 hosts.clear(); 693 hosts.clear();
666 694
667 const char* kFormatString = "Master entry fetch failed (%d) %s"; 695 const char* kFormatString = "Manifest fetch failed (%d) %s";
668 const std::string message = base::StringPrintf(kFormatString, 696 std::string message = FormatUrlErrorMessage(
669 response_code, request->url().spec().c_str()); 697 kFormatString, request->url(), fetcher->result(), response_code);
670 host_notifier.SendErrorNotifications(message); 698 host_notifier.SendErrorNotifications(message);
671 699
672 // In downloading case, update result is different if all master entries 700 // In downloading case, update result is different if all master entries
673 // failed vs. only some failing. 701 // failed vs. only some failing.
674 if (inprogress_cache_.get()) { 702 if (inprogress_cache_.get()) {
675 // Only count successful downloads to know if all master entries failed. 703 // Only count successful downloads to know if all master entries failed.
676 pending_master_entries_.erase(found); 704 pending_master_entries_.erase(found);
677 --master_entries_completed_; 705 --master_entries_completed_;
678 706
679 // Section 6.9.4, step 22.3. 707 // Section 6.9.4, step 22.3.
680 if (update_type_ == CACHE_ATTEMPT && pending_master_entries_.empty()) { 708 if (update_type_ == CACHE_ATTEMPT && pending_master_entries_.empty()) {
681 HandleCacheFailure(message); 709 HandleCacheFailure(message, fetcher->result());
682 return; 710 return;
683 } 711 }
684 } 712 }
685 } 713 }
686 714
687 DCHECK(internal_state_ != CACHE_FAILURE); 715 DCHECK(internal_state_ != CACHE_FAILURE);
688 FetchMasterEntries(); 716 FetchMasterEntries();
689 MaybeCompleteUpdate(); 717 MaybeCompleteUpdate();
690 } 718 }
691 719
(...skipping 20 matching lines...) Expand all
712 manifest_response_writer_->WriteInfo( 740 manifest_response_writer_->WriteInfo(
713 io_buffer.get(), 741 io_buffer.get(),
714 base::Bind(&AppCacheUpdateJob::OnManifestInfoWriteComplete, 742 base::Bind(&AppCacheUpdateJob::OnManifestInfoWriteComplete,
715 base::Unretained(this))); 743 base::Unretained(this)));
716 } 744 }
717 } else { 745 } else {
718 VLOG(1) << "Request status: " << request->status().status() 746 VLOG(1) << "Request status: " << request->status().status()
719 << " error: " << request->status().error() 747 << " error: " << request->status().error()
720 << " response code: " << response_code; 748 << " response code: " << response_code;
721 ScheduleUpdateRetry(kRerunDelayMs); 749 ScheduleUpdateRetry(kRerunDelayMs);
722 HandleCacheFailure("Manifest changed during update, scheduling retry"); 750 if (response_code == 200) {
751 HandleCacheFailure("Manifest changed during update", MANIFEST_ERROR);
752 } else {
753 const char* kFormatString = "Manifest re-fetch failed (%d) %s";
754 std::string message = FormatUrlErrorMessage(
755 kFormatString, manifest_url_, fetcher->result(), response_code);
756 HandleCacheFailure(message, fetcher->result());
757 }
723 } 758 }
724 } 759 }
725 760
726 void AppCacheUpdateJob::OnManifestInfoWriteComplete(int result) { 761 void AppCacheUpdateJob::OnManifestInfoWriteComplete(int result) {
727 if (result > 0) { 762 if (result > 0) {
728 scoped_refptr<net::StringIOBuffer> io_buffer( 763 scoped_refptr<net::StringIOBuffer> io_buffer(
729 new net::StringIOBuffer(manifest_data_)); 764 new net::StringIOBuffer(manifest_data_));
730 manifest_response_writer_->WriteData( 765 manifest_response_writer_->WriteData(
731 io_buffer.get(), 766 io_buffer.get(),
732 manifest_data_.length(), 767 manifest_data_.length(),
733 base::Bind(&AppCacheUpdateJob::OnManifestDataWriteComplete, 768 base::Bind(&AppCacheUpdateJob::OnManifestDataWriteComplete,
734 base::Unretained(this))); 769 base::Unretained(this)));
735 } else { 770 } else {
736 HandleCacheFailure("Failed to write the manifest headers to storage"); 771 HandleCacheFailure("Failed to write the manifest headers to storage",
772 DISKCACHE_ERROR);
737 } 773 }
738 } 774 }
739 775
740 void AppCacheUpdateJob::OnManifestDataWriteComplete(int result) { 776 void AppCacheUpdateJob::OnManifestDataWriteComplete(int result) {
741 if (result > 0) { 777 if (result > 0) {
742 AppCacheEntry entry(AppCacheEntry::MANIFEST, 778 AppCacheEntry entry(AppCacheEntry::MANIFEST,
743 manifest_response_writer_->response_id(), 779 manifest_response_writer_->response_id(),
744 manifest_response_writer_->amount_written()); 780 manifest_response_writer_->amount_written());
745 if (!inprogress_cache_->AddOrModifyEntry(manifest_url_, entry)) 781 if (!inprogress_cache_->AddOrModifyEntry(manifest_url_, entry))
746 duplicate_response_ids_.push_back(entry.response_id()); 782 duplicate_response_ids_.push_back(entry.response_id());
747 StoreGroupAndCache(); 783 StoreGroupAndCache();
748 } else { 784 } else {
749 HandleCacheFailure("Failed to write the manifest data to storage"); 785 HandleCacheFailure("Failed to write the manifest data to storage",
786 DISKCACHE_ERROR);
750 } 787 }
751 } 788 }
752 789
753 void AppCacheUpdateJob::StoreGroupAndCache() { 790 void AppCacheUpdateJob::StoreGroupAndCache() {
754 DCHECK(stored_state_ == UNSTORED); 791 DCHECK(stored_state_ == UNSTORED);
755 stored_state_ = STORING; 792 stored_state_ = STORING;
756 scoped_refptr<AppCache> newest_cache; 793 scoped_refptr<AppCache> newest_cache;
757 if (inprogress_cache_.get()) 794 if (inprogress_cache_.get())
758 newest_cache.swap(inprogress_cache_); 795 newest_cache.swap(inprogress_cache_);
759 else 796 else
(...skipping 12 matching lines...) Expand all
772 DCHECK(stored_state_ == STORING); 809 DCHECK(stored_state_ == STORING);
773 if (success) { 810 if (success) {
774 stored_state_ = STORED; 811 stored_state_ = STORED;
775 MaybeCompleteUpdate(); // will definitely complete 812 MaybeCompleteUpdate(); // will definitely complete
776 } else { 813 } else {
777 // Restore inprogress_cache_ to get the proper events delivered 814 // Restore inprogress_cache_ to get the proper events delivered
778 // and the proper cleanup to occur. 815 // and the proper cleanup to occur.
779 if (newest_cache != group->newest_complete_cache()) 816 if (newest_cache != group->newest_complete_cache())
780 inprogress_cache_ = newest_cache; 817 inprogress_cache_ = newest_cache;
781 818
819 ResultType result = DB_ERROR;
782 std::string message("Failed to commit new cache to storage"); 820 std::string message("Failed to commit new cache to storage");
783 if (would_exceed_quota) 821 if (would_exceed_quota) {
784 message.append(", would exceed quota"); 822 message.append(", would exceed quota");
785 HandleCacheFailure(message); 823 result = QUOTA_ERROR;
824 }
825 HandleCacheFailure(message, result);
786 } 826 }
787 } 827 }
788 828
789 void AppCacheUpdateJob::NotifySingleHost(AppCacheHost* host, 829 void AppCacheUpdateJob::NotifySingleHost(AppCacheHost* host,
790 EventID event_id) { 830 EventID event_id) {
791 std::vector<int> ids(1, host->host_id()); 831 std::vector<int> ids(1, host->host_id());
792 host->frontend()->OnEventRaised(ids, event_id); 832 host->frontend()->OnEventRaised(ids, event_id);
793 } 833 }
794 834
795 void AppCacheUpdateJob::NotifyAllAssociatedHosts(EventID event_id) { 835 void AppCacheUpdateJob::NotifyAllAssociatedHosts(EventID event_id) {
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
860 DCHECK(update_type_ == UPGRADE_ATTEMPT); 900 DCHECK(update_type_ == UPGRADE_ATTEMPT);
861 AppCacheEntry* entry = NULL; 901 AppCacheEntry* entry = NULL;
862 if (group_->newest_complete_cache()) 902 if (group_->newest_complete_cache())
863 entry = group_->newest_complete_cache()->GetEntry(manifest_url_); 903 entry = group_->newest_complete_cache()->GetEntry(manifest_url_);
864 if (!entry) { 904 if (!entry) {
865 // TODO(michaeln): This is just a bandaid to avoid a crash. 905 // TODO(michaeln): This is just a bandaid to avoid a crash.
866 // http://code.google.com/p/chromium/issues/detail?id=95101 906 // http://code.google.com/p/chromium/issues/detail?id=95101
867 if (service_->storage() == storage_) { 907 if (service_->storage() == storage_) {
868 // Use a local variable because service_ is reset in HandleCacheFailure. 908 // Use a local variable because service_ is reset in HandleCacheFailure.
869 AppCacheService* service = service_; 909 AppCacheService* service = service_;
870 HandleCacheFailure("Manifest entry not found in existing cache"); 910 HandleCacheFailure("Manifest entry not found in existing cache",
911 DB_ERROR);
871 AppCacheHistograms::AddMissingManifestEntrySample(); 912 AppCacheHistograms::AddMissingManifestEntrySample();
872 service->DeleteAppCacheGroup(manifest_url_, net::CompletionCallback()); 913 service->DeleteAppCacheGroup(manifest_url_, net::CompletionCallback());
873 } 914 }
874 return; 915 return;
875 } 916 }
876 917
877 // Load manifest data from storage to compare against fetched manifest. 918 // Load manifest data from storage to compare against fetched manifest.
878 manifest_response_reader_.reset( 919 manifest_response_reader_.reset(
879 storage_->CreateResponseReader(manifest_url_, 920 storage_->CreateResponseReader(manifest_url_,
880 group_->group_id(), 921 group_->group_id(),
(...skipping 383 matching lines...) Expand 10 before | Expand all | Expand 10 after
1264 break; 1305 break;
1265 case REFETCH_MANIFEST: 1306 case REFETCH_MANIFEST:
1266 DCHECK(stored_state_ == STORED); 1307 DCHECK(stored_state_ == STORED);
1267 NotifyAllFinalProgress(); 1308 NotifyAllFinalProgress();
1268 if (update_type_ == CACHE_ATTEMPT) 1309 if (update_type_ == CACHE_ATTEMPT)
1269 NotifyAllAssociatedHosts(CACHED_EVENT); 1310 NotifyAllAssociatedHosts(CACHED_EVENT);
1270 else 1311 else
1271 NotifyAllAssociatedHosts(UPDATE_READY_EVENT); 1312 NotifyAllAssociatedHosts(UPDATE_READY_EVENT);
1272 DiscardDuplicateResponses(); 1313 DiscardDuplicateResponses();
1273 internal_state_ = COMPLETED; 1314 internal_state_ = COMPLETED;
1315 AppCacheHistograms::CountUpdateJobResult(
1316 UPDATE_OK, manifest_url_.GetOrigin());
1274 break; 1317 break;
1275 case CACHE_FAILURE: 1318 case CACHE_FAILURE:
1276 NOTREACHED(); // See HandleCacheFailure 1319 NOTREACHED(); // See HandleCacheFailure
1277 break; 1320 break;
1278 default: 1321 default:
1279 break; 1322 break;
1280 } 1323 }
1281 1324
1282 // Let the stack unwind before deletion to make it less risky as this 1325 // Let the stack unwind before deletion to make it less risky as this
1283 // method is called from multiple places in this file. 1326 // method is called from multiple places in this file.
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
1367 1410
1368 // Break the connection with the group so the group cannot call delete 1411 // 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. 1412 // on this object after we've posted a task to delete ourselves.
1370 group_->SetUpdateStatus(AppCacheGroup::IDLE); 1413 group_->SetUpdateStatus(AppCacheGroup::IDLE);
1371 group_ = NULL; 1414 group_ = NULL;
1372 1415
1373 base::MessageLoop::current()->DeleteSoon(FROM_HERE, this); 1416 base::MessageLoop::current()->DeleteSoon(FROM_HERE, this);
1374 } 1417 }
1375 1418
1376 } // namespace appcache 1419 } // namespace appcache
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698