diff options
author | michaeln@chromium.org <michaeln@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-07-21 19:28:04 +0000 |
---|---|---|
committer | michaeln@chromium.org <michaeln@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-07-21 19:28:04 +0000 |
commit | 348b9bc12d4e2ccd03a7fbcb327a3975207a5fec (patch) | |
tree | d3c81fa677e6bd2b5f179e4ef113a0cbcdcc80bf /webkit/appcache | |
parent | 248a52e7965033a65b8d12b623739ac727e54e89 (diff) | |
download | chromium_src-348b9bc12d4e2ccd03a7fbcb327a3975207a5fec.zip chromium_src-348b9bc12d4e2ccd03a7fbcb327a3975207a5fec.tar.gz chromium_src-348b9bc12d4e2ccd03a7fbcb327a3975207a5fec.tar.bz2 |
Make conditional requests when updating the appcache.
TEST=altered existing tests to also cover this case
BUG=49548
Review URL: http://codereview.chromium.org/3033003
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@53230 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'webkit/appcache')
-rw-r--r-- | webkit/appcache/appcache_update_job.cc | 177 | ||||
-rw-r--r-- | webkit/appcache/appcache_update_job.h | 25 | ||||
-rw-r--r-- | webkit/appcache/appcache_update_job_unittest.cc | 58 |
3 files changed, 172 insertions, 88 deletions
diff --git a/webkit/appcache/appcache_update_job.cc b/webkit/appcache/appcache_update_job.cc index 9a2d729..a112310 100644 --- a/webkit/appcache/appcache_update_job.cc +++ b/webkit/appcache/appcache_update_job.cc @@ -13,7 +13,6 @@ #include "net/http/http_request_headers.h" #include "webkit/appcache/appcache_group.h" #include "webkit/appcache/appcache_policy.h" -#include "webkit/appcache/appcache_response.h" namespace appcache { @@ -43,8 +42,8 @@ class UpdateJobInfo : public URLRequest::UserData { } void SetUpResponseWriter(AppCacheResponseWriter* writer, - AppCacheUpdateJob* update, - URLRequest* request) { + AppCacheUpdateJob* update, + URLRequest* request) { DCHECK(!response_writer_.get()); response_writer_.reset(writer); update_job_ = update; @@ -60,6 +59,9 @@ class UpdateJobInfo : public URLRequest::UserData { scoped_refptr<net::IOBuffer> buffer_; int retry_503_attempts_; + // The entry from the newest cache for this url, used for 304 responses. + AppCacheEntry existing_entry_; + // Info needed to write responses to storage and process callbacks. scoped_ptr<AppCacheResponseWriter> response_writer_; AppCacheUpdateJob* update_job_; @@ -159,6 +161,10 @@ AppCacheUpdateJob::~AppCacheUpdateJob() { policy_callback_->Cancel(); } +UpdateJobInfo* AppCacheUpdateJob::GetUpdateJobInfo(URLRequest* request) { + return static_cast<UpdateJobInfo*>(request->GetUserData(this)); +} + void AppCacheUpdateJob::StartUpdate(AppCacheHost* host, const GURL& new_master_resource) { DCHECK(group_->update_job() == this); @@ -285,44 +291,41 @@ void AppCacheUpdateJob::FetchManifest(bool is_first_fetch) { service_->storage()->LoadResponseInfo(manifest_url_, entry->response_id(), this); } else { - AddHttpHeadersAndFetch(manifest_url_request_, NULL); + manifest_url_request_->Start(); } } else { DCHECK(internal_state_ == REFETCH_MANIFEST); DCHECK(manifest_response_info_.get()); - AddHttpHeadersAndFetch(manifest_url_request_, - manifest_response_info_.get()); + AddConditionalHeaders(manifest_url_request_, + manifest_response_info_.get()); + manifest_url_request_->Start(); } } -void AppCacheUpdateJob::AddHttpHeadersAndFetch( +void AppCacheUpdateJob::AddConditionalHeaders( URLRequest* request, const net::HttpResponseInfo* info) { - DCHECK(request); - if (info) { - net::HttpRequestHeaders extra_headers; - - // Add If-Modified-Since header if response info has Last-Modified header. - const std::string last_modified = "Last-Modified"; - std::string last_modified_value; - info->headers->EnumerateHeader(NULL, last_modified, &last_modified_value); - if (!last_modified_value.empty()) { - extra_headers.SetHeader(net::HttpRequestHeaders::kIfModifiedSince, - last_modified_value); - } - - // Add If-None-Match header if resposne info has ETag header. - const std::string etag = "ETag"; - std::string etag_value; - info->headers->EnumerateHeader(NULL, etag, &etag_value); - if (!etag_value.empty()) { - extra_headers.SetHeader(net::HttpRequestHeaders::kIfNoneMatch, - etag_value); - } + DCHECK(request && info); + net::HttpRequestHeaders extra_headers; + + // Add If-Modified-Since header if response info has Last-Modified header. + const std::string last_modified = "Last-Modified"; + std::string last_modified_value; + info->headers->EnumerateHeader(NULL, last_modified, &last_modified_value); + if (!last_modified_value.empty()) { + extra_headers.SetHeader(net::HttpRequestHeaders::kIfModifiedSince, + last_modified_value); + } - if (!extra_headers.IsEmpty()) - request->SetExtraRequestHeaders(extra_headers); + // Add If-None-Match header if resposne info has ETag header. + const std::string etag = "ETag"; + std::string etag_value; + info->headers->EnumerateHeader(NULL, etag, &etag_value); + if (!etag_value.empty()) { + extra_headers.SetHeader(net::HttpRequestHeaders::kIfNoneMatch, + etag_value); } - request->Start(); + if (!extra_headers.IsEmpty()) + request->SetExtraRequestHeaders(extra_headers); } void AppCacheUpdateJob::OnResponseStarted(URLRequest *request) { @@ -330,8 +333,7 @@ void AppCacheUpdateJob::OnResponseStarted(URLRequest *request) { (request->GetResponseCode() / 100) == 2) { // Write response info to storage for URL fetches. Wait for async write // completion before reading any response data. - UpdateJobInfo* info = - static_cast<UpdateJobInfo*>(request->GetUserData(this)); + UpdateJobInfo* info = GetUpdateJobInfo(request); if (info->type_ == UpdateJobInfo::URL_FETCH || info->type_ == UpdateJobInfo::MASTER_ENTRY_FETCH) { info->SetUpResponseWriter( @@ -357,8 +359,7 @@ void AppCacheUpdateJob::ReadResponseData(URLRequest* request) { } int bytes_read = 0; - UpdateJobInfo* info = - static_cast<UpdateJobInfo*>(request->GetUserData(this)); + UpdateJobInfo* info = GetUpdateJobInfo(request); request->Read(info->buffer_, kBufferSize, &bytes_read); OnReadCompleted(request, bytes_read); } @@ -366,9 +367,7 @@ void AppCacheUpdateJob::ReadResponseData(URLRequest* request) { void AppCacheUpdateJob::OnReadCompleted(URLRequest* request, int bytes_read) { bool data_consumed = true; if (request->status().is_success() && bytes_read > 0) { - UpdateJobInfo* info = - static_cast<UpdateJobInfo*>(request->GetUserData(this)); - + UpdateJobInfo* info = GetUpdateJobInfo(request); data_consumed = ConsumeResponseData(request, info, bytes_read); if (data_consumed) { bytes_read = 0; @@ -439,8 +438,7 @@ void AppCacheUpdateJob::OnResponseCompleted(URLRequest* request) { return; } - UpdateJobInfo* info = - static_cast<UpdateJobInfo*>(request->GetUserData(this)); + UpdateJobInfo* info = GetUpdateJobInfo(request); switch (info->type_) { case UpdateJobInfo::MANIFEST_FETCH: HandleManifestFetchCompleted(request); @@ -462,8 +460,7 @@ void AppCacheUpdateJob::OnResponseCompleted(URLRequest* request) { } bool AppCacheUpdateJob::RetryRequest(URLRequest* request) { - UpdateJobInfo* info = - static_cast<UpdateJobInfo*>(request->GetUserData(this)); + UpdateJobInfo* info = GetUpdateJobInfo(request); if (info->retry_503_attempts_ >= kMax503Retries) { return false; } @@ -475,6 +472,7 @@ bool AppCacheUpdateJob::RetryRequest(URLRequest* request) { URLRequest* retry = new URLRequest(url, this); UpdateJobInfo* retry_info = new UpdateJobInfo(info->type_); retry_info->retry_503_attempts_ = info->retry_503_attempts_ + 1; + retry_info->existing_entry_ = info->existing_entry_; retry->SetUserData(this, retry_info); retry->set_context(request->context()); retry->set_load_flags(request->load_flags()); @@ -598,6 +596,7 @@ void AppCacheUpdateJob::ContinueHandleManifestFetchCompleted(bool changed) { void AppCacheUpdateJob::HandleUrlFetchCompleted(URLRequest* request) { DCHECK(internal_state_ == DOWNLOADING); + UpdateJobInfo* info = GetUpdateJobInfo(request); const GURL& url = request->original_url(); pending_url_fetches_.erase(url); @@ -608,14 +607,11 @@ void AppCacheUpdateJob::HandleUrlFetchCompleted(URLRequest* request) { ? request->GetResponseCode() : -1; AppCacheEntry& entry = url_file_list_.find(url)->second; - if (request->status().is_success() && (response_code / 100 == 2)) { + if (response_code / 100 == 2) { // Associate storage with the new entry. - UpdateJobInfo* info = - static_cast<UpdateJobInfo*>(request->GetUserData(this)); DCHECK(info->response_writer_.get()); entry.set_response_id(info->response_writer_->response_id()); entry.set_response_size(info->response_writer_->amount_written()); - if (!inprogress_cache_->AddOrModifyEntry(url, entry)) duplicate_response_ids_.push_back(entry.response_id()); @@ -629,22 +625,29 @@ void AppCacheUpdateJob::HandleUrlFetchCompleted(URLRequest* request) { << " os_error: " << request->status().os_error() << " response code: " << response_code; if (entry.IsExplicit() || entry.IsFallback()) { - const char* kFormatString = "Resource fetch failed (%d) %s"; - const std::string message = StringPrintf(kFormatString, response_code, - request->url().spec().c_str()); - HandleCacheFailure(message); - return; - } else if (response_code == 404 || response_code == 410) { - // Entry is skipped. They are dropped from the cache. - } else if (update_type_ == UPGRADE_ATTEMPT) { - // Copy the response from the newest complete cache. - AppCache* cache = group_->newest_complete_cache(); - AppCacheEntry* copy = cache->GetEntry(url); - if (copy) { - entry.set_response_id(copy->response_id()); - entry.set_response_size(copy->response_size()); + if (response_code == 304 && info->existing_entry_.has_response_id()) { + // Keep the existing response. + entry.set_response_id(info->existing_entry_.response_id()); + entry.set_response_size(info->existing_entry_.response_size()); inprogress_cache_->AddOrModifyEntry(url, entry); + } else { + const char* kFormatString = "Resource fetch failed (%d) %s"; + const std::string message = StringPrintf(kFormatString, response_code, + request->url().spec().c_str()); + HandleCacheFailure(message); + return; } + } else if (response_code == 404 || response_code == 410) { + // Entry is skipped. They are dropped from the cache. + } else if (update_type_ == UPGRADE_ATTEMPT && + info->existing_entry_.has_response_id()) { + // Keep the existing response. + // TODO(michaeln): Not sure this is a good idea. This is spec compliant + // but the old resource may or may not be compatible with the new contents + // of the cache. Impossible to know one way or the other. + entry.set_response_id(info->existing_entry_.response_id()); + entry.set_response_size(info->existing_entry_.response_size()); + inprogress_cache_->AddOrModifyEntry(url, entry); } } @@ -676,8 +679,7 @@ void AppCacheUpdateJob::HandleMasterEntryFetchCompleted(URLRequest* request) { // Section 6.9.4. No update case: step 7.3, else step 22. if (response_code / 100 == 2) { // Add fetched master entry to the appropriate cache. - UpdateJobInfo* info = - static_cast<UpdateJobInfo*>(request->GetUserData(this)); + UpdateJobInfo* info = GetUpdateJobInfo(request); AppCache* cache = inprogress_cache_ ? inprogress_cache_.get() : group_->newest_complete_cache(); DCHECK(info->response_writer_.get()); @@ -943,7 +945,7 @@ void AppCacheUpdateJob::AddUrlToFileList(const GURL& url, int type) { AppCache::EntryMap::value_type(url, AppCacheEntry(type))); if (ret.second) - urls_to_fetch_.push_back(UrlsToFetch(url, false)); + urls_to_fetch_.push_back(UrlToFetch(url, false, NULL)); else ret.first->second.add_types(type); // URL already exists. Merge types. } @@ -956,30 +958,46 @@ void AppCacheUpdateJob::FetchUrls() { // each fetch completes. while (pending_url_fetches_.size() < kMaxConcurrentUrlFetches && !urls_to_fetch_.empty()) { - const GURL url = urls_to_fetch_.front().first; - bool storage_checked = urls_to_fetch_.front().second; + UrlToFetch url_to_fetch = urls_to_fetch_.front(); urls_to_fetch_.pop_front(); - AppCache::EntryMap::iterator it = url_file_list_.find(url); + AppCache::EntryMap::iterator it = url_file_list_.find(url_to_fetch.url); DCHECK(it != url_file_list_.end()); AppCacheEntry& entry = it->second; if (ShouldSkipUrlFetch(entry)) { - NotifyAllProgress(url); + NotifyAllProgress(url_to_fetch.url); ++url_fetches_completed_; - } else if (AlreadyFetchedEntry(url, entry.types())) { - NotifyAllProgress(url); + } else if (AlreadyFetchedEntry(url_to_fetch.url, entry.types())) { + NotifyAllProgress(url_to_fetch.url); ++url_fetches_completed_; // saved a URL request - } else if (!storage_checked && MaybeLoadFromNewestCache(url, entry)) { + } else if (!url_to_fetch.storage_checked && + MaybeLoadFromNewestCache(url_to_fetch.url, entry)) { // Continues asynchronously after data is loaded from newest cache. } else { + UpdateJobInfo* info = new UpdateJobInfo(UpdateJobInfo::URL_FETCH); + const net::HttpResponseInfo* http_info = NULL; + if (url_to_fetch.existing_response_info.get()) { + DCHECK(group_->newest_complete_cache()); + AppCacheEntry* existing_entry = + group_->newest_complete_cache()->GetEntry(url_to_fetch.url); + DCHECK(existing_entry); + DCHECK(existing_entry->response_id() == + url_to_fetch.existing_response_info->response_id()); + info->existing_entry_ = *existing_entry; + http_info = url_to_fetch.existing_response_info->http_response_info(); + } + // Send URL request for the resource. - URLRequest* request = new URLRequest(url, this); - request->SetUserData(this, new UpdateJobInfo(UpdateJobInfo::URL_FETCH)); + URLRequest* request = new URLRequest(url_to_fetch.url, this); + request->SetUserData(this, info); request->set_context(service_->request_context()); request->set_load_flags( request->load_flags() | net::LOAD_DISABLE_INTERCEPT); + if (http_info) + AddConditionalHeaders(request, http_info); request->Start(); - pending_url_fetches_.insert(PendingUrlFetches::value_type(url, request)); + pending_url_fetches_.insert( + PendingUrlFetches::value_type(url_to_fetch.url, request)); } } } @@ -1161,7 +1179,9 @@ void AppCacheUpdateJob::OnResponseInfoLoaded( // Needed response info for a manifest fetch request. if (internal_state_ == FETCH_MANIFEST) { - AddHttpHeadersAndFetch(manifest_url_request_, http_info); + if (http_info) + AddConditionalHeaders(manifest_url_request_, http_info); + manifest_url_request_->Start(); return; } @@ -1170,7 +1190,7 @@ void AppCacheUpdateJob::OnResponseInfoLoaded( const GURL& url = found->second; if (!http_info) { - LoadFromNewestCacheFailed(url); // no response found + LoadFromNewestCacheFailed(url, NULL); // no response found } else { // Check if response can be re-used according to HTTP caching semantics. // Responses with a "vary" header get treated as expired. @@ -1182,7 +1202,7 @@ void AppCacheUpdateJob::OnResponseInfoLoaded( base::Time::Now()) || http_info->headers->EnumerateHeader(&iter, name, &value)) { // TODO(michaeln): Make a conditional request when we can in this case. - LoadFromNewestCacheFailed(url); + LoadFromNewestCacheFailed(url, response_info); } else { DCHECK(group_->newest_complete_cache()); AppCacheEntry* copy_me = group_->newest_complete_cache()->GetEntry(url); @@ -1204,12 +1224,13 @@ void AppCacheUpdateJob::OnResponseInfoLoaded( MaybeCompleteUpdate(); } -void AppCacheUpdateJob::LoadFromNewestCacheFailed(const GURL& url) { +void AppCacheUpdateJob::LoadFromNewestCacheFailed( + const GURL& url, AppCacheResponseInfo* response_info) { if (internal_state_ == CACHE_FAILURE) return; // Re-insert url at front of fetch list. Indicate storage has been checked. - urls_to_fetch_.push_front(AppCacheUpdateJob::UrlsToFetch(url, true)); + urls_to_fetch_.push_front(UrlToFetch(url, true, response_info)); FetchUrls(); } diff --git a/webkit/appcache/appcache_update_job.h b/webkit/appcache/appcache_update_job.h index d9c1669..ff6452c 100644 --- a/webkit/appcache/appcache_update_job.h +++ b/webkit/appcache/appcache_update_job.h @@ -20,6 +20,7 @@ #include "webkit/appcache/appcache.h" #include "webkit/appcache/appcache_host.h" #include "webkit/appcache/appcache_interfaces.h" +#include "webkit/appcache/appcache_response.h" #include "webkit/appcache/appcache_storage.h" namespace appcache { @@ -49,7 +50,6 @@ class AppCacheUpdateJob : public URLRequest::Delegate, typedef std::vector<AppCacheHost*> PendingHosts; typedef std::map<GURL, PendingHosts> PendingMasters; typedef std::map<GURL, URLRequest*> PendingUrlFetches; - typedef std::pair<GURL, bool> UrlsToFetch; // flag TRUE if storage checked typedef std::map<int64, GURL> LoadingResponses; static const int kRerunDelayMs = 1000; @@ -82,6 +82,16 @@ class AppCacheUpdateJob : public URLRequest::Delegate, STORED, }; + struct UrlToFetch { + GURL url; + bool storage_checked; + scoped_refptr<AppCacheResponseInfo> existing_response_info; + UrlToFetch(const GURL& url, bool checked, AppCacheResponseInfo* info) + : url(url), storage_checked(checked), existing_response_info(info) {} + }; + + UpdateJobInfo* GetUpdateJobInfo(URLRequest* request); + // Methods for URLRequest::Delegate. void OnResponseStarted(URLRequest* request); void OnReadCompleted(URLRequest* request, int bytes_read); @@ -108,10 +118,10 @@ class AppCacheUpdateJob : public URLRequest::Delegate, void FetchManifest(bool is_first_fetch); - // Add extra HTTP headers to the request based on the response info and - // start the URL request. - void AddHttpHeadersAndFetch(URLRequest* request, - const net::HttpResponseInfo* info); + // Add extra conditional HTTP headers to the request based on the + // currently cached response headers. + void AddConditionalHeaders(URLRequest* request, + const net::HttpResponseInfo* info); void OnResponseCompleted(URLRequest* request); @@ -180,7 +190,8 @@ class AppCacheUpdateJob : public URLRequest::Delegate, // Returns false if immediately obvious that data cannot be loaded from // newest complete cache. bool MaybeLoadFromNewestCache(const GURL& url, AppCacheEntry& entry); - void LoadFromNewestCacheFailed(const GURL& url); + void LoadFromNewestCacheFailed(const GURL& url, + AppCacheResponseInfo* newest_response_info); // Does nothing if update process is still waiting for pending master // entries or URL fetches to complete downloading. Otherwise, completes @@ -233,7 +244,7 @@ class AppCacheUpdateJob : public URLRequest::Delegate, // Helper container to track which urls have not been fetched yet. URLs are // removed when the fetch is initiated. Flag indicates whether an attempt // to load the URL from storage has already been tried and failed. - std::deque<UrlsToFetch> urls_to_fetch_; + std::deque<UrlToFetch> urls_to_fetch_; // Helper container to track which urls are being loaded from response // storage. diff --git a/webkit/appcache/appcache_update_job_unittest.cc b/webkit/appcache/appcache_update_job_unittest.cc index f90eb87..0bcda2c 100644 --- a/webkit/appcache/appcache_update_job_unittest.cc +++ b/webkit/appcache/appcache_update_job_unittest.cc @@ -105,6 +105,11 @@ class MockHttpServer { } else if (path == "/files/manifest1") { (*headers) = std::string(manifest_headers, arraysize(manifest_headers)); (*body) = kManifest1Contents; + } else if (path == "/files/manifest1-with-notmodified") { + (*headers) = std::string(manifest_headers, arraysize(manifest_headers)); + (*body) = kManifest1Contents; + (*body).append("CACHE:\n" + "notmodified\n"); } else if (path == "/files/manifest-fb-404") { (*headers) = std::string(manifest_headers, arraysize(manifest_headers)); (*body) = "CACHE MANIFEST\n" @@ -529,6 +534,7 @@ class AppCacheUpdateJobTest : public testing::Test, expect_newest_cache_(NULL), expect_non_null_update_time_(false), tested_manifest_(NONE), + tested_manifest1_path_override_(NULL), registered_factory_(false), old_factory_(NULL) { } @@ -1396,9 +1402,13 @@ class AppCacheUpdateJobTest : public testing::Test, void UpgradeFailMasterUrlFetchTest() { ASSERT_EQ(MessageLoop::TYPE_IO, MessageLoop::current()->type()); + tested_manifest1_path_override_ = "files/manifest1-with-notmodified"; + MakeService(); + const GURL kManifestUrl = + MockHttpServer::GetMockUrl(tested_manifest1_path_override_); group_ = new AppCacheGroup( - service_.get(), MockHttpServer::GetMockUrl("files/manifest1"), + service_.get(), kManifestUrl, service_->storage()->NewGroupId()); AppCacheUpdateJob* update = new AppCacheUpdateJob(service_.get(), group_); group_->update_job_ = update; @@ -1411,7 +1421,7 @@ class AppCacheUpdateJobTest : public testing::Test, host1->AssociateCache(cache); host2->AssociateCache(cache); - // Give the newest cache some master entries; one will fail with a 404. + // Give the newest cache some existing entries; one will fail with a 404. cache->AddEntry( MockHttpServer::GetMockUrl("files/notfound"), AppCacheEntry(AppCacheEntry::MASTER, 222)); @@ -1421,6 +1431,20 @@ class AppCacheUpdateJobTest : public testing::Test, cache->AddEntry( MockHttpServer::GetMockUrl("files/servererror"), AppCacheEntry(AppCacheEntry::MASTER, 444)); + cache->AddEntry( + MockHttpServer::GetMockUrl("files/notmodified"), + AppCacheEntry(AppCacheEntry::EXPLICIT, 555)); + + // Seed the response_info working set with canned data for + // files/servererror and for files/notmodified to test that the + // existing entries for those resource are reused by the update job. + const char kData[] = + "HTTP/1.1 200 OK\0" + "Last-Modified: Sat, 29 Oct 1994 19:43:31 GMT\0" + "\0"; + const std::string kRawHeaders(kData, arraysize(kData)); + MakeAppCacheResponseInfo(kManifestUrl, 444, kRawHeaders); + MakeAppCacheResponseInfo(kManifestUrl, 555, kRawHeaders); update->StartUpdate(NULL, GURL()); EXPECT_TRUE(update->manifest_url_request_ != NULL); @@ -1437,8 +1461,13 @@ class AppCacheUpdateJobTest : public testing::Test, expect_extra_entries_.insert(AppCache::EntryMap::value_type( MockHttpServer::GetMockUrl("files/servererror"), AppCacheEntry(AppCacheEntry::MASTER))); + expect_extra_entries_.insert(AppCache::EntryMap::value_type( + MockHttpServer::GetMockUrl("files/notmodified"), + AppCacheEntry(AppCacheEntry::EXPLICIT))); expect_response_ids_.insert(std::map<GURL, int64>::value_type( MockHttpServer::GetMockUrl("files/servererror"), 444)); // copied + expect_response_ids_.insert(std::map<GURL, int64>::value_type( + MockHttpServer::GetMockUrl("files/notmodified"), 555)); // copied MockFrontend::HostIds ids1(1, host1->host_id()); frontend1->AddExpectedEvent(ids1, CHECKING_EVENT); frontend1->AddExpectedEvent(ids1, DOWNLOADING_EVENT); @@ -1447,6 +1476,7 @@ class AppCacheUpdateJobTest : public testing::Test, frontend1->AddExpectedEvent(ids1, PROGRESS_EVENT); // notfound frontend1->AddExpectedEvent(ids1, PROGRESS_EVENT); // explicit2 frontend1->AddExpectedEvent(ids1, PROGRESS_EVENT); // servererror + frontend1->AddExpectedEvent(ids1, PROGRESS_EVENT); // notmodified frontend1->AddExpectedEvent(ids1, PROGRESS_EVENT); // final frontend1->AddExpectedEvent(ids1, UPDATE_READY_EVENT); MockFrontend::HostIds ids2(1, host2->host_id()); @@ -1457,6 +1487,7 @@ class AppCacheUpdateJobTest : public testing::Test, frontend2->AddExpectedEvent(ids2, PROGRESS_EVENT); // notfound frontend2->AddExpectedEvent(ids2, PROGRESS_EVENT); // explicit2 frontend2->AddExpectedEvent(ids2, PROGRESS_EVENT); // servererror + frontend2->AddExpectedEvent(ids2, PROGRESS_EVENT); // notmodified frontend2->AddExpectedEvent(ids2, PROGRESS_EVENT); // final frontend2->AddExpectedEvent(ids2, UPDATE_READY_EVENT); @@ -2773,6 +2804,7 @@ class AppCacheUpdateJobTest : public testing::Test, group_ = NULL; STLDeleteContainerPointers(hosts_.begin(), hosts_.end()); STLDeleteContainerPointers(frontends_.begin(), frontends_.end()); + response_infos_.clear(); service_.reset(NULL); if (registered_factory_) URLRequest::RegisterProtocolFactory("http", old_factory_); @@ -2805,6 +2837,18 @@ class AppCacheUpdateJobTest : public testing::Test, return host; } + AppCacheResponseInfo* MakeAppCacheResponseInfo( + const GURL& manifest_url, int64 response_id, + const std::string& raw_headers) { + net::HttpResponseInfo* http_info = new net::HttpResponseInfo(); + http_info->headers = new net::HttpResponseHeaders(raw_headers); + scoped_refptr<AppCacheResponseInfo> info = + new AppCacheResponseInfo(service_.get(), manifest_url, + response_id, http_info, 0); + response_infos_.push_back(info); + return info; + } + MockFrontend* MakeMockFrontend() { MockFrontend* frontend = new MockFrontend(); frontends_.push_back(frontend); @@ -2929,8 +2973,11 @@ class AppCacheUpdateJobTest : public testing::Test, void VerifyManifest1(AppCache* cache) { size_t expected = 3 + expect_extra_entries_.size(); EXPECT_EQ(expected, cache->entries().size()); + const char* kManifestPath = tested_manifest1_path_override_ ? + tested_manifest1_path_override_ : + "files/manifest1"; AppCacheEntry* entry = - cache->GetEntry(MockHttpServer::GetMockUrl("files/manifest1")); + cache->GetEntry(MockHttpServer::GetMockUrl(kManifestPath)); ASSERT_TRUE(entry); EXPECT_EQ(AppCacheEntry::MANIFEST, entry->types()); entry = cache->GetEntry(MockHttpServer::GetMockUrl("files/explicit1")); @@ -3083,6 +3130,10 @@ class AppCacheUpdateJobTest : public testing::Test, // Otherwise, test can put host on the stack instead of here. std::vector<AppCacheHost*> hosts_; + // Response infos used by an async test that need to live until update job + // finishes. + std::vector<scoped_refptr<AppCacheResponseInfo> > response_infos_; + // Flag indicating if test cares to verify the update after update finishes. bool do_checks_after_update_finished_; bool expect_group_obsolete_; @@ -3092,6 +3143,7 @@ class AppCacheUpdateJobTest : public testing::Test, bool expect_non_null_update_time_; std::vector<MockFrontend*> frontends_; // to check expected events TestedManifest tested_manifest_; + const char* tested_manifest1_path_override_; AppCache::EntryMap expect_extra_entries_; std::map<GURL, int64> expect_response_ids_; |