| 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 "content/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 "content/browser/appcache/appcache_group.h" |
| 14 #include "content/browser/appcache/appcache_histograms.h" |
| 13 #include "net/base/io_buffer.h" | 15 #include "net/base/io_buffer.h" |
| 14 #include "net/base/load_flags.h" | 16 #include "net/base/load_flags.h" |
| 15 #include "net/base/net_errors.h" | 17 #include "net/base/net_errors.h" |
| 16 #include "net/base/request_priority.h" | 18 #include "net/base/request_priority.h" |
| 17 #include "net/http/http_request_headers.h" | 19 #include "net/http/http_request_headers.h" |
| 18 #include "net/http/http_response_headers.h" | 20 #include "net/http/http_response_headers.h" |
| 19 #include "net/url_request/url_request_context.h" | 21 #include "net/url_request/url_request_context.h" |
| 20 #include "webkit/browser/appcache/appcache_group.h" | |
| 21 #include "webkit/browser/appcache/appcache_histograms.h" | |
| 22 | 22 |
| 23 namespace appcache { | 23 namespace content { |
| 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( | 29 static std::string FormatUrlErrorMessage( |
| 30 const char* format, const GURL& url, | 30 const char* format, const GURL& url, |
| 31 AppCacheUpdateJob::ResultType error, | 31 AppCacheUpdateJob::ResultType error, |
| 32 int response_code) { | 32 int response_code) { |
| 33 // Show the net response code if we have one. | 33 // Show the net response code if we have one. |
| (...skipping 485 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 519 } else if (response_code == 304 && update_type_ == UPGRADE_ATTEMPT) { | 519 } else if (response_code == 304 && update_type_ == UPGRADE_ATTEMPT) { |
| 520 ContinueHandleManifestFetchCompleted(false); | 520 ContinueHandleManifestFetchCompleted(false); |
| 521 } else if ((response_code == 404 || response_code == 410) && | 521 } else if ((response_code == 404 || response_code == 410) && |
| 522 update_type_ == UPGRADE_ATTEMPT) { | 522 update_type_ == UPGRADE_ATTEMPT) { |
| 523 storage_->MakeGroupObsolete(group_, this, response_code); // async | 523 storage_->MakeGroupObsolete(group_, this, response_code); // async |
| 524 } else { | 524 } else { |
| 525 const char* kFormatString = "Manifest fetch failed (%d) %s"; | 525 const char* kFormatString = "Manifest fetch failed (%d) %s"; |
| 526 std::string message = FormatUrlErrorMessage( | 526 std::string message = FormatUrlErrorMessage( |
| 527 kFormatString, manifest_url_, fetcher->result(), response_code); | 527 kFormatString, manifest_url_, fetcher->result(), response_code); |
| 528 HandleCacheFailure(AppCacheErrorDetails(message, | 528 HandleCacheFailure(AppCacheErrorDetails(message, |
| 529 appcache::APPCACHE_MANIFEST_ERROR, | 529 APPCACHE_MANIFEST_ERROR, |
| 530 manifest_url_, | 530 manifest_url_, |
| 531 response_code, | 531 response_code, |
| 532 false /*is_cross_origin*/), | 532 false /*is_cross_origin*/), |
| 533 fetcher->result(), | 533 fetcher->result(), |
| 534 GURL()); | 534 GURL()); |
| 535 } | 535 } |
| 536 } | 536 } |
| 537 | 537 |
| 538 void AppCacheUpdateJob::OnGroupMadeObsolete(AppCacheGroup* group, | 538 void AppCacheUpdateJob::OnGroupMadeObsolete(AppCacheGroup* group, |
| 539 bool success, | 539 bool success, |
| 540 int response_code) { | 540 int response_code) { |
| 541 DCHECK(master_entry_fetches_.empty()); | 541 DCHECK(master_entry_fetches_.empty()); |
| 542 CancelAllMasterEntryFetches(AppCacheErrorDetails( | 542 CancelAllMasterEntryFetches(AppCacheErrorDetails( |
| 543 "The cache has been made obsolete, " | 543 "The cache has been made obsolete, " |
| 544 "the manifest file returned 404 or 410", | 544 "the manifest file returned 404 or 410", |
| 545 appcache::APPCACHE_MANIFEST_ERROR, | 545 APPCACHE_MANIFEST_ERROR, |
| 546 GURL(), | 546 GURL(), |
| 547 response_code, | 547 response_code, |
| 548 false /*is_cross_origin*/)); | 548 false /*is_cross_origin*/)); |
| 549 if (success) { | 549 if (success) { |
| 550 DCHECK(group->is_obsolete()); | 550 DCHECK(group->is_obsolete()); |
| 551 NotifyAllAssociatedHosts(APPCACHE_OBSOLETE_EVENT); | 551 NotifyAllAssociatedHosts(APPCACHE_OBSOLETE_EVENT); |
| 552 internal_state_ = COMPLETED; | 552 internal_state_ = COMPLETED; |
| 553 MaybeCompleteUpdate(); | 553 MaybeCompleteUpdate(); |
| 554 } else { | 554 } else { |
| 555 // Treat failure to mark group obsolete as a cache failure. | 555 // Treat failure to mark group obsolete as a cache failure. |
| (...skipping 28 matching lines...) Expand all Loading... |
| 584 PARSE_MANIFEST_ALLOWING_INTERCEPTS : | 584 PARSE_MANIFEST_ALLOWING_INTERCEPTS : |
| 585 PARSE_MANIFEST_PER_STANDARD, | 585 PARSE_MANIFEST_PER_STANDARD, |
| 586 manifest)) { | 586 manifest)) { |
| 587 const char* kFormatString = "Failed to parse manifest %s"; | 587 const char* kFormatString = "Failed to parse manifest %s"; |
| 588 const std::string message = base::StringPrintf(kFormatString, | 588 const std::string message = base::StringPrintf(kFormatString, |
| 589 manifest_url_.spec().c_str()); | 589 manifest_url_.spec().c_str()); |
| 590 HandleCacheFailure( | 590 HandleCacheFailure( |
| 591 AppCacheErrorDetails( | 591 AppCacheErrorDetails( |
| 592 message, APPCACHE_SIGNATURE_ERROR, GURL(), 0, | 592 message, APPCACHE_SIGNATURE_ERROR, GURL(), 0, |
| 593 false /*is_cross_origin*/), | 593 false /*is_cross_origin*/), |
| 594 APPCACHE_MANIFEST_ERROR, | 594 MANIFEST_ERROR, |
| 595 GURL()); | 595 GURL()); |
| 596 VLOG(1) << message; | 596 VLOG(1) << message; |
| 597 return; | 597 return; |
| 598 } | 598 } |
| 599 | 599 |
| 600 // Proceed with update process. Section 6.9.4 steps 8-20. | 600 // Proceed with update process. Section 6.9.4 steps 8-20. |
| 601 internal_state_ = DOWNLOADING; | 601 internal_state_ = DOWNLOADING; |
| 602 inprogress_cache_ = new AppCache(storage_, storage_->NewCacheId()); | 602 inprogress_cache_ = new AppCache(storage_, storage_->NewCacheId()); |
| 603 BuildUrlFileList(manifest); | 603 BuildUrlFileList(manifest); |
| 604 inprogress_cache_->InitializeWithManifest(&manifest); | 604 inprogress_cache_->InitializeWithManifest(&manifest); |
| (...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 783 | 783 |
| 784 host->RemoveObserver(this); | 784 host->RemoveObserver(this); |
| 785 } | 785 } |
| 786 hosts.clear(); | 786 hosts.clear(); |
| 787 | 787 |
| 788 const char* kFormatString = "Manifest fetch failed (%d) %s"; | 788 const char* kFormatString = "Manifest fetch failed (%d) %s"; |
| 789 std::string message = FormatUrlErrorMessage( | 789 std::string message = FormatUrlErrorMessage( |
| 790 kFormatString, request->url(), fetcher->result(), response_code); | 790 kFormatString, request->url(), fetcher->result(), response_code); |
| 791 host_notifier.SendErrorNotifications( | 791 host_notifier.SendErrorNotifications( |
| 792 AppCacheErrorDetails(message, | 792 AppCacheErrorDetails(message, |
| 793 appcache::APPCACHE_MANIFEST_ERROR, | 793 APPCACHE_MANIFEST_ERROR, |
| 794 request->url(), | 794 request->url(), |
| 795 response_code, | 795 response_code, |
| 796 false /*is_cross_origin*/)); | 796 false /*is_cross_origin*/)); |
| 797 | 797 |
| 798 // In downloading case, update result is different if all master entries | 798 // In downloading case, update result is different if all master entries |
| 799 // failed vs. only some failing. | 799 // failed vs. only some failing. |
| 800 if (inprogress_cache_.get()) { | 800 if (inprogress_cache_.get()) { |
| 801 // Only count successful downloads to know if all master entries failed. | 801 // Only count successful downloads to know if all master entries failed. |
| 802 pending_master_entries_.erase(found); | 802 pending_master_entries_.erase(found); |
| 803 --master_entries_completed_; | 803 --master_entries_completed_; |
| 804 | 804 |
| 805 // Section 6.9.4, step 22.3. | 805 // Section 6.9.4, step 22.3. |
| 806 if (update_type_ == CACHE_ATTEMPT && pending_master_entries_.empty()) { | 806 if (update_type_ == CACHE_ATTEMPT && pending_master_entries_.empty()) { |
| 807 HandleCacheFailure(AppCacheErrorDetails(message, | 807 HandleCacheFailure(AppCacheErrorDetails(message, |
| 808 appcache::APPCACHE_MANIFEST_ERROR, | 808 APPCACHE_MANIFEST_ERROR, |
| 809 request->url(), | 809 request->url(), |
| 810 response_code, | 810 response_code, |
| 811 false /*is_cross_origin*/), | 811 false /*is_cross_origin*/), |
| 812 fetcher->result(), | 812 fetcher->result(), |
| 813 GURL()); | 813 GURL()); |
| 814 return; | 814 return; |
| 815 } | 815 } |
| 816 } | 816 } |
| 817 } | 817 } |
| 818 | 818 |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 850 VLOG(1) << "Request status: " << request->status().status() | 850 VLOG(1) << "Request status: " << request->status().status() |
| 851 << " error: " << request->status().error() | 851 << " error: " << request->status().error() |
| 852 << " response code: " << response_code; | 852 << " response code: " << response_code; |
| 853 ScheduleUpdateRetry(kRerunDelayMs); | 853 ScheduleUpdateRetry(kRerunDelayMs); |
| 854 if (response_code == 200) { | 854 if (response_code == 200) { |
| 855 HandleCacheFailure(AppCacheErrorDetails("Manifest changed during update", | 855 HandleCacheFailure(AppCacheErrorDetails("Manifest changed during update", |
| 856 APPCACHE_CHANGED_ERROR, | 856 APPCACHE_CHANGED_ERROR, |
| 857 GURL(), | 857 GURL(), |
| 858 0, | 858 0, |
| 859 false /*is_cross_origin*/), | 859 false /*is_cross_origin*/), |
| 860 APPCACHE_MANIFEST_ERROR, | 860 MANIFEST_ERROR, |
| 861 GURL()); | 861 GURL()); |
| 862 } else { | 862 } else { |
| 863 const char* kFormatString = "Manifest re-fetch failed (%d) %s"; | 863 const char* kFormatString = "Manifest re-fetch failed (%d) %s"; |
| 864 std::string message = FormatUrlErrorMessage( | 864 std::string message = FormatUrlErrorMessage( |
| 865 kFormatString, manifest_url_, fetcher->result(), response_code); | 865 kFormatString, manifest_url_, fetcher->result(), response_code); |
| 866 HandleCacheFailure(AppCacheErrorDetails(message, | 866 HandleCacheFailure(AppCacheErrorDetails(message, |
| 867 appcache::APPCACHE_MANIFEST_ERROR, | 867 APPCACHE_MANIFEST_ERROR, |
| 868 GURL(), | 868 GURL(), |
| 869 response_code, | 869 response_code, |
| 870 false /*is_cross_origin*/), | 870 false /*is_cross_origin*/), |
| 871 fetcher->result(), | 871 fetcher->result(), |
| 872 GURL()); | 872 GURL()); |
| 873 } | 873 } |
| 874 } | 874 } |
| 875 } | 875 } |
| 876 | 876 |
| 877 void AppCacheUpdateJob::OnManifestInfoWriteComplete(int result) { | 877 void AppCacheUpdateJob::OnManifestInfoWriteComplete(int result) { |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 944 // Restore inprogress_cache_ to get the proper events delivered | 944 // Restore inprogress_cache_ to get the proper events delivered |
| 945 // and the proper cleanup to occur. | 945 // and the proper cleanup to occur. |
| 946 if (newest_cache != group->newest_complete_cache()) | 946 if (newest_cache != group->newest_complete_cache()) |
| 947 inprogress_cache_ = newest_cache; | 947 inprogress_cache_ = newest_cache; |
| 948 | 948 |
| 949 ResultType result = DB_ERROR; | 949 ResultType result = DB_ERROR; |
| 950 AppCacheErrorReason reason = APPCACHE_UNKNOWN_ERROR; | 950 AppCacheErrorReason reason = APPCACHE_UNKNOWN_ERROR; |
| 951 std::string message("Failed to commit new cache to storage"); | 951 std::string message("Failed to commit new cache to storage"); |
| 952 if (would_exceed_quota) { | 952 if (would_exceed_quota) { |
| 953 message.append(", would exceed quota"); | 953 message.append(", would exceed quota"); |
| 954 result = APPCACHE_QUOTA_ERROR; | 954 result = QUOTA_ERROR; |
| 955 reason = appcache::APPCACHE_QUOTA_ERROR; | 955 reason = APPCACHE_QUOTA_ERROR; |
| 956 } | 956 } |
| 957 HandleCacheFailure( | 957 HandleCacheFailure( |
| 958 AppCacheErrorDetails(message, reason, GURL(), 0, | 958 AppCacheErrorDetails(message, reason, GURL(), 0, |
| 959 false /*is_cross_origin*/), | 959 false /*is_cross_origin*/), |
| 960 result, | 960 result, |
| 961 GURL()); | 961 GURL()); |
| 962 } | 962 } |
| 963 } | 963 } |
| 964 | 964 |
| 965 void AppCacheUpdateJob::NotifySingleHost(AppCacheHost* host, | 965 void AppCacheUpdateJob::NotifySingleHost(AppCacheHost* host, |
| (...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1092 } | 1092 } |
| 1093 } | 1093 } |
| 1094 | 1094 |
| 1095 void AppCacheUpdateJob::BuildUrlFileList(const Manifest& manifest) { | 1095 void AppCacheUpdateJob::BuildUrlFileList(const Manifest& manifest) { |
| 1096 for (base::hash_set<std::string>::const_iterator it = | 1096 for (base::hash_set<std::string>::const_iterator it = |
| 1097 manifest.explicit_urls.begin(); | 1097 manifest.explicit_urls.begin(); |
| 1098 it != manifest.explicit_urls.end(); ++it) { | 1098 it != manifest.explicit_urls.end(); ++it) { |
| 1099 AddUrlToFileList(GURL(*it), AppCacheEntry::EXPLICIT); | 1099 AddUrlToFileList(GURL(*it), AppCacheEntry::EXPLICIT); |
| 1100 } | 1100 } |
| 1101 | 1101 |
| 1102 const std::vector<Namespace>& intercepts = | 1102 const std::vector<AppCacheNamespace>& intercepts = |
| 1103 manifest.intercept_namespaces; | 1103 manifest.intercept_namespaces; |
| 1104 for (std::vector<Namespace>::const_iterator it = intercepts.begin(); | 1104 for (std::vector<AppCacheNamespace>::const_iterator it = intercepts.begin(); |
| 1105 it != intercepts.end(); ++it) { | 1105 it != intercepts.end(); ++it) { |
| 1106 int flags = AppCacheEntry::INTERCEPT; | 1106 int flags = AppCacheEntry::INTERCEPT; |
| 1107 if (it->is_executable) | 1107 if (it->is_executable) |
| 1108 flags |= AppCacheEntry::EXECUTABLE; | 1108 flags |= AppCacheEntry::EXECUTABLE; |
| 1109 AddUrlToFileList(it->target_url, flags); | 1109 AddUrlToFileList(it->target_url, flags); |
| 1110 } | 1110 } |
| 1111 | 1111 |
| 1112 const std::vector<Namespace>& fallbacks = | 1112 const std::vector<AppCacheNamespace>& fallbacks = |
| 1113 manifest.fallback_namespaces; | 1113 manifest.fallback_namespaces; |
| 1114 for (std::vector<Namespace>::const_iterator it = fallbacks.begin(); | 1114 for (std::vector<AppCacheNamespace>::const_iterator it = fallbacks.begin(); |
| 1115 it != fallbacks.end(); ++it) { | 1115 it != fallbacks.end(); ++it) { |
| 1116 AddUrlToFileList(it->target_url, AppCacheEntry::FALLBACK); | 1116 AddUrlToFileList(it->target_url, AppCacheEntry::FALLBACK); |
| 1117 } | 1117 } |
| 1118 | 1118 |
| 1119 // Add all master entries from newest complete cache. | 1119 // Add all master entries from newest complete cache. |
| 1120 if (update_type_ == UPGRADE_ATTEMPT) { | 1120 if (update_type_ == UPGRADE_ATTEMPT) { |
| 1121 const AppCache::EntryMap& entries = | 1121 const AppCache::EntryMap& entries = |
| 1122 group_->newest_complete_cache()->entries(); | 1122 group_->newest_complete_cache()->entries(); |
| 1123 for (AppCache::EntryMap::const_iterator it = entries.begin(); | 1123 for (AppCache::EntryMap::const_iterator it = entries.begin(); |
| 1124 it != entries.end(); ++it) { | 1124 it != entries.end(); ++it) { |
| (...skipping 476 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1601 service_ = NULL; | 1601 service_ = NULL; |
| 1602 | 1602 |
| 1603 // Break the connection with the group so the group cannot call delete | 1603 // Break the connection with the group so the group cannot call delete |
| 1604 // on this object after we've posted a task to delete ourselves. | 1604 // on this object after we've posted a task to delete ourselves. |
| 1605 group_->SetUpdateAppCacheStatus(AppCacheGroup::IDLE); | 1605 group_->SetUpdateAppCacheStatus(AppCacheGroup::IDLE); |
| 1606 group_ = NULL; | 1606 group_ = NULL; |
| 1607 | 1607 |
| 1608 base::MessageLoop::current()->DeleteSoon(FROM_HERE, this); | 1608 base::MessageLoop::current()->DeleteSoon(FROM_HERE, this); |
| 1609 } | 1609 } |
| 1610 | 1610 |
| 1611 } // namespace appcache | 1611 } // namespace content |
| OLD | NEW |