| Index: webkit/browser/appcache/appcache_update_job.cc
|
| diff --git a/webkit/browser/appcache/appcache_update_job.cc b/webkit/browser/appcache/appcache_update_job.cc
|
| index 17e3bef6da644a90a10eab2081ed9ee41f2a8523..69f37cba07c4e276a89ecf22b6b3f5b8a1d07021 100644
|
| --- a/webkit/browser/appcache/appcache_update_job.cc
|
| +++ b/webkit/browser/appcache/appcache_update_job.cc
|
| @@ -26,6 +26,17 @@ static const int kBufferSize = 32768;
|
| static const size_t kMaxConcurrentUrlFetches = 2;
|
| static const int kMax503Retries = 3;
|
|
|
| +static std::string FormatUrlErrorMessage(
|
| + const char* format, const GURL& url,
|
| + AppCacheUpdateJob::ResultType error,
|
| + int response_code) {
|
| + // Show the net response code if we have one.
|
| + int code = response_code;
|
| + if (error != AppCacheUpdateJob::SERVER_ERROR)
|
| + code = static_cast<int>(error);
|
| + return base::StringPrintf(format, code, url.spec().c_str());
|
| +}
|
| +
|
| // Helper class for collecting hosts per frontend when sending notifications
|
| // so that only one notification is sent for all hosts using the same frontend.
|
| class HostNotifier {
|
| @@ -101,7 +112,8 @@ AppCacheUpdateJob::URLFetcher::URLFetcher(const GURL& url,
|
| retry_503_attempts_(0),
|
| buffer_(new net::IOBuffer(kBufferSize)),
|
| request_(job->service_->request_context()
|
| - ->CreateRequest(url, net::DEFAULT_PRIORITY, this)) {}
|
| + ->CreateRequest(url, net::DEFAULT_PRIORITY, this)),
|
| + result_(UPDATE_OK) {}
|
|
|
| AppCacheUpdateJob::URLFetcher::~URLFetcher() {
|
| }
|
| @@ -120,14 +132,17 @@ void AppCacheUpdateJob::URLFetcher::OnReceivedRedirect(
|
| DCHECK(request_ == request);
|
| // Redirect is not allowed by the update process.
|
| request->Cancel();
|
| + result_ = REDIRECT_ERROR;
|
| OnResponseCompleted();
|
| }
|
|
|
| void AppCacheUpdateJob::URLFetcher::OnResponseStarted(
|
| net::URLRequest *request) {
|
| DCHECK(request == request_);
|
| - if (request->status().is_success() &&
|
| - (request->GetResponseCode() / 100) == 2) {
|
| + int response_code = -1;
|
| + if (request->status().is_success())
|
| + response_code = request->GetResponseCode();
|
| + if ((response_code / 100) == 2) {
|
|
|
| // See http://code.google.com/p/chromium/issues/detail?id=69594
|
| // We willfully violate the HTML5 spec at this point in order
|
| @@ -141,6 +156,7 @@ void AppCacheUpdateJob::URLFetcher::OnResponseStarted(
|
| if (request->response_headers()->
|
| HasHeaderValue("cache-control", "no-store")) {
|
| request->Cancel();
|
| + result_ = SERVER_ERROR; // Not the best match?
|
| OnResponseCompleted();
|
| return;
|
| }
|
| @@ -160,6 +176,10 @@ void AppCacheUpdateJob::URLFetcher::OnResponseStarted(
|
| ReadResponseData();
|
| }
|
| } else {
|
| + if (response_code > 0)
|
| + result_ = SERVER_ERROR;
|
| + else
|
| + result_ = NETWORK_ERROR;
|
| OnResponseCompleted();
|
| }
|
| }
|
| @@ -216,6 +236,7 @@ void AppCacheUpdateJob::URLFetcher::AddConditionalHeaders(
|
| void AppCacheUpdateJob::URLFetcher::OnWriteComplete(int result) {
|
| if (result < 0) {
|
| request_->Cancel();
|
| + result_ = DISKCACHE_ERROR;
|
| OnResponseCompleted();
|
| return;
|
| }
|
| @@ -396,16 +417,21 @@ AppCacheResponseWriter* AppCacheUpdateJob::CreateResponseWriter() {
|
| return writer;
|
| }
|
|
|
| -void AppCacheUpdateJob::HandleCacheFailure(const std::string& error_message) {
|
| +void AppCacheUpdateJob::HandleCacheFailure(
|
| + const std::string& error_message,
|
| + ResultType result) {
|
| // 6.9.4 cache failure steps 2-8.
|
| DCHECK(internal_state_ != CACHE_FAILURE);
|
| DCHECK(!error_message.empty());
|
| + DCHECK(result != UPDATE_OK);
|
| internal_state_ = CACHE_FAILURE;
|
| CancelAllUrlFetches();
|
| CancelAllMasterEntryFetches(error_message);
|
| NotifyAllError(error_message);
|
| DiscardInprogressCache();
|
| internal_state_ = COMPLETED;
|
| + AppCacheHistograms::CountUpdateJobResult(
|
| + result, manifest_url_.GetOrigin());
|
| DeleteSoon(); // To unwind the stack prior to deletion.
|
| }
|
|
|
| @@ -467,9 +493,9 @@ void AppCacheUpdateJob::HandleManifestFetchCompleted(
|
| storage_->MakeGroupObsolete(group_, this); // async
|
| } else {
|
| const char* kFormatString = "Manifest fetch failed (%d) %s";
|
| - std::string message = base::StringPrintf(kFormatString, response_code,
|
| - manifest_url_.spec().c_str());
|
| - HandleCacheFailure(message);
|
| + std::string message = FormatUrlErrorMessage(
|
| + kFormatString, manifest_url_, fetcher->result(), response_code);
|
| + HandleCacheFailure(message, fetcher->result());
|
| }
|
| }
|
|
|
| @@ -485,7 +511,7 @@ void AppCacheUpdateJob::OnGroupMadeObsolete(AppCacheGroup* group,
|
| MaybeCompleteUpdate();
|
| } else {
|
| // Treat failure to mark group obsolete as a cache failure.
|
| - HandleCacheFailure("Failed to mark the cache as obsolete");
|
| + HandleCacheFailure("Failed to mark the cache as obsolete", DB_ERROR);
|
| }
|
| }
|
|
|
| @@ -508,7 +534,7 @@ void AppCacheUpdateJob::ContinueHandleManifestFetchCompleted(bool changed) {
|
| const char* kFormatString = "Failed to parse manifest %s";
|
| const std::string message = base::StringPrintf(kFormatString,
|
| manifest_url_.spec().c_str());
|
| - HandleCacheFailure(message);
|
| + HandleCacheFailure(message, MANIFEST_ERROR);
|
| VLOG(1) << message;
|
| return;
|
| }
|
| @@ -580,9 +606,9 @@ void AppCacheUpdateJob::HandleUrlFetchCompleted(URLFetcher* fetcher) {
|
| inprogress_cache_->AddOrModifyEntry(url, entry);
|
| } else {
|
| const char* kFormatString = "Resource fetch failed (%d) %s";
|
| - const std::string message = base::StringPrintf(kFormatString,
|
| - response_code, url.spec().c_str());
|
| - HandleCacheFailure(message);
|
| + std::string message = FormatUrlErrorMessage(
|
| + kFormatString, url, fetcher->result(), response_code);
|
| + HandleCacheFailure(message, fetcher->result());
|
| return;
|
| }
|
| } else if (response_code == 404 || response_code == 410) {
|
| @@ -664,9 +690,9 @@ void AppCacheUpdateJob::HandleMasterEntryFetchCompleted(
|
| }
|
| hosts.clear();
|
|
|
| - const char* kFormatString = "Master entry fetch failed (%d) %s";
|
| - const std::string message = base::StringPrintf(kFormatString,
|
| - response_code, request->url().spec().c_str());
|
| + const char* kFormatString = "Manifest fetch failed (%d) %s";
|
| + std::string message = FormatUrlErrorMessage(
|
| + kFormatString, request->url(), fetcher->result(), response_code);
|
| host_notifier.SendErrorNotifications(message);
|
|
|
| // In downloading case, update result is different if all master entries
|
| @@ -678,7 +704,7 @@ void AppCacheUpdateJob::HandleMasterEntryFetchCompleted(
|
|
|
| // Section 6.9.4, step 22.3.
|
| if (update_type_ == CACHE_ATTEMPT && pending_master_entries_.empty()) {
|
| - HandleCacheFailure(message);
|
| + HandleCacheFailure(message, fetcher->result());
|
| return;
|
| }
|
| }
|
| @@ -719,7 +745,14 @@ void AppCacheUpdateJob::HandleManifestRefetchCompleted(
|
| << " error: " << request->status().error()
|
| << " response code: " << response_code;
|
| ScheduleUpdateRetry(kRerunDelayMs);
|
| - HandleCacheFailure("Manifest changed during update, scheduling retry");
|
| + if (response_code == 200) {
|
| + HandleCacheFailure("Manifest changed during update", MANIFEST_ERROR);
|
| + } else {
|
| + const char* kFormatString = "Manifest re-fetch failed (%d) %s";
|
| + std::string message = FormatUrlErrorMessage(
|
| + kFormatString, manifest_url_, fetcher->result(), response_code);
|
| + HandleCacheFailure(message, fetcher->result());
|
| + }
|
| }
|
| }
|
|
|
| @@ -733,7 +766,8 @@ void AppCacheUpdateJob::OnManifestInfoWriteComplete(int result) {
|
| base::Bind(&AppCacheUpdateJob::OnManifestDataWriteComplete,
|
| base::Unretained(this)));
|
| } else {
|
| - HandleCacheFailure("Failed to write the manifest headers to storage");
|
| + HandleCacheFailure("Failed to write the manifest headers to storage",
|
| + DISKCACHE_ERROR);
|
| }
|
| }
|
|
|
| @@ -746,7 +780,8 @@ void AppCacheUpdateJob::OnManifestDataWriteComplete(int result) {
|
| duplicate_response_ids_.push_back(entry.response_id());
|
| StoreGroupAndCache();
|
| } else {
|
| - HandleCacheFailure("Failed to write the manifest data to storage");
|
| + HandleCacheFailure("Failed to write the manifest data to storage",
|
| + DISKCACHE_ERROR);
|
| }
|
| }
|
|
|
| @@ -779,10 +814,13 @@ void AppCacheUpdateJob::OnGroupAndNewestCacheStored(AppCacheGroup* group,
|
| if (newest_cache != group->newest_complete_cache())
|
| inprogress_cache_ = newest_cache;
|
|
|
| + ResultType result = DB_ERROR;
|
| std::string message("Failed to commit new cache to storage");
|
| - if (would_exceed_quota)
|
| + if (would_exceed_quota) {
|
| message.append(", would exceed quota");
|
| - HandleCacheFailure(message);
|
| + result = QUOTA_ERROR;
|
| + }
|
| + HandleCacheFailure(message, result);
|
| }
|
| }
|
|
|
| @@ -867,7 +905,8 @@ void AppCacheUpdateJob::CheckIfManifestChanged() {
|
| if (service_->storage() == storage_) {
|
| // Use a local variable because service_ is reset in HandleCacheFailure.
|
| AppCacheService* service = service_;
|
| - HandleCacheFailure("Manifest entry not found in existing cache");
|
| + HandleCacheFailure("Manifest entry not found in existing cache",
|
| + DB_ERROR);
|
| AppCacheHistograms::AddMissingManifestEntrySample();
|
| service->DeleteAppCacheGroup(manifest_url_, net::CompletionCallback());
|
| }
|
| @@ -1271,6 +1310,8 @@ void AppCacheUpdateJob::MaybeCompleteUpdate() {
|
| NotifyAllAssociatedHosts(UPDATE_READY_EVENT);
|
| DiscardDuplicateResponses();
|
| internal_state_ = COMPLETED;
|
| + AppCacheHistograms::CountUpdateJobResult(
|
| + UPDATE_OK, manifest_url_.GetOrigin());
|
| break;
|
| case CACHE_FAILURE:
|
| NOTREACHED(); // See HandleCacheFailure
|
|
|