Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 124 net::LOAD_DISABLE_INTERCEPT); | 124 net::LOAD_DISABLE_INTERCEPT); |
| 125 if (existing_response_headers_.get()) | 125 if (existing_response_headers_.get()) |
| 126 AddConditionalHeaders(existing_response_headers_.get()); | 126 AddConditionalHeaders(existing_response_headers_.get()); |
| 127 request_->Start(); | 127 request_->Start(); |
| 128 } | 128 } |
| 129 | 129 |
| 130 void AppCacheUpdateJob::URLFetcher::OnReceivedRedirect( | 130 void AppCacheUpdateJob::URLFetcher::OnReceivedRedirect( |
| 131 net::URLRequest* request, const GURL& new_url, bool* defer_redirect) { | 131 net::URLRequest* request, const GURL& new_url, bool* defer_redirect) { |
| 132 DCHECK(request_ == request); | 132 DCHECK(request_ == request); |
| 133 // Redirect is not allowed by the update process. | 133 // Redirect is not allowed by the update process. |
| 134 job_->MadeProgress(); | |
|
jsbell
2014/03/21 16:41:02
So here, a redirect - which is an error - calls Ma
michaeln
2014/03/24 18:12:04
Yes, MadeProgress() just means it wasn't dead in a
jsbell
2014/03/24 22:21:23
Yep, thanks.
| |
| 134 request->Cancel(); | 135 request->Cancel(); |
| 135 result_ = REDIRECT_ERROR; | 136 result_ = REDIRECT_ERROR; |
| 136 OnResponseCompleted(); | 137 OnResponseCompleted(); |
| 137 } | 138 } |
| 138 | 139 |
| 139 void AppCacheUpdateJob::URLFetcher::OnResponseStarted( | 140 void AppCacheUpdateJob::URLFetcher::OnResponseStarted( |
| 140 net::URLRequest *request) { | 141 net::URLRequest *request) { |
| 141 DCHECK(request == request_); | 142 DCHECK(request == request_); |
| 142 int response_code = -1; | 143 int response_code = -1; |
| 143 if (request->status().is_success()) | 144 if (request->status().is_success()) { |
| 144 response_code = request->GetResponseCode(); | 145 response_code = request->GetResponseCode(); |
| 146 job_->MadeProgress(); | |
|
jsbell
2014/03/21 16:41:02
But here and below, MakeProgress is only called if
michaeln
2014/03/24 18:12:04
see previous comment
| |
| 147 } | |
| 145 if ((response_code / 100) == 2) { | 148 if ((response_code / 100) == 2) { |
| 146 | 149 |
| 147 // See http://code.google.com/p/chromium/issues/detail?id=69594 | 150 // See http://code.google.com/p/chromium/issues/detail?id=69594 |
| 148 // We willfully violate the HTML5 spec at this point in order | 151 // We willfully violate the HTML5 spec at this point in order |
| 149 // to support the appcaching of cross-origin HTTPS resources. | 152 // to support the appcaching of cross-origin HTTPS resources. |
| 150 // We've opted for a milder constraint and allow caching unless | 153 // We've opted for a milder constraint and allow caching unless |
| 151 // 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 |
| 152 // requested on the whatwg list. | 155 // requested on the whatwg list. |
| 153 // TODO(michaeln): Consider doing this for cross-origin HTTP resources too. | 156 // TODO(michaeln): Consider doing this for cross-origin HTTP resources too. |
| 154 if (url_.SchemeIsSecure() && | 157 if (url_.SchemeIsSecure() && |
| (...skipping 27 matching lines...) Expand all Loading... | |
| 182 result_ = NETWORK_ERROR; | 185 result_ = NETWORK_ERROR; |
| 183 OnResponseCompleted(); | 186 OnResponseCompleted(); |
| 184 } | 187 } |
| 185 } | 188 } |
| 186 | 189 |
| 187 void AppCacheUpdateJob::URLFetcher::OnReadCompleted( | 190 void AppCacheUpdateJob::URLFetcher::OnReadCompleted( |
| 188 net::URLRequest* request, int bytes_read) { | 191 net::URLRequest* request, int bytes_read) { |
| 189 DCHECK(request_ == request); | 192 DCHECK(request_ == request); |
| 190 bool data_consumed = true; | 193 bool data_consumed = true; |
| 191 if (request->status().is_success() && bytes_read > 0) { | 194 if (request->status().is_success() && bytes_read > 0) { |
| 195 job_->MadeProgress(); | |
| 192 data_consumed = ConsumeResponseData(bytes_read); | 196 data_consumed = ConsumeResponseData(bytes_read); |
| 193 if (data_consumed) { | 197 if (data_consumed) { |
| 194 bytes_read = 0; | 198 bytes_read = 0; |
| 195 while (request->Read(buffer_.get(), kBufferSize, &bytes_read)) { | 199 while (request->Read(buffer_.get(), kBufferSize, &bytes_read)) { |
| 196 if (bytes_read > 0) { | 200 if (bytes_read > 0) { |
| 197 data_consumed = ConsumeResponseData(bytes_read); | 201 data_consumed = ConsumeResponseData(bytes_read); |
| 198 if (!data_consumed) | 202 if (!data_consumed) |
| 199 break; // wait for async data processing, then read more | 203 break; // wait for async data processing, then read more |
| 200 } else { | 204 } else { |
| 201 break; | 205 break; |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 272 bytes_read, | 276 bytes_read, |
| 273 base::Bind(&URLFetcher::OnWriteComplete, base::Unretained(this))); | 277 base::Bind(&URLFetcher::OnWriteComplete, base::Unretained(this))); |
| 274 return false; // wait for async write completion to continue reading | 278 return false; // wait for async write completion to continue reading |
| 275 default: | 279 default: |
| 276 NOTREACHED(); | 280 NOTREACHED(); |
| 277 } | 281 } |
| 278 return true; | 282 return true; |
| 279 } | 283 } |
| 280 | 284 |
| 281 void AppCacheUpdateJob::URLFetcher::OnResponseCompleted() { | 285 void AppCacheUpdateJob::URLFetcher::OnResponseCompleted() { |
| 286 if (request_->status().is_success()) | |
| 287 job_->MadeProgress(); | |
| 288 | |
| 282 // Retry for 503s where retry-after is 0. | 289 // Retry for 503s where retry-after is 0. |
| 283 if (request_->status().is_success() && | 290 if (request_->status().is_success() && |
| 284 request_->GetResponseCode() == 503 && | 291 request_->GetResponseCode() == 503 && |
| 285 MaybeRetryRequest()) { | 292 MaybeRetryRequest()) { |
| 286 return; | 293 return; |
| 287 } | 294 } |
| 288 | 295 |
| 289 switch (fetch_type_) { | 296 switch (fetch_type_) { |
| 290 case MANIFEST_FETCH: | 297 case MANIFEST_FETCH: |
| 291 job_->HandleManifestFetchCompleted(this); | 298 job_->HandleManifestFetchCompleted(this); |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 387 // Add to fetch list or an existing entry if already fetched. | 394 // Add to fetch list or an existing entry if already fetched. |
| 388 if (!new_master_resource.is_empty()) { | 395 if (!new_master_resource.is_empty()) { |
| 389 AddMasterEntryToFetchList(host, new_master_resource, | 396 AddMasterEntryToFetchList(host, new_master_resource, |
| 390 is_new_pending_master_entry); | 397 is_new_pending_master_entry); |
| 391 } | 398 } |
| 392 } | 399 } |
| 393 return; | 400 return; |
| 394 } | 401 } |
| 395 | 402 |
| 396 // Begin update process for the group. | 403 // Begin update process for the group. |
| 404 MadeProgress(); | |
| 397 group_->SetUpdateStatus(AppCacheGroup::CHECKING); | 405 group_->SetUpdateStatus(AppCacheGroup::CHECKING); |
| 398 if (group_->HasCache()) { | 406 if (group_->HasCache()) { |
| 399 update_type_ = UPGRADE_ATTEMPT; | 407 update_type_ = UPGRADE_ATTEMPT; |
| 400 NotifyAllAssociatedHosts(CHECKING_EVENT); | 408 NotifyAllAssociatedHosts(CHECKING_EVENT); |
| 401 } else { | 409 } else { |
| 402 update_type_ = CACHE_ATTEMPT; | 410 update_type_ = CACHE_ATTEMPT; |
| 403 DCHECK(host); | 411 DCHECK(host); |
| 404 NotifySingleHost(host, CHECKING_EVENT); | 412 NotifySingleHost(host, CHECKING_EVENT); |
| 405 } | 413 } |
| 406 | 414 |
| 407 if (!new_master_resource.is_empty()) { | 415 if (!new_master_resource.is_empty()) { |
| 408 AddMasterEntryToFetchList(host, new_master_resource, | 416 AddMasterEntryToFetchList(host, new_master_resource, |
| 409 is_new_pending_master_entry); | 417 is_new_pending_master_entry); |
| 410 } | 418 } |
| 411 | 419 |
| 412 FetchManifest(true); | 420 FetchManifest(true); |
| 413 } | 421 } |
| 414 | 422 |
| 415 AppCacheResponseWriter* AppCacheUpdateJob::CreateResponseWriter() { | 423 AppCacheResponseWriter* AppCacheUpdateJob::CreateResponseWriter() { |
| 416 AppCacheResponseWriter* writer = | 424 AppCacheResponseWriter* writer = |
| 417 storage_->CreateResponseWriter(manifest_url_, | 425 storage_->CreateResponseWriter(manifest_url_, |
| 418 group_->group_id()); | 426 group_->group_id()); |
| 419 stored_response_ids_.push_back(writer->response_id()); | 427 stored_response_ids_.push_back(writer->response_id()); |
| 420 return writer; | 428 return writer; |
| 421 } | 429 } |
| 422 | 430 |
| 423 void AppCacheUpdateJob::HandleCacheFailure( | 431 void AppCacheUpdateJob::HandleCacheFailure( |
| 424 const std::string& error_message, | 432 const std::string& error_message, |
| 425 ResultType result) { | 433 ResultType result, |
| 434 const GURL& failed_resource_url) { | |
| 426 // 6.9.4 cache failure steps 2-8. | 435 // 6.9.4 cache failure steps 2-8. |
| 427 DCHECK(internal_state_ != CACHE_FAILURE); | 436 DCHECK(internal_state_ != CACHE_FAILURE); |
| 428 DCHECK(!error_message.empty()); | 437 DCHECK(!error_message.empty()); |
| 429 DCHECK(result != UPDATE_OK); | 438 DCHECK(result != UPDATE_OK); |
| 430 internal_state_ = CACHE_FAILURE; | 439 internal_state_ = CACHE_FAILURE; |
| 440 LogHistogramStats(result, failed_resource_url); | |
| 431 CancelAllUrlFetches(); | 441 CancelAllUrlFetches(); |
| 432 CancelAllMasterEntryFetches(error_message); | 442 CancelAllMasterEntryFetches(error_message); |
| 433 NotifyAllError(error_message); | 443 NotifyAllError(error_message); |
| 434 DiscardInprogressCache(); | 444 DiscardInprogressCache(); |
| 435 internal_state_ = COMPLETED; | 445 internal_state_ = COMPLETED; |
| 436 AppCacheHistograms::CountUpdateJobResult( | |
| 437 result, manifest_url_.GetOrigin()); | |
| 438 DeleteSoon(); // To unwind the stack prior to deletion. | 446 DeleteSoon(); // To unwind the stack prior to deletion. |
| 439 } | 447 } |
| 440 | 448 |
| 441 void AppCacheUpdateJob::FetchManifest(bool is_first_fetch) { | 449 void AppCacheUpdateJob::FetchManifest(bool is_first_fetch) { |
| 442 DCHECK(!manifest_fetcher_); | 450 DCHECK(!manifest_fetcher_); |
| 443 manifest_fetcher_ = new URLFetcher( | 451 manifest_fetcher_ = new URLFetcher( |
| 444 manifest_url_, | 452 manifest_url_, |
| 445 is_first_fetch ? URLFetcher::MANIFEST_FETCH : | 453 is_first_fetch ? URLFetcher::MANIFEST_FETCH : |
| 446 URLFetcher::MANIFEST_REFETCH, | 454 URLFetcher::MANIFEST_REFETCH, |
| 447 this); | 455 this); |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 471 URLFetcher* fetcher) { | 479 URLFetcher* fetcher) { |
| 472 DCHECK_EQ(internal_state_, FETCH_MANIFEST); | 480 DCHECK_EQ(internal_state_, FETCH_MANIFEST); |
| 473 DCHECK_EQ(manifest_fetcher_, fetcher); | 481 DCHECK_EQ(manifest_fetcher_, fetcher); |
| 474 manifest_fetcher_ = NULL; | 482 manifest_fetcher_ = NULL; |
| 475 | 483 |
| 476 net::URLRequest* request = fetcher->request(); | 484 net::URLRequest* request = fetcher->request(); |
| 477 int response_code = -1; | 485 int response_code = -1; |
| 478 bool is_valid_response_code = false; | 486 bool is_valid_response_code = false; |
| 479 if (request->status().is_success()) { | 487 if (request->status().is_success()) { |
| 480 response_code = request->GetResponseCode(); | 488 response_code = request->GetResponseCode(); |
| 481 is_valid_response_code = (response_code / 100 == 2); | 489 is_valid_response_code = (response_code / 100 == 2);; |
|
jsbell
2014/03/21 16:41:02
Extra ; - was this going to MakeProgress too?
michaeln
2014/03/24 18:12:04
Done. idk, maybe i had it that way before the fetc
| |
| 482 } | 490 } |
| 483 | 491 |
| 484 if (is_valid_response_code) { | 492 if (is_valid_response_code) { |
| 485 manifest_data_ = fetcher->manifest_data(); | 493 manifest_data_ = fetcher->manifest_data(); |
| 486 manifest_response_info_.reset( | 494 manifest_response_info_.reset( |
| 487 new net::HttpResponseInfo(request->response_info())); | 495 new net::HttpResponseInfo(request->response_info())); |
| 488 if (update_type_ == UPGRADE_ATTEMPT) | 496 if (update_type_ == UPGRADE_ATTEMPT) |
| 489 CheckIfManifestChanged(); // continues asynchronously | 497 CheckIfManifestChanged(); // continues asynchronously |
| 490 else | 498 else |
| 491 ContinueHandleManifestFetchCompleted(true); | 499 ContinueHandleManifestFetchCompleted(true); |
| 492 } else if (response_code == 304 && update_type_ == UPGRADE_ATTEMPT) { | 500 } else if (response_code == 304 && update_type_ == UPGRADE_ATTEMPT) { |
| 493 ContinueHandleManifestFetchCompleted(false); | 501 ContinueHandleManifestFetchCompleted(false); |
| 494 } else if ((response_code == 404 || response_code == 410) && | 502 } else if ((response_code == 404 || response_code == 410) && |
| 495 update_type_ == UPGRADE_ATTEMPT) { | 503 update_type_ == UPGRADE_ATTEMPT) { |
| 496 storage_->MakeGroupObsolete(group_, this); // async | 504 storage_->MakeGroupObsolete(group_, this); // async |
| 497 } else { | 505 } else { |
| 498 const char* kFormatString = "Manifest fetch failed (%d) %s"; | 506 const char* kFormatString = "Manifest fetch failed (%d) %s"; |
| 499 std::string message = FormatUrlErrorMessage( | 507 std::string message = FormatUrlErrorMessage( |
| 500 kFormatString, manifest_url_, fetcher->result(), response_code); | 508 kFormatString, manifest_url_, fetcher->result(), response_code); |
| 501 HandleCacheFailure(message, fetcher->result()); | 509 HandleCacheFailure(message, fetcher->result(), GURL()); |
| 502 } | 510 } |
| 503 } | 511 } |
| 504 | 512 |
| 505 void AppCacheUpdateJob::OnGroupMadeObsolete(AppCacheGroup* group, | 513 void AppCacheUpdateJob::OnGroupMadeObsolete(AppCacheGroup* group, |
| 506 bool success) { | 514 bool success) { |
| 507 DCHECK(master_entry_fetches_.empty()); | 515 DCHECK(master_entry_fetches_.empty()); |
| 508 CancelAllMasterEntryFetches("The cache has been made obsolete, " | 516 CancelAllMasterEntryFetches("The cache has been made obsolete, " |
| 509 "the manifest file returned 404 or 410"); | 517 "the manifest file returned 404 or 410"); |
| 510 if (success) { | 518 if (success) { |
| 511 DCHECK(group->is_obsolete()); | 519 DCHECK(group->is_obsolete()); |
| 512 NotifyAllAssociatedHosts(OBSOLETE_EVENT); | 520 NotifyAllAssociatedHosts(OBSOLETE_EVENT); |
| 513 internal_state_ = COMPLETED; | 521 internal_state_ = COMPLETED; |
| 514 MaybeCompleteUpdate(); | 522 MaybeCompleteUpdate(); |
| 515 } else { | 523 } else { |
| 516 // Treat failure to mark group obsolete as a cache failure. | 524 // Treat failure to mark group obsolete as a cache failure. |
| 517 HandleCacheFailure("Failed to mark the cache as obsolete", DB_ERROR); | 525 HandleCacheFailure("Failed to mark the cache as obsolete", |
| 526 DB_ERROR, GURL()); | |
| 518 } | 527 } |
| 519 } | 528 } |
| 520 | 529 |
| 521 void AppCacheUpdateJob::ContinueHandleManifestFetchCompleted(bool changed) { | 530 void AppCacheUpdateJob::ContinueHandleManifestFetchCompleted(bool changed) { |
| 522 DCHECK(internal_state_ == FETCH_MANIFEST); | 531 DCHECK(internal_state_ == FETCH_MANIFEST); |
| 523 | 532 |
| 524 if (!changed) { | 533 if (!changed) { |
| 525 DCHECK(update_type_ == UPGRADE_ATTEMPT); | 534 DCHECK(update_type_ == UPGRADE_ATTEMPT); |
| 526 internal_state_ = NO_UPDATE; | 535 internal_state_ = NO_UPDATE; |
| 527 | 536 |
| 528 // Wait for pending master entries to download. | 537 // Wait for pending master entries to download. |
| 529 FetchMasterEntries(); | 538 FetchMasterEntries(); |
| 530 MaybeCompleteUpdate(); // if not done, run async 6.9.4 step 7 substeps | 539 MaybeCompleteUpdate(); // if not done, run async 6.9.4 step 7 substeps |
| 531 return; | 540 return; |
| 532 } | 541 } |
| 533 | 542 |
| 534 Manifest manifest; | 543 Manifest manifest; |
| 535 if (!ParseManifest(manifest_url_, manifest_data_.data(), | 544 if (!ParseManifest(manifest_url_, manifest_data_.data(), |
| 536 manifest_data_.length(), manifest)) { | 545 manifest_data_.length(), manifest)) { |
| 537 const char* kFormatString = "Failed to parse manifest %s"; | 546 const char* kFormatString = "Failed to parse manifest %s"; |
| 538 const std::string message = base::StringPrintf(kFormatString, | 547 const std::string message = base::StringPrintf(kFormatString, |
| 539 manifest_url_.spec().c_str()); | 548 manifest_url_.spec().c_str()); |
| 540 HandleCacheFailure(message, MANIFEST_ERROR); | 549 HandleCacheFailure(message, MANIFEST_ERROR, GURL()); |
| 541 VLOG(1) << message; | 550 VLOG(1) << message; |
| 542 return; | 551 return; |
| 543 } | 552 } |
| 544 | 553 |
| 545 // Proceed with update process. Section 6.9.4 steps 8-20. | 554 // Proceed with update process. Section 6.9.4 steps 8-20. |
| 546 internal_state_ = DOWNLOADING; | 555 internal_state_ = DOWNLOADING; |
| 547 inprogress_cache_ = new AppCache(storage_, storage_->NewCacheId()); | 556 inprogress_cache_ = new AppCache(storage_, storage_->NewCacheId()); |
| 548 BuildUrlFileList(manifest); | 557 BuildUrlFileList(manifest); |
| 549 inprogress_cache_->InitializeWithManifest(&manifest); | 558 inprogress_cache_->InitializeWithManifest(&manifest); |
| 550 | 559 |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 604 if (entry.IsExplicit() || entry.IsFallback() || entry.IsIntercept()) { | 613 if (entry.IsExplicit() || entry.IsFallback() || entry.IsIntercept()) { |
| 605 if (response_code == 304 && fetcher->existing_entry().has_response_id()) { | 614 if (response_code == 304 && fetcher->existing_entry().has_response_id()) { |
| 606 // Keep the existing response. | 615 // Keep the existing response. |
| 607 entry.set_response_id(fetcher->existing_entry().response_id()); | 616 entry.set_response_id(fetcher->existing_entry().response_id()); |
| 608 entry.set_response_size(fetcher->existing_entry().response_size()); | 617 entry.set_response_size(fetcher->existing_entry().response_size()); |
| 609 inprogress_cache_->AddOrModifyEntry(url, entry); | 618 inprogress_cache_->AddOrModifyEntry(url, entry); |
| 610 } else { | 619 } else { |
| 611 const char* kFormatString = "Resource fetch failed (%d) %s"; | 620 const char* kFormatString = "Resource fetch failed (%d) %s"; |
| 612 std::string message = FormatUrlErrorMessage( | 621 std::string message = FormatUrlErrorMessage( |
| 613 kFormatString, url, fetcher->result(), response_code); | 622 kFormatString, url, fetcher->result(), response_code); |
| 614 HandleCacheFailure(message, fetcher->result()); | 623 HandleCacheFailure(message, fetcher->result(), url); |
| 615 return; | 624 return; |
| 616 } | 625 } |
| 617 } else if (response_code == 404 || response_code == 410) { | 626 } else if (response_code == 404 || response_code == 410) { |
| 618 // Entry is skipped. They are dropped from the cache. | 627 // Entry is skipped. They are dropped from the cache. |
| 619 } else if (update_type_ == UPGRADE_ATTEMPT && | 628 } else if (update_type_ == UPGRADE_ATTEMPT && |
| 620 fetcher->existing_entry().has_response_id()) { | 629 fetcher->existing_entry().has_response_id()) { |
| 621 // Keep the existing response. | 630 // Keep the existing response. |
| 622 // TODO(michaeln): Not sure this is a good idea. This is spec compliant | 631 // TODO(michaeln): Not sure this is a good idea. This is spec compliant |
| 623 // but the old resource may or may not be compatible with the new contents | 632 // but the old resource may or may not be compatible with the new contents |
| 624 // of the cache. Impossible to know one way or the other. | 633 // of the cache. Impossible to know one way or the other. |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 700 | 709 |
| 701 // In downloading case, update result is different if all master entries | 710 // In downloading case, update result is different if all master entries |
| 702 // failed vs. only some failing. | 711 // failed vs. only some failing. |
| 703 if (inprogress_cache_.get()) { | 712 if (inprogress_cache_.get()) { |
| 704 // Only count successful downloads to know if all master entries failed. | 713 // Only count successful downloads to know if all master entries failed. |
| 705 pending_master_entries_.erase(found); | 714 pending_master_entries_.erase(found); |
| 706 --master_entries_completed_; | 715 --master_entries_completed_; |
| 707 | 716 |
| 708 // Section 6.9.4, step 22.3. | 717 // Section 6.9.4, step 22.3. |
| 709 if (update_type_ == CACHE_ATTEMPT && pending_master_entries_.empty()) { | 718 if (update_type_ == CACHE_ATTEMPT && pending_master_entries_.empty()) { |
| 710 HandleCacheFailure(message, fetcher->result()); | 719 HandleCacheFailure(message, fetcher->result(), GURL()); |
| 711 return; | 720 return; |
| 712 } | 721 } |
| 713 } | 722 } |
| 714 } | 723 } |
| 715 | 724 |
| 716 DCHECK(internal_state_ != CACHE_FAILURE); | 725 DCHECK(internal_state_ != CACHE_FAILURE); |
| 717 FetchMasterEntries(); | 726 FetchMasterEntries(); |
| 718 MaybeCompleteUpdate(); | 727 MaybeCompleteUpdate(); |
| 719 } | 728 } |
| 720 | 729 |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 742 io_buffer.get(), | 751 io_buffer.get(), |
| 743 base::Bind(&AppCacheUpdateJob::OnManifestInfoWriteComplete, | 752 base::Bind(&AppCacheUpdateJob::OnManifestInfoWriteComplete, |
| 744 base::Unretained(this))); | 753 base::Unretained(this))); |
| 745 } | 754 } |
| 746 } else { | 755 } else { |
| 747 VLOG(1) << "Request status: " << request->status().status() | 756 VLOG(1) << "Request status: " << request->status().status() |
| 748 << " error: " << request->status().error() | 757 << " error: " << request->status().error() |
| 749 << " response code: " << response_code; | 758 << " response code: " << response_code; |
| 750 ScheduleUpdateRetry(kRerunDelayMs); | 759 ScheduleUpdateRetry(kRerunDelayMs); |
| 751 if (response_code == 200) { | 760 if (response_code == 200) { |
| 752 HandleCacheFailure("Manifest changed during update", MANIFEST_ERROR); | 761 HandleCacheFailure( |
| 762 "Manifest changed during update", MANIFEST_ERROR, GURL()); | |
| 753 } else { | 763 } else { |
| 754 const char* kFormatString = "Manifest re-fetch failed (%d) %s"; | 764 const char* kFormatString = "Manifest re-fetch failed (%d) %s"; |
| 755 std::string message = FormatUrlErrorMessage( | 765 std::string message = FormatUrlErrorMessage( |
| 756 kFormatString, manifest_url_, fetcher->result(), response_code); | 766 kFormatString, manifest_url_, fetcher->result(), response_code); |
| 757 HandleCacheFailure(message, fetcher->result()); | 767 HandleCacheFailure(message, fetcher->result(), GURL()); |
| 758 } | 768 } |
| 759 } | 769 } |
| 760 } | 770 } |
| 761 | 771 |
| 762 void AppCacheUpdateJob::OnManifestInfoWriteComplete(int result) { | 772 void AppCacheUpdateJob::OnManifestInfoWriteComplete(int result) { |
| 763 if (result > 0) { | 773 if (result > 0) { |
| 764 scoped_refptr<net::StringIOBuffer> io_buffer( | 774 scoped_refptr<net::StringIOBuffer> io_buffer( |
| 765 new net::StringIOBuffer(manifest_data_)); | 775 new net::StringIOBuffer(manifest_data_)); |
| 766 manifest_response_writer_->WriteData( | 776 manifest_response_writer_->WriteData( |
| 767 io_buffer.get(), | 777 io_buffer.get(), |
| 768 manifest_data_.length(), | 778 manifest_data_.length(), |
| 769 base::Bind(&AppCacheUpdateJob::OnManifestDataWriteComplete, | 779 base::Bind(&AppCacheUpdateJob::OnManifestDataWriteComplete, |
| 770 base::Unretained(this))); | 780 base::Unretained(this))); |
| 771 } else { | 781 } else { |
| 772 HandleCacheFailure("Failed to write the manifest headers to storage", | 782 HandleCacheFailure("Failed to write the manifest headers to storage", |
| 773 DISKCACHE_ERROR); | 783 DISKCACHE_ERROR, GURL()); |
| 774 } | 784 } |
| 775 } | 785 } |
| 776 | 786 |
| 777 void AppCacheUpdateJob::OnManifestDataWriteComplete(int result) { | 787 void AppCacheUpdateJob::OnManifestDataWriteComplete(int result) { |
| 778 if (result > 0) { | 788 if (result > 0) { |
| 779 AppCacheEntry entry(AppCacheEntry::MANIFEST, | 789 AppCacheEntry entry(AppCacheEntry::MANIFEST, |
| 780 manifest_response_writer_->response_id(), | 790 manifest_response_writer_->response_id(), |
| 781 manifest_response_writer_->amount_written()); | 791 manifest_response_writer_->amount_written()); |
| 782 if (!inprogress_cache_->AddOrModifyEntry(manifest_url_, entry)) | 792 if (!inprogress_cache_->AddOrModifyEntry(manifest_url_, entry)) |
| 783 duplicate_response_ids_.push_back(entry.response_id()); | 793 duplicate_response_ids_.push_back(entry.response_id()); |
| 784 StoreGroupAndCache(); | 794 StoreGroupAndCache(); |
| 785 } else { | 795 } else { |
| 786 HandleCacheFailure("Failed to write the manifest data to storage", | 796 HandleCacheFailure("Failed to write the manifest data to storage", |
| 787 DISKCACHE_ERROR); | 797 DISKCACHE_ERROR, GURL()); |
| 788 } | 798 } |
| 789 } | 799 } |
| 790 | 800 |
| 791 void AppCacheUpdateJob::StoreGroupAndCache() { | 801 void AppCacheUpdateJob::StoreGroupAndCache() { |
| 792 DCHECK(stored_state_ == UNSTORED); | 802 DCHECK(stored_state_ == UNSTORED); |
| 793 stored_state_ = STORING; | 803 stored_state_ = STORING; |
| 794 scoped_refptr<AppCache> newest_cache; | 804 scoped_refptr<AppCache> newest_cache; |
| 795 if (inprogress_cache_.get()) | 805 if (inprogress_cache_.get()) |
| 796 newest_cache.swap(inprogress_cache_); | 806 newest_cache.swap(inprogress_cache_); |
| 797 else | 807 else |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 818 // and the proper cleanup to occur. | 828 // and the proper cleanup to occur. |
| 819 if (newest_cache != group->newest_complete_cache()) | 829 if (newest_cache != group->newest_complete_cache()) |
| 820 inprogress_cache_ = newest_cache; | 830 inprogress_cache_ = newest_cache; |
| 821 | 831 |
| 822 ResultType result = DB_ERROR; | 832 ResultType result = DB_ERROR; |
| 823 std::string message("Failed to commit new cache to storage"); | 833 std::string message("Failed to commit new cache to storage"); |
| 824 if (would_exceed_quota) { | 834 if (would_exceed_quota) { |
| 825 message.append(", would exceed quota"); | 835 message.append(", would exceed quota"); |
| 826 result = QUOTA_ERROR; | 836 result = QUOTA_ERROR; |
| 827 } | 837 } |
| 828 HandleCacheFailure(message, result); | 838 HandleCacheFailure(message, result, GURL()); |
| 829 } | 839 } |
| 830 } | 840 } |
| 831 | 841 |
| 832 void AppCacheUpdateJob::NotifySingleHost(AppCacheHost* host, | 842 void AppCacheUpdateJob::NotifySingleHost(AppCacheHost* host, |
| 833 EventID event_id) { | 843 EventID event_id) { |
| 834 std::vector<int> ids(1, host->host_id()); | 844 std::vector<int> ids(1, host->host_id()); |
| 835 host->frontend()->OnEventRaised(ids, event_id); | 845 host->frontend()->OnEventRaised(ids, event_id); |
| 836 } | 846 } |
| 837 | 847 |
| 838 void AppCacheUpdateJob::NotifyAllAssociatedHosts(EventID event_id) { | 848 void AppCacheUpdateJob::NotifyAllAssociatedHosts(EventID event_id) { |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 904 AppCacheEntry* entry = NULL; | 914 AppCacheEntry* entry = NULL; |
| 905 if (group_->newest_complete_cache()) | 915 if (group_->newest_complete_cache()) |
| 906 entry = group_->newest_complete_cache()->GetEntry(manifest_url_); | 916 entry = group_->newest_complete_cache()->GetEntry(manifest_url_); |
| 907 if (!entry) { | 917 if (!entry) { |
| 908 // TODO(michaeln): This is just a bandaid to avoid a crash. | 918 // TODO(michaeln): This is just a bandaid to avoid a crash. |
| 909 // http://code.google.com/p/chromium/issues/detail?id=95101 | 919 // http://code.google.com/p/chromium/issues/detail?id=95101 |
| 910 if (service_->storage() == storage_) { | 920 if (service_->storage() == storage_) { |
| 911 // Use a local variable because service_ is reset in HandleCacheFailure. | 921 // Use a local variable because service_ is reset in HandleCacheFailure. |
| 912 AppCacheService* service = service_; | 922 AppCacheService* service = service_; |
| 913 HandleCacheFailure("Manifest entry not found in existing cache", | 923 HandleCacheFailure("Manifest entry not found in existing cache", |
| 914 DB_ERROR); | 924 DB_ERROR, GURL()); |
| 915 AppCacheHistograms::AddMissingManifestEntrySample(); | 925 AppCacheHistograms::AddMissingManifestEntrySample(); |
| 916 service->DeleteAppCacheGroup(manifest_url_, net::CompletionCallback()); | 926 service->DeleteAppCacheGroup(manifest_url_, net::CompletionCallback()); |
| 917 } | 927 } |
| 918 return; | 928 return; |
| 919 } | 929 } |
| 920 | 930 |
| 921 // Load manifest data from storage to compare against fetched manifest. | 931 // Load manifest data from storage to compare against fetched manifest. |
| 922 manifest_response_reader_.reset( | 932 manifest_response_reader_.reset( |
| 923 storage_->CreateResponseReader(manifest_url_, | 933 storage_->CreateResponseReader(manifest_url_, |
| 924 group_->group_id(), | 934 group_->group_id(), |
| (...skipping 383 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1308 break; | 1318 break; |
| 1309 case REFETCH_MANIFEST: | 1319 case REFETCH_MANIFEST: |
| 1310 DCHECK(stored_state_ == STORED); | 1320 DCHECK(stored_state_ == STORED); |
| 1311 NotifyAllFinalProgress(); | 1321 NotifyAllFinalProgress(); |
| 1312 if (update_type_ == CACHE_ATTEMPT) | 1322 if (update_type_ == CACHE_ATTEMPT) |
| 1313 NotifyAllAssociatedHosts(CACHED_EVENT); | 1323 NotifyAllAssociatedHosts(CACHED_EVENT); |
| 1314 else | 1324 else |
| 1315 NotifyAllAssociatedHosts(UPDATE_READY_EVENT); | 1325 NotifyAllAssociatedHosts(UPDATE_READY_EVENT); |
| 1316 DiscardDuplicateResponses(); | 1326 DiscardDuplicateResponses(); |
| 1317 internal_state_ = COMPLETED; | 1327 internal_state_ = COMPLETED; |
| 1318 AppCacheHistograms::CountUpdateJobResult( | 1328 LogHistogramStats(UPDATE_OK, GURL()); |
| 1319 UPDATE_OK, manifest_url_.GetOrigin()); | |
| 1320 break; | 1329 break; |
| 1321 case CACHE_FAILURE: | 1330 case CACHE_FAILURE: |
| 1322 NOTREACHED(); // See HandleCacheFailure | 1331 NOTREACHED(); // See HandleCacheFailure |
| 1323 break; | 1332 break; |
| 1324 default: | 1333 default: |
| 1325 break; | 1334 break; |
| 1326 } | 1335 } |
| 1327 | 1336 |
| 1328 // Let the stack unwind before deletion to make it less risky as this | 1337 // Let the stack unwind before deletion to make it less risky as this |
| 1329 // method is called from multiple places in this file. | 1338 // method is called from multiple places in this file. |
| 1330 if (internal_state_ == COMPLETED) | 1339 if (internal_state_ == COMPLETED) |
| 1331 DeleteSoon(); | 1340 DeleteSoon(); |
| 1332 } | 1341 } |
| 1333 | 1342 |
| 1334 void AppCacheUpdateJob::ScheduleUpdateRetry(int delay_ms) { | 1343 void AppCacheUpdateJob::ScheduleUpdateRetry(int delay_ms) { |
| 1335 // TODO(jennb): post a delayed task with the "same parameters" as this job | 1344 // TODO(jennb): post a delayed task with the "same parameters" as this job |
| 1336 // to retry the update at a later time. Need group, URLs of pending master | 1345 // to retry the update at a later time. Need group, URLs of pending master |
| 1337 // entries and their hosts. | 1346 // entries and their hosts. |
| 1338 } | 1347 } |
| 1339 | 1348 |
| 1340 void AppCacheUpdateJob::Cancel() { | 1349 void AppCacheUpdateJob::Cancel() { |
| 1341 internal_state_ = CANCELLED; | 1350 internal_state_ = CANCELLED; |
| 1342 | 1351 |
| 1352 LogHistogramStats(CANCELLED_ERROR, GURL()); | |
|
michaeln
2014/03/21 01:21:39
When the job ends by this code path, if there are
| |
| 1353 | |
| 1343 if (manifest_fetcher_) { | 1354 if (manifest_fetcher_) { |
| 1344 delete manifest_fetcher_; | 1355 delete manifest_fetcher_; |
| 1345 manifest_fetcher_ = NULL; | 1356 manifest_fetcher_ = NULL; |
| 1346 } | 1357 } |
| 1347 | 1358 |
| 1348 for (PendingUrlFetches::iterator it = pending_url_fetches_.begin(); | 1359 for (PendingUrlFetches::iterator it = pending_url_fetches_.begin(); |
| 1349 it != pending_url_fetches_.end(); ++it) { | 1360 it != pending_url_fetches_.end(); ++it) { |
| 1350 delete it->second; | 1361 delete it->second; |
| 1351 } | 1362 } |
| 1352 pending_url_fetches_.clear(); | 1363 pending_url_fetches_.clear(); |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1409 (*hosts.begin())->AssociateNoCache(GURL()); | 1420 (*hosts.begin())->AssociateNoCache(GURL()); |
| 1410 | 1421 |
| 1411 inprogress_cache_ = NULL; | 1422 inprogress_cache_ = NULL; |
| 1412 added_master_entries_.clear(); | 1423 added_master_entries_.clear(); |
| 1413 } | 1424 } |
| 1414 | 1425 |
| 1415 void AppCacheUpdateJob::DiscardDuplicateResponses() { | 1426 void AppCacheUpdateJob::DiscardDuplicateResponses() { |
| 1416 storage_->DoomResponses(manifest_url_, duplicate_response_ids_); | 1427 storage_->DoomResponses(manifest_url_, duplicate_response_ids_); |
| 1417 } | 1428 } |
| 1418 | 1429 |
| 1430 void AppCacheUpdateJob::LogHistogramStats( | |
| 1431 ResultType result, const GURL& failed_resource_url) { | |
| 1432 AppCacheHistograms::CountUpdateJobResult(result, manifest_url_.GetOrigin()); | |
| 1433 if (result == UPDATE_OK) | |
| 1434 return; | |
| 1435 | |
| 1436 int percent_complete = 0; | |
| 1437 if (url_file_list_.size() > 0) { | |
| 1438 size_t actual_fetches_completed = url_fetches_completed_; | |
| 1439 if (!failed_resource_url.is_empty() && actual_fetches_completed) | |
| 1440 --actual_fetches_completed; | |
| 1441 percent_complete = (static_cast<double>(actual_fetches_completed) / | |
| 1442 static_cast<double>(url_file_list_.size())) * 100.0; | |
| 1443 percent_complete = std::min(percent_complete, 99); | |
| 1444 } | |
| 1445 | |
| 1446 bool was_making_progress = | |
| 1447 base::Time::Now() - last_progress_time_ < | |
| 1448 base::TimeDelta::FromMinutes(5); | |
| 1449 | |
| 1450 bool off_origin_resource_failure = | |
| 1451 !failed_resource_url.is_empty() && | |
| 1452 (failed_resource_url.GetOrigin() != manifest_url_.GetOrigin()); | |
| 1453 | |
| 1454 AppCacheHistograms::LogUpdateFailureStats( | |
| 1455 manifest_url_.GetOrigin(), | |
| 1456 percent_complete, | |
| 1457 was_making_progress, | |
| 1458 off_origin_resource_failure); | |
| 1459 } | |
| 1460 | |
| 1419 void AppCacheUpdateJob::DeleteSoon() { | 1461 void AppCacheUpdateJob::DeleteSoon() { |
| 1420 ClearPendingMasterEntries(); | 1462 ClearPendingMasterEntries(); |
| 1421 manifest_response_writer_.reset(); | 1463 manifest_response_writer_.reset(); |
| 1422 storage_->CancelDelegateCallbacks(this); | 1464 storage_->CancelDelegateCallbacks(this); |
| 1423 service_->RemoveObserver(this); | 1465 service_->RemoveObserver(this); |
| 1424 service_ = NULL; | 1466 service_ = NULL; |
| 1425 | 1467 |
| 1426 // Break the connection with the group so the group cannot call delete | 1468 // Break the connection with the group so the group cannot call delete |
| 1427 // on this object after we've posted a task to delete ourselves. | 1469 // on this object after we've posted a task to delete ourselves. |
| 1428 group_->SetUpdateStatus(AppCacheGroup::IDLE); | 1470 group_->SetUpdateStatus(AppCacheGroup::IDLE); |
| 1429 group_ = NULL; | 1471 group_ = NULL; |
| 1430 | 1472 |
| 1431 base::MessageLoop::current()->DeleteSoon(FROM_HERE, this); | 1473 base::MessageLoop::current()->DeleteSoon(FROM_HERE, this); |
| 1432 } | 1474 } |
| 1433 | 1475 |
| 1434 } // namespace appcache | 1476 } // namespace appcache |
| OLD | NEW |