summaryrefslogtreecommitdiffstats
path: root/webkit/appcache
diff options
context:
space:
mode:
authormichaeln@google.com <michaeln@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2011-04-15 20:56:47 +0000
committermichaeln@google.com <michaeln@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2011-04-15 20:56:47 +0000
commitea2a7b919337fb796c8602f1701b60d8fa2d7f42 (patch)
tree61ab4cb64a4aa0c64e94a5280a7d7f4e35062855 /webkit/appcache
parentc468f9498bcb426edb87cb803a03a63e793e8222 (diff)
downloadchromium_src-ea2a7b919337fb796c8602f1701b60d8fa2d7f42.zip
chromium_src-ea2a7b919337fb796c8602f1701b60d8fa2d7f42.tar.gz
chromium_src-ea2a7b919337fb796c8602f1701b60d8fa2d7f42.tar.bz2
Select a more appropiate appcache based on the opener or the parent or the target frame of the new document. The change determines a 'preferred manifest url' in these cases:
* <iframe> loading, we prefer the parent frame's manifest url * window.open() loading, we prefer the opener frame's manifest url * href clicking to navigate a frame in place, we prefer the manifest url of the document in the frame when the navigation starts BUG=68479 Review URL: http://codereview.chromium.org/6727006 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@81801 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'webkit/appcache')
-rw-r--r--webkit/appcache/appcache_backend_impl.cc3
-rw-r--r--webkit/appcache/appcache_host.cc20
-rw-r--r--webkit/appcache/appcache_host.h23
-rw-r--r--webkit/appcache/appcache_host_unittest.cc1
-rw-r--r--webkit/appcache/appcache_request_handler.cc11
-rw-r--r--webkit/appcache/appcache_request_handler_unittest.cc11
-rw-r--r--webkit/appcache/appcache_service.cc4
-rw-r--r--webkit/appcache/appcache_storage.h4
-rw-r--r--webkit/appcache/appcache_storage_impl.cc288
-rw-r--r--webkit/appcache/appcache_storage_impl.h5
-rw-r--r--webkit/appcache/appcache_storage_impl_unittest.cc161
-rw-r--r--webkit/appcache/mock_appcache_storage.cc4
-rw-r--r--webkit/appcache/mock_appcache_storage.h3
-rw-r--r--webkit/appcache/mock_appcache_storage_unittest.cc14
-rw-r--r--webkit/appcache/web_application_cache_host_impl.cc15
-rw-r--r--webkit/appcache/web_application_cache_host_impl.h2
16 files changed, 428 insertions, 141 deletions
diff --git a/webkit/appcache/appcache_backend_impl.cc b/webkit/appcache/appcache_backend_impl.cc
index 8ada332..cbe557b 100644
--- a/webkit/appcache/appcache_backend_impl.cc
+++ b/webkit/appcache/appcache_backend_impl.cc
@@ -59,8 +59,7 @@ bool AppCacheBackendImpl::SetSpawningHostId(
AppCacheHost* host = GetHost(host_id);
if (!host)
return false;
- // TODO(michaeln): Write me, see the bug for details.
- // http://code.google.com/p/chromium/issues/detail?id=68479
+ host->SetSpawningHostId(process_id_, spawning_host_id);
return true;
}
diff --git a/webkit/appcache/appcache_host.cc b/webkit/appcache/appcache_host.cc
index 2bc463f..18809790 100644
--- a/webkit/appcache/appcache_host.cc
+++ b/webkit/appcache/appcache_host.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -33,7 +33,9 @@ void FillCacheInfo(
AppCacheHost::AppCacheHost(int host_id, AppCacheFrontend* frontend,
AppCacheService* service)
- : host_id_(host_id), parent_host_id_(kNoHostId), parent_process_id_(0),
+ : host_id_(host_id),
+ spawning_host_id_(kNoHostId), spawning_process_id_(0),
+ parent_host_id_(kNoHostId), parent_process_id_(0),
pending_main_resource_cache_id_(kNoCacheId),
pending_selected_cache_id_(kNoCacheId),
frontend_(frontend), service_(service),
@@ -89,6 +91,7 @@ void AppCacheHost::SelectCache(const GURL& document_url,
// Note: The client detects if the document was not loaded using HTTP GET
// and invokes SelectCache without a manifest url, so that detection step
// is also skipped here. See WebApplicationCacheHostImpl.cc
+ set_preferred_manifest_url(manifest_url);
new_master_entry_url_ = document_url;
LoadOrCreateGroup(manifest_url);
return;
@@ -230,6 +233,17 @@ void AppCacheHost::DoPendingSwapCache() {
pending_callback_param_ = NULL;
}
+void AppCacheHost::SetSpawningHostId(
+ int spawning_process_id, int spawning_host_id) {
+ spawning_process_id_ = spawning_process_id;
+ spawning_host_id_ = spawning_host_id;
+}
+
+const AppCacheHost* AppCacheHost::GetSpawningHost() const {
+ AppCacheBackendImpl* backend = service_->GetBackend(spawning_process_id_);
+ return backend ? backend->GetHost(spawning_host_id_) : NULL;
+}
+
AppCacheHost* AppCacheHost::GetParentAppCacheHost() const {
DCHECK(is_for_dedicated_worker());
AppCacheBackendImpl* backend = service_->GetBackend(parent_process_id_);
@@ -338,6 +352,7 @@ void AppCacheHost::FinishCacheSelection(
// context being navigated.
DCHECK(cache->owning_group());
DCHECK(new_master_entry_url_.is_empty());
+ DCHECK_EQ(cache->owning_group()->manifest_url(), preferred_manifest_url_);
AppCacheGroup* owing_group = cache->owning_group();
const char* kFormatString =
"Document was loaded from Application Cache with manifest %s";
@@ -358,6 +373,7 @@ void AppCacheHost::FinishCacheSelection(
// resource from which document was loaded as the new master resourse.
DCHECK(!group->is_obsolete());
DCHECK(new_master_entry_url_.is_valid());
+ DCHECK_EQ(group->manifest_url(), preferred_manifest_url_);
const char* kFormatString = group->HasCache() ?
"Adding master entry to Application Cache with manifest %s" :
"Creating Application Cache with manifest %s";
diff --git a/webkit/appcache/appcache_host.h b/webkit/appcache/appcache_host.h
index c449982..6f25a57 100644
--- a/webkit/appcache/appcache_host.h
+++ b/webkit/appcache/appcache_host.h
@@ -71,6 +71,22 @@ class AppCacheHost : public AppCacheStorage::Delegate,
void SwapCacheWithCallback(SwapCacheCallback* callback,
void* callback_param);
+ // Called prior to the main resource load. When the system contains multiple
+ // candidates for a main resource load, the appcache preferred by the host
+ // that created this host is used to break ties.
+ void SetSpawningHostId(int spawning_process_id, int spawning_host_id);
+
+ // May return NULL if the spawning host context has been closed, or if a
+ // spawning host context was never identified.
+ const AppCacheHost* GetSpawningHost() const;
+
+ const GURL& preferred_manifest_url() const {
+ return preferred_manifest_url_;
+ }
+ void set_preferred_manifest_url(const GURL& url) {
+ preferred_manifest_url_ = url;
+ }
+
// Support for loading resources out of the appcache.
// May return NULL if the request isn't subject to retrieval from an appache.
AppCacheRequestHandler* CreateRequestHandler(
@@ -149,6 +165,13 @@ class AppCacheHost : public AppCacheStorage::Delegate,
// Identifies the corresponding appcache host in the child process.
int host_id_;
+ // Information about the host that created this one; the manifest
+ // preferred by our creator influences which cache our main resource
+ // should be loaded from.
+ int spawning_host_id_;
+ int spawning_process_id_;
+ GURL preferred_manifest_url_;
+
// Hosts for dedicated workers are special cased to shunt
// request handling off to the dedicated worker's parent.
// The scriptable api is not accessible in dedicated workers
diff --git a/webkit/appcache/appcache_host_unittest.cc b/webkit/appcache/appcache_host_unittest.cc
index 2e36728..d648e07 100644
--- a/webkit/appcache/appcache_host_unittest.cc
+++ b/webkit/appcache/appcache_host_unittest.cc
@@ -156,6 +156,7 @@ TEST_F(AppCacheHostTest, SelectNoCache) {
EXPECT_EQ(&mock_frontend_, host.frontend());
EXPECT_EQ(NULL, host.associated_cache());
EXPECT_FALSE(host.is_selection_pending());
+ EXPECT_TRUE(host.preferred_manifest_url().is_empty());
}
TEST_F(AppCacheHostTest, ForeignEntry) {
diff --git a/webkit/appcache/appcache_request_handler.cc b/webkit/appcache/appcache_request_handler.cc
index a514517..064b378 100644
--- a/webkit/appcache/appcache_request_handler.cc
+++ b/webkit/appcache/appcache_request_handler.cc
@@ -188,11 +188,19 @@ void AppCacheRequestHandler::DeliverNetworkResponse() {
void AppCacheRequestHandler::MaybeLoadMainResource(net::URLRequest* request) {
DCHECK(!job_);
+ DCHECK(host_);
+
+ const AppCacheHost* spawning_host =
+ ResourceType::IsSharedWorker(resource_type_) ?
+ host_ : host_->GetSpawningHost();
+ GURL preferred_manifest_url = spawning_host ?
+ spawning_host->preferred_manifest_url() : GURL();
// We may have to wait for our storage query to complete, but
// this query can also complete syncrhonously.
job_ = new AppCacheURLRequestJob(request, storage());
- storage()->FindResponseForMainRequest(request->url(), this);
+ storage()->FindResponseForMainRequest(
+ request->url(), preferred_manifest_url, this);
}
void AppCacheRequestHandler::OnMainResponseFound(
@@ -216,6 +224,7 @@ void AppCacheRequestHandler::OnMainResponseFound(
// in advance of subresource loads happening, secondly to prevent the
// AppCache from falling out of the working set on frame navigations.
host_->LoadMainResourceCache(cache_id);
+ host_->set_preferred_manifest_url(manifest_url);
}
} else {
DCHECK(ResourceType::IsSharedWorker(resource_type_));
diff --git a/webkit/appcache/appcache_request_handler_unittest.cc b/webkit/appcache/appcache_request_handler_unittest.cc
index 0c41b00..c9fbe0e 100644
--- a/webkit/appcache/appcache_request_handler_unittest.cc
+++ b/webkit/appcache/appcache_request_handler_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -223,6 +223,8 @@ class AppCacheRequestHandlerTest : public testing::Test {
fallback_job = handler_->MaybeLoadFallbackForResponse(request_.get());
EXPECT_FALSE(fallback_job);
+ EXPECT_TRUE(host_->preferred_manifest_url().is_empty());
+
TestFinished();
}
@@ -264,6 +266,9 @@ class AppCacheRequestHandlerTest : public testing::Test {
fallback_job = handler_->MaybeLoadFallbackForResponse(request_.get());
EXPECT_FALSE(fallback_job);
+ EXPECT_EQ(GURL("http://blah/manifest/"),
+ host_->preferred_manifest_url());
+
TestFinished();
}
@@ -317,6 +322,9 @@ class AppCacheRequestHandlerTest : public testing::Test {
EXPECT_TRUE(host_->main_resource_was_fallback_);
EXPECT_EQ(GURL("http://blah/fallbackurl"), host_->fallback_url_);
+ EXPECT_EQ(GURL("http://blah/manifest/"),
+ host_->preferred_manifest_url());
+
TestFinished();
}
@@ -366,6 +374,7 @@ class AppCacheRequestHandlerTest : public testing::Test {
// Precondition, the host is waiting on cache selection.
scoped_refptr<AppCache> cache(MakeNewCache());
host_->pending_selected_cache_id_ = cache->cache_id();
+ host_->set_preferred_manifest_url(cache->owning_group()->manifest_url());
request_.reset(new MockURLRequest(GURL("http://blah/")));
handler_.reset(host_->CreateRequestHandler(request_.get(),
diff --git a/webkit/appcache/appcache_service.cc b/webkit/appcache/appcache_service.cc
index e748434..5e477ac 100644
--- a/webkit/appcache/appcache_service.cc
+++ b/webkit/appcache/appcache_service.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -73,7 +73,7 @@ class AppCacheService::CanHandleOfflineHelper : AsyncHelper {
}
virtual void Start() {
- service_->storage()->FindResponseForMainRequest(url_, this);
+ service_->storage()->FindResponseForMainRequest(url_, GURL(), this);
}
private:
diff --git a/webkit/appcache/appcache_storage.h b/webkit/appcache/appcache_storage.h
index 7d64d31..5672546 100644
--- a/webkit/appcache/appcache_storage.h
+++ b/webkit/appcache/appcache_storage.h
@@ -114,7 +114,9 @@ class AppCacheStorage {
// Schedules a query to identify a response for a main request. Upon
// completion the delegate will be called back.
virtual void FindResponseForMainRequest(
- const GURL& url, Delegate* delegate) = 0;
+ const GURL& url,
+ const GURL& preferred_manifest_url,
+ Delegate* delegate) = 0;
// Performs an immediate lookup of the in-memory cache to
// identify a response for a sub resource request.
diff --git a/webkit/appcache/appcache_storage_impl.cc b/webkit/appcache/appcache_storage_impl.cc
index 0f78b77..fe325a1 100644
--- a/webkit/appcache/appcache_storage_impl.cc
+++ b/webkit/appcache/appcache_storage_impl.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -509,12 +509,13 @@ void AppCacheStorageImpl::StoreGroupAndCacheTask::Run() {
void AppCacheStorageImpl::StoreGroupAndCacheTask::RunCompleted() {
if (success_) {
- // TODO(kkanetkar): Add to creation time when that's enabled.
storage_->origins_with_groups_.insert(group_->manifest_url().GetOrigin());
if (cache_ != group_->newest_complete_cache()) {
cache_->set_complete(true);
group_->AddCache(cache_);
}
+ if (group_->creation_time().is_null())
+ group_->set_creation_time(group_record_.creation_time);
group_->AddNewlyDeletableResponseIds(&newly_deletable_response_ids_);
}
FOR_EACH_DELEGATE(delegates_,
@@ -536,9 +537,13 @@ void AppCacheStorageImpl::StoreGroupAndCacheTask::CancelCompletion() {
class AppCacheStorageImpl::FindMainResponseTask : public DatabaseTask {
public:
- FindMainResponseTask(AppCacheStorageImpl* storage, const GURL& url,
+ FindMainResponseTask(AppCacheStorageImpl* storage,
+ const GURL& url,
+ const GURL& preferred_manifest_url,
const AppCacheWorkingSet::GroupMap* groups_in_use)
- : DatabaseTask(storage), url_(url), cache_id_(kNoCacheId) {
+ : DatabaseTask(storage), url_(url),
+ preferred_manifest_url_(preferred_manifest_url),
+ cache_id_(kNoCacheId) {
if (groups_in_use) {
for (AppCacheWorkingSet::GroupMap::const_iterator it =
groups_in_use->begin();
@@ -555,7 +560,15 @@ class AppCacheStorageImpl::FindMainResponseTask : public DatabaseTask {
virtual void Run();
virtual void RunCompleted();
+ private:
+ typedef std::vector<AppCacheDatabase::FallbackNameSpaceRecord*>
+ FallbackNameSpaceVector;
+ bool FindExactMatch(int64 preferred_id);
+ bool FindFallback(int64 preferred_id);
+ bool FindFirstValidFallback(const FallbackNameSpaceVector& fallbacks);
+
GURL url_;
+ GURL preferred_manifest_url_;
std::set<int64> cache_ids_in_use_;
AppCacheEntry entry_;
AppCacheEntry fallback_entry_;
@@ -566,6 +579,32 @@ class AppCacheStorageImpl::FindMainResponseTask : public DatabaseTask {
// Helpers for FindMainResponseTask::Run()
namespace {
+class SortByCachePreference
+ : public std::binary_function<
+ AppCacheDatabase::EntryRecord,
+ AppCacheDatabase::EntryRecord,
+ bool> {
+ public:
+ SortByCachePreference(int64 preferred_id, const std::set<int64>& in_use_ids)
+ : preferred_id_(preferred_id), in_use_ids_(in_use_ids) {
+ }
+ bool operator()(
+ const AppCacheDatabase::EntryRecord& lhs,
+ const AppCacheDatabase::EntryRecord& rhs) {
+ return compute_value(lhs) > compute_value(rhs);
+ }
+ private:
+ int compute_value(const AppCacheDatabase::EntryRecord& entry) {
+ if (entry.cache_id == preferred_id_)
+ return 100;
+ else if (in_use_ids_.find(entry.cache_id) != in_use_ids_.end())
+ return 50;
+ return 0;
+ }
+ int64 preferred_id_;
+ const std::set<int64>& in_use_ids_;
+};
+
bool SortByLength(
const AppCacheDatabase::FallbackNameSpaceRecord& lhs,
const AppCacheDatabase::FallbackNameSpaceRecord& rhs) {
@@ -609,99 +648,150 @@ class NetworkNamespaceHelper {
WhiteListMap namespaces_map_;
AppCacheDatabase* database_;
};
+
+bool FindManifestForEntry(
+ const AppCacheDatabase::EntryRecord& entry_record,
+ AppCacheDatabase* database,
+ GURL* manifest_url_out) {
+ AppCacheDatabase::GroupRecord group_record;
+ if (!database->FindGroupForCache(entry_record.cache_id, &group_record)) {
+ NOTREACHED() << "A cache without a group is not expected.";
+ return false;
+ }
+ *manifest_url_out = group_record.manifest_url;
+ return true;
+}
+
} // namespace
void AppCacheStorageImpl::FindMainResponseTask::Run() {
- // We have a bias for hits from caches that are in use.
-
- // TODO(michaeln): The heuristics around choosing amoungst
- // multiple candidates is under specified, and just plain
- // not fully understood. Refine these over time. In particular,
- // * prefer candidates from newer caches
- // * take into account the cache associated with the document
- // that initiated the navigation
- // * take into account the cache associated with the document
- // currently residing in the frame being navigated
-
- // First look for an exact match. We don't worry about whether
- // the containing cache is in-use in this loop because the
- // storage class's FindResponseForMainRequest method does that
- // as a pre-optimization.
+ // NOTE: The heuristics around choosing amoungst multiple candidates
+ // is underspecified, and just plain not fully understood. This needs
+ // to be refined.
+
+ // The 'preferred_manifest_url' is the url of the manifest associated
+ // with the page that opened or embedded the page being loaded now.
+ // We have a strong preference to use resources from that cache.
+ // We also have a lesser bias to use resources from caches that are currently
+ // being used by other unrelated pages.
+ // TODO(michaeln): come up with a 'preferred_manifest_url' in more cases
+ // - when navigating a frame whose current contents are from an appcache
+ // - when clicking an href in a frame that is appcached
+ int64 preferred_cache_id = kNoCacheId;
+ if (!preferred_manifest_url_.is_empty()) {
+ AppCacheDatabase::GroupRecord preferred_group;
+ AppCacheDatabase::CacheRecord preferred_cache;
+ if (database_->FindGroupForManifestUrl(
+ preferred_manifest_url_, &preferred_group) &&
+ database_->FindCacheForGroup(
+ preferred_group.group_id, &preferred_cache)) {
+ preferred_cache_id = preferred_cache.cache_id;
+ }
+ }
+
+ if (FindExactMatch(preferred_cache_id) ||
+ FindFallback(preferred_cache_id)) {
+ // We found something.
+ DCHECK(cache_id_ != kNoCacheId && !manifest_url_.is_empty());
+ return;
+ }
+
+ // We didn't find anything.
+ DCHECK(cache_id_ == kNoCacheId && manifest_url_.is_empty());
+}
+
+bool AppCacheStorageImpl::
+FindMainResponseTask::FindExactMatch(int64 preferred_cache_id) {
std::vector<AppCacheDatabase::EntryRecord> entries;
if (database_->FindEntriesForUrl(url_, &entries) && !entries.empty()) {
+ // Sort them in order of preference, from the preferred_cache first,
+ // followed by hits from caches that are 'in use', then the rest.
+ std::sort(entries.begin(), entries.end(),
+ SortByCachePreference(preferred_cache_id, cache_ids_in_use_));
+
+ // Take the first with a valid, non-foreign entry.
std::vector<AppCacheDatabase::EntryRecord>::iterator iter;
for (iter = entries.begin(); iter < entries.end(); ++iter) {
- if (iter->flags & AppCacheEntry::FOREIGN)
- continue;
-
- AppCacheDatabase::GroupRecord group_record;
- if (!database_->FindGroupForCache(iter->cache_id, &group_record)) {
- NOTREACHED() << "A cache without a group is not expected.";
+ if ((iter->flags & AppCacheEntry::FOREIGN) ||
+ !FindManifestForEntry(*iter, database_, &manifest_url_)) {
continue;
}
entry_ = AppCacheEntry(iter->flags, iter->response_id);
cache_id_ = iter->cache_id;
- manifest_url_ = group_record.manifest_url;
- return;
+ return true; // We found an exact match.
}
}
+ return false;
+}
- // No exact matches, look at the fallback namespaces for this origin.
- std::vector<AppCacheDatabase::FallbackNameSpaceRecord> fallbacks;
- if (!database_->FindFallbackNameSpacesForOrigin(url_.GetOrigin(), &fallbacks)
- || fallbacks.empty()) {
- return;
+bool AppCacheStorageImpl::
+FindMainResponseTask::FindFallback(int64 preferred_cache_id) {
+ std::vector<AppCacheDatabase::FallbackNameSpaceRecord> all_fallbacks;
+ if (!database_->FindFallbackNameSpacesForOrigin(
+ url_.GetOrigin(), &all_fallbacks)
+ || all_fallbacks.empty()) {
+ return false;
}
- // Sort by namespace url string length, longest to shortest,
- // since longer matches trump when matching a url to a namespace.
- std::sort(fallbacks.begin(), fallbacks.end(), SortByLength);
+ // Sort them by length, longer matches within the same cache/bucket take
+ // precedence.
+ std::sort(all_fallbacks.begin(), all_fallbacks.end(), SortByLength);
- bool has_candidate = false;
- GURL candidate_fallback_namespace;
- std::vector<AppCacheDatabase::FallbackNameSpaceRecord>::iterator iter;
+ // Filter the list and bin them into buckets.
NetworkNamespaceHelper network_namespace_helper(database_);
- for (iter = fallbacks.begin(); iter < fallbacks.end(); ++iter) {
- // Skip this fallback namespace if the requested url falls into a network
- // namespace of the containing appcache.
- if (network_namespace_helper.IsInNetworkNamespace(url_, iter->cache_id))
+ FallbackNameSpaceVector preferred_fallbacks;
+ FallbackNameSpaceVector inuse_fallbacks;
+ FallbackNameSpaceVector other_fallbacks;
+ std::vector<AppCacheDatabase::FallbackNameSpaceRecord>::iterator iter;
+ for (iter = all_fallbacks.begin(); iter < all_fallbacks.end(); ++iter) {
+ // Skip those that aren't a prefix match.
+ if (!StartsWithASCII(url_.spec(), iter->namespace_url.spec(), true))
continue;
- if (has_candidate &&
- (candidate_fallback_namespace.spec().length() >
- iter->namespace_url.spec().length())) {
- break; // Stop iterating since longer namespace prefix matches win.
- }
-
- if (StartsWithASCII(url_.spec(), iter->namespace_url.spec(), true)) {
- bool is_cache_in_use = cache_ids_in_use_.find(iter->cache_id) !=
- cache_ids_in_use_.end();
+ // Skip fallback namespaces where the requested url falls into a network
+ // namespace of its containing appcache.
+ if (network_namespace_helper.IsInNetworkNamespace(url_, iter->cache_id))
+ continue;
- bool take_new_candidate = !has_candidate || is_cache_in_use;
+ // Bin them into one of our three buckets.
+ if (iter->cache_id == preferred_cache_id)
+ preferred_fallbacks.push_back(&(*iter));
+ else if (cache_ids_in_use_.find(iter->cache_id) != cache_ids_in_use_.end())
+ inuse_fallbacks.push_back(&(*iter));
+ else
+ other_fallbacks.push_back(&(*iter));
+ }
- AppCacheDatabase::EntryRecord entry_record;
- if (take_new_candidate &&
- database_->FindEntry(iter->cache_id, iter->fallback_entry_url,
- &entry_record)) {
- if (entry_record.flags & AppCacheEntry::FOREIGN)
- continue;
- AppCacheDatabase::GroupRecord group_record;
- if (!database_->FindGroupForCache(iter->cache_id, &group_record)) {
- NOTREACHED() << "A cache without a group is not expected.";
- continue;
- }
- cache_id_ = iter->cache_id;
- fallback_url_ = iter->fallback_entry_url;
- manifest_url_ = group_record.manifest_url;
- fallback_entry_ = AppCacheEntry(
- entry_record.flags, entry_record.response_id);
- if (is_cache_in_use)
- break; // Stop iterating since we favor hits from in-use caches.
- candidate_fallback_namespace = iter->namespace_url;
- has_candidate = true;
+ if (FindFirstValidFallback(preferred_fallbacks) ||
+ FindFirstValidFallback(inuse_fallbacks) ||
+ FindFirstValidFallback(other_fallbacks))
+ return true; // We found one.
+
+ // We didn't find anything.
+ return false;
+}
+
+bool AppCacheStorageImpl::
+FindMainResponseTask::FindFirstValidFallback(
+ const FallbackNameSpaceVector& fallbacks) {
+ // Take the first with a valid, non-foreign entry.
+ FallbackNameSpaceVector::const_iterator iter;
+ for (iter = fallbacks.begin(); iter < fallbacks.end(); ++iter) {
+ AppCacheDatabase::EntryRecord entry_record;
+ if (database_->FindEntry((*iter)->cache_id, (*iter)->fallback_entry_url,
+ &entry_record)) {
+ if ((entry_record.flags & AppCacheEntry::FOREIGN) ||
+ !FindManifestForEntry(entry_record, database_, &manifest_url_)) {
+ continue;
}
+ cache_id_ = (*iter)->cache_id;
+ fallback_url_ = (*iter)->fallback_entry_url;
+ fallback_entry_ = AppCacheEntry(
+ entry_record.flags, entry_record.response_id);
+ return true; // We found one.
}
}
+ return false; // We didn't find a match.
}
void AppCacheStorageImpl::FindMainResponseTask::RunCompleted() {
@@ -1038,7 +1128,8 @@ void AppCacheStorageImpl::StoreGroupAndNewestCache(
}
void AppCacheStorageImpl::FindResponseForMainRequest(
- const GURL& url, Delegate* delegate) {
+ const GURL& url, const GURL& preferred_manifest_url,
+ Delegate* delegate) {
DCHECK(delegate);
const GURL* url_ptr = &url;
@@ -1057,21 +1148,22 @@ void AppCacheStorageImpl::FindResponseForMainRequest(
const AppCacheWorkingSet::GroupMap* groups_in_use =
working_set()->GetGroupsInOrigin(origin);
if (groups_in_use) {
- for (AppCacheWorkingSet::GroupMap::const_iterator it =
- groups_in_use->begin();
- it != groups_in_use->end(); ++it) {
- AppCacheGroup* group = it->second;
- AppCache* cache = group->newest_complete_cache();
- if (group->is_obsolete() || !cache)
- continue;
-
- AppCacheEntry* entry = cache->GetEntry(*url_ptr);
- if (entry && !entry->IsForeign()) {
- ScheduleSimpleTask(method_factory_.NewRunnableMethod(
- &AppCacheStorageImpl::DeliverShortCircuitedFindMainResponse,
- url, *entry, make_scoped_refptr(group), make_scoped_refptr(cache),
- make_scoped_refptr(GetOrCreateDelegateReference(delegate))));
- return;
+ if (!preferred_manifest_url.is_empty()) {
+ AppCacheWorkingSet::GroupMap::const_iterator found =
+ groups_in_use->find(preferred_manifest_url);
+ if (found != groups_in_use->end() &&
+ FindResponseForMainRequestInGroup(
+ found->second, *url_ptr, delegate)) {
+ return;
+ }
+ } else {
+ for (AppCacheWorkingSet::GroupMap::const_iterator it =
+ groups_in_use->begin();
+ it != groups_in_use->end(); ++it) {
+ if (FindResponseForMainRequestInGroup(
+ it->second, *url_ptr, delegate)) {
+ return;
+ }
}
}
}
@@ -1091,11 +1183,29 @@ void AppCacheStorageImpl::FindResponseForMainRequest(
// We have to query the database, schedule a database task to do so.
scoped_refptr<FindMainResponseTask> task(
- new FindMainResponseTask(this, *url_ptr, groups_in_use));
+ new FindMainResponseTask(this, *url_ptr, preferred_manifest_url,
+ groups_in_use));
task->AddDelegate(GetOrCreateDelegateReference(delegate));
task->Schedule();
}
+bool AppCacheStorageImpl::FindResponseForMainRequestInGroup(
+ AppCacheGroup* group, const GURL& url, Delegate* delegate) {
+ AppCache* cache = group->newest_complete_cache();
+ if (group->is_obsolete() || !cache)
+ return false;
+
+ AppCacheEntry* entry = cache->GetEntry(url);
+ if (!entry || entry->IsForeign())
+ return false;
+
+ ScheduleSimpleTask(method_factory_.NewRunnableMethod(
+ &AppCacheStorageImpl::DeliverShortCircuitedFindMainResponse,
+ url, *entry, make_scoped_refptr(group), make_scoped_refptr(cache),
+ make_scoped_refptr(GetOrCreateDelegateReference(delegate))));
+ return true;
+}
+
void AppCacheStorageImpl::DeliverShortCircuitedFindMainResponse(
const GURL& url, AppCacheEntry found_entry,
scoped_refptr<AppCacheGroup> group, scoped_refptr<AppCache> cache,
diff --git a/webkit/appcache/appcache_storage_impl.h b/webkit/appcache/appcache_storage_impl.h
index dc49053d..cd54a86 100644
--- a/webkit/appcache/appcache_storage_impl.h
+++ b/webkit/appcache/appcache_storage_impl.h
@@ -35,7 +35,8 @@ class AppCacheStorageImpl : public AppCacheStorage {
virtual void LoadOrCreateGroup(const GURL& manifest_url, Delegate* delegate);
virtual void StoreGroupAndNewestCache(
AppCacheGroup* group, AppCache* newest_cache, Delegate* delegate);
- virtual void FindResponseForMainRequest(const GURL& url, Delegate* delegate);
+ virtual void FindResponseForMainRequest(
+ const GURL& url, const GURL& preferred_manifest_url, Delegate* delegate);
virtual void FindResponseForSubRequest(
AppCache* cache, const GURL& url,
AppCacheEntry* found_entry, AppCacheEntry* found_fallback_entry,
@@ -101,6 +102,8 @@ class AppCacheStorageImpl : public AppCacheStorage {
void OnDiskCacheInitialized(int rv);
// Sometimes we can respond without having to query the database.
+ bool FindResponseForMainRequestInGroup(
+ AppCacheGroup* group, const GURL& url, Delegate* delegate);
void DeliverShortCircuitedFindMainResponse(
const GURL& url, AppCacheEntry found_entry,
scoped_refptr<AppCacheGroup> group, scoped_refptr<AppCache> newest_cache,
diff --git a/webkit/appcache/appcache_storage_impl_unittest.cc b/webkit/appcache/appcache_storage_impl_unittest.cc
index 1d874bc..af87b08 100644
--- a/webkit/appcache/appcache_storage_impl_unittest.cc
+++ b/webkit/appcache/appcache_storage_impl_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -25,6 +25,7 @@ namespace {
const base::Time kZeroTime;
const GURL kManifestUrl("http://blah/manifest");
const GURL kManifestUrl2("http://blah/manifest2");
+const GURL kManifestUrl3("http://blah/manifest3");
const GURL kEntryUrl("http://blah/entry");
const GURL kEntryUrl2("http://blah/entry2");
const GURL kFallbackNamespace("http://blah/fallback_namespace/");
@@ -34,6 +35,9 @@ const GURL kOnlineNamespace("http://blah/online_namespace");
const GURL kOnlineNamespaceWithinFallback(
"http://blah/fallback_namespace/online/");
+const int kManifestEntryIdOffset = 100;
+const int kFallbackEntryIdOffset = 1000;
+
// For the duration of this test case, we hijack the AppCacheThread API
// calls and implement them in terms of the io and db threads created here.
@@ -723,7 +727,7 @@ class AppCacheStorageImplTest : public testing::Test {
this, &AppCacheStorageImplTest::Verify_FindNoMainResponse));
// Conduct the test.
- storage()->FindResponseForMainRequest(kEntryUrl, delegate());
+ storage()->FindResponseForMainRequest(kEntryUrl, GURL(), delegate());
EXPECT_NE(kEntryUrl, delegate()->found_url_);
}
@@ -783,7 +787,7 @@ class AppCacheStorageImplTest : public testing::Test {
}
// Conduct the test.
- storage()->FindResponseForMainRequest(kEntryUrl, delegate());
+ storage()->FindResponseForMainRequest(kEntryUrl, GURL(), delegate());
EXPECT_NE(kEntryUrl, delegate()->found_url_);
}
@@ -844,7 +848,7 @@ class AppCacheStorageImplTest : public testing::Test {
// Conduct the test. The test url is in both fallback namespace urls,
// but should match the longer of the two.
- storage()->FindResponseForMainRequest(kFallbackTestUrl, delegate());
+ storage()->FindResponseForMainRequest(kFallbackTestUrl, GURL(), delegate());
EXPECT_NE(kFallbackTestUrl, delegate()->found_url_);
}
@@ -866,37 +870,98 @@ class AppCacheStorageImplTest : public testing::Test {
PushNextTask(NewRunnableMethod(this,
&AppCacheStorageImplTest::Verify_FindMainResponseWithMultipleHits));
- // Setup some preconditions. Create 2 complete caches with an entry
- // for the same url.
+ // Setup some preconditions, create a few caches with an identical set
+ // of entries and fallback namespaces. Only the last one remains in
+ // the working set to simulate appearing as "in use".
+ MakeMultipleHitCacheAndGroup(kManifestUrl, 1);
+ MakeMultipleHitCacheAndGroup(kManifestUrl2, 2);
+ MakeMultipleHitCacheAndGroup(kManifestUrl3, 3);
- // The first cache, in the database but not in the working set.
- MakeCacheAndGroup(kManifestUrl, 1, 1, true);
- cache_->AddEntry(kEntryUrl, AppCacheEntry(AppCacheEntry::EXPLICIT, 1));
+ // Conduct the test, we should find the response from the last cache
+ // since it's "in use".
+ storage()->FindResponseForMainRequest(kEntryUrl, GURL(), delegate());
+ EXPECT_NE(kEntryUrl, delegate()->found_url_);
+ }
+
+ void MakeMultipleHitCacheAndGroup(const GURL& manifest_url, int id) {
+ MakeCacheAndGroup(manifest_url, id, id, true);
AppCacheDatabase::EntryRecord entry_record;
- entry_record.cache_id = 1;
+
+ // Add an entry for kEntryUrl
+ entry_record.cache_id = id;
entry_record.url = kEntryUrl;
entry_record.flags = AppCacheEntry::EXPLICIT;
- entry_record.response_id = 1;
+ entry_record.response_id = id;
EXPECT_TRUE(database()->InsertEntry(&entry_record));
- cache_ = NULL;
- group_ = NULL;
+ cache_->AddEntry(
+ entry_record.url,
+ AppCacheEntry(entry_record.flags, entry_record.response_id));
+
+ // Add an entry for the manifestUrl
+ entry_record.cache_id = id;
+ entry_record.url = manifest_url;
+ entry_record.flags = AppCacheEntry::MANIFEST;
+ entry_record.response_id = id + kManifestEntryIdOffset;
+ EXPECT_TRUE(database()->InsertEntry(&entry_record));
+ cache_->AddEntry(
+ entry_record.url,
+ AppCacheEntry(entry_record.flags, entry_record.response_id));
- // The second cache, in the database and working set.
- MakeCacheAndGroup(kManifestUrl2, 2, 2, true);
- cache_->AddEntry(kEntryUrl, AppCacheEntry(AppCacheEntry::EXPLICIT, 2));
- entry_record.cache_id = 2;
- entry_record.url = kEntryUrl;
- entry_record.flags = AppCacheEntry::EXPLICIT;
- entry_record.response_id = 2;
+ // Add a fallback entry and namespace
+ entry_record.cache_id = id;
+ entry_record.url = kEntryUrl2;
+ entry_record.flags = AppCacheEntry::FALLBACK;
+ entry_record.response_id = id + kFallbackEntryIdOffset;
EXPECT_TRUE(database()->InsertEntry(&entry_record));
+ cache_->AddEntry(
+ entry_record.url,
+ AppCacheEntry(entry_record.flags, entry_record.response_id));
+ AppCacheDatabase::FallbackNameSpaceRecord fallback_namespace_record;
+ fallback_namespace_record.cache_id = id;
+ fallback_namespace_record.fallback_entry_url = entry_record.url;
+ fallback_namespace_record.namespace_url = kFallbackNamespace;
+ fallback_namespace_record.origin = manifest_url.GetOrigin();
+ EXPECT_TRUE(
+ database()->InsertFallbackNameSpace(&fallback_namespace_record));
+ cache_->fallback_namespaces_.push_back(
+ FallbackNamespace(kFallbackNamespace, kEntryUrl2));
+ }
- // Conduct the test, we should find the response from the second cache
- // since it's "in use".
- storage()->FindResponseForMainRequest(kEntryUrl, delegate());
+ void Verify_FindMainResponseWithMultipleHits() {
+ EXPECT_EQ(kEntryUrl, delegate()->found_url_);
+ EXPECT_EQ(kManifestUrl3, delegate()->found_manifest_url_);
+ EXPECT_FALSE(delegate()->found_blocked_by_policy_);
+ EXPECT_EQ(3, delegate()->found_cache_id_);
+ EXPECT_EQ(3, delegate()->found_entry_.response_id());
+ EXPECT_TRUE(delegate()->found_entry_.IsExplicit());
+ EXPECT_FALSE(delegate()->found_fallback_entry_.has_response_id());
+
+ // Conduct another test perferring kManifestUrl
+ delegate_.reset(new MockStorageDelegate(this));
+ PushNextTask(NewRunnableMethod(this,
+ &AppCacheStorageImplTest::Verify_FindMainResponseWithMultipleHits2));
+ storage()->FindResponseForMainRequest(kEntryUrl, kManifestUrl, delegate());
EXPECT_NE(kEntryUrl, delegate()->found_url_);
}
- void Verify_FindMainResponseWithMultipleHits() {
+ void Verify_FindMainResponseWithMultipleHits2() {
+ EXPECT_EQ(kEntryUrl, delegate()->found_url_);
+ EXPECT_EQ(kManifestUrl, delegate()->found_manifest_url_);
+ EXPECT_FALSE(delegate()->found_blocked_by_policy_);
+ EXPECT_EQ(1, delegate()->found_cache_id_);
+ EXPECT_EQ(1, delegate()->found_entry_.response_id());
+ EXPECT_TRUE(delegate()->found_entry_.IsExplicit());
+ EXPECT_FALSE(delegate()->found_fallback_entry_.has_response_id());
+
+ // Conduct the another test perferring kManifestUrl2
+ delegate_.reset(new MockStorageDelegate(this));
+ PushNextTask(NewRunnableMethod(this,
+ &AppCacheStorageImplTest::Verify_FindMainResponseWithMultipleHits3));
+ storage()->FindResponseForMainRequest(kEntryUrl, kManifestUrl2, delegate());
+ EXPECT_NE(kEntryUrl, delegate()->found_url_);
+ }
+
+ void Verify_FindMainResponseWithMultipleHits3() {
EXPECT_EQ(kEntryUrl, delegate()->found_url_);
EXPECT_EQ(kManifestUrl2, delegate()->found_manifest_url_);
EXPECT_FALSE(delegate()->found_blocked_by_policy_);
@@ -904,6 +969,47 @@ class AppCacheStorageImplTest : public testing::Test {
EXPECT_EQ(2, delegate()->found_entry_.response_id());
EXPECT_TRUE(delegate()->found_entry_.IsExplicit());
EXPECT_FALSE(delegate()->found_fallback_entry_.has_response_id());
+
+ // Conduct another test with no preferred manifest that hits the fallback.
+ delegate_.reset(new MockStorageDelegate(this));
+ PushNextTask(NewRunnableMethod(this,
+ &AppCacheStorageImplTest::Verify_FindMainResponseWithMultipleHits4));
+ storage()->FindResponseForMainRequest(
+ kFallbackTestUrl, GURL(), delegate());
+ EXPECT_NE(kFallbackTestUrl, delegate()->found_url_);
+ }
+
+ void Verify_FindMainResponseWithMultipleHits4() {
+ EXPECT_EQ(kFallbackTestUrl, delegate()->found_url_);
+ EXPECT_EQ(kManifestUrl3, delegate()->found_manifest_url_);
+ EXPECT_FALSE(delegate()->found_blocked_by_policy_);
+ EXPECT_EQ(3, delegate()->found_cache_id_);
+ EXPECT_FALSE(delegate()->found_entry_.has_response_id());
+ EXPECT_EQ(3 + kFallbackEntryIdOffset,
+ delegate()->found_fallback_entry_.response_id());
+ EXPECT_TRUE(delegate()->found_fallback_entry_.IsFallback());
+ EXPECT_EQ(kEntryUrl2, delegate()->found_fallback_url_);
+
+ // Conduct another test preferring kManifestUrl2 that hits the fallback.
+ delegate_.reset(new MockStorageDelegate(this));
+ PushNextTask(NewRunnableMethod(this,
+ &AppCacheStorageImplTest::Verify_FindMainResponseWithMultipleHits5));
+ storage()->FindResponseForMainRequest(
+ kFallbackTestUrl, kManifestUrl2, delegate());
+ EXPECT_NE(kFallbackTestUrl, delegate()->found_url_);
+ }
+
+ void Verify_FindMainResponseWithMultipleHits5() {
+ EXPECT_EQ(kFallbackTestUrl, delegate()->found_url_);
+ EXPECT_EQ(kManifestUrl2, delegate()->found_manifest_url_);
+ EXPECT_FALSE(delegate()->found_blocked_by_policy_);
+ EXPECT_EQ(2, delegate()->found_cache_id_);
+ EXPECT_FALSE(delegate()->found_entry_.has_response_id());
+ EXPECT_EQ(2 + kFallbackEntryIdOffset,
+ delegate()->found_fallback_entry_.response_id());
+ EXPECT_TRUE(delegate()->found_fallback_entry_.IsFallback());
+ EXPECT_EQ(kEntryUrl2, delegate()->found_fallback_url_);
+
TestFinished();
}
@@ -961,7 +1067,7 @@ class AppCacheStorageImplTest : public testing::Test {
PushNextTask(NewRunnableMethod(
this, &AppCacheStorageImplTest::Verify_ExclusionNotFound,
kEntryUrl, 1));
- storage()->FindResponseForMainRequest(kEntryUrl, delegate());
+ storage()->FindResponseForMainRequest(kEntryUrl, GURL(), delegate());
}
void Verify_ExclusionNotFound(GURL expected_url, int phase) {
@@ -980,7 +1086,8 @@ class AppCacheStorageImplTest : public testing::Test {
PushNextTask(NewRunnableMethod(this,
&AppCacheStorageImplTest::Verify_ExclusionNotFound,
kOnlineNamespace, 2));
- storage()->FindResponseForMainRequest(kOnlineNamespace, delegate());
+ storage()->FindResponseForMainRequest(
+ kOnlineNamespace, GURL(), delegate());
return;
}
if (phase == 2) {
@@ -990,7 +1097,7 @@ class AppCacheStorageImplTest : public testing::Test {
&AppCacheStorageImplTest::Verify_ExclusionNotFound,
kOnlineNamespaceWithinFallback, 3));
storage()->FindResponseForMainRequest(
- kOnlineNamespaceWithinFallback, delegate());
+ kOnlineNamespaceWithinFallback, GURL(), delegate());
return;
}
diff --git a/webkit/appcache/mock_appcache_storage.cc b/webkit/appcache/mock_appcache_storage.cc
index 73ae6c9..98af9bf 100644
--- a/webkit/appcache/mock_appcache_storage.cc
+++ b/webkit/appcache/mock_appcache_storage.cc
@@ -83,9 +83,11 @@ void MockAppCacheStorage::StoreGroupAndNewestCache(
}
void MockAppCacheStorage::FindResponseForMainRequest(
- const GURL& url, Delegate* delegate) {
+ const GURL& url, const GURL& preferred_manifest_url, Delegate* delegate) {
DCHECK(delegate);
+ // Note: MockAppCacheStorage does not respect the preferred_manifest_url.
+
// Always make this operation look async.
ScheduleTask(method_factory_.NewRunnableMethod(
&MockAppCacheStorage::ProcessFindResponseForMainRequest,
diff --git a/webkit/appcache/mock_appcache_storage.h b/webkit/appcache/mock_appcache_storage.h
index c808610..ea3ca1f 100644
--- a/webkit/appcache/mock_appcache_storage.h
+++ b/webkit/appcache/mock_appcache_storage.h
@@ -34,7 +34,8 @@ class MockAppCacheStorage : public AppCacheStorage {
virtual void LoadOrCreateGroup(const GURL& manifest_url, Delegate* delegate);
virtual void StoreGroupAndNewestCache(
AppCacheGroup* group, AppCache* newest_cache, Delegate* delegate);
- virtual void FindResponseForMainRequest(const GURL& url, Delegate* delegate);
+ virtual void FindResponseForMainRequest(
+ const GURL& url, const GURL& preferred_manifest_url, Delegate* delegate);
virtual void FindResponseForSubRequest(
AppCache* cache, const GURL& url,
AppCacheEntry* found_entry, AppCacheEntry* found_fallback_entry,
diff --git a/webkit/appcache/mock_appcache_storage_unittest.cc b/webkit/appcache/mock_appcache_storage_unittest.cc
index 2be8642..d04a896 100644
--- a/webkit/appcache/mock_appcache_storage_unittest.cc
+++ b/webkit/appcache/mock_appcache_storage_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -394,7 +394,7 @@ TEST_F(MockAppCacheStorageTest, FindNoMainResponse) {
MockStorageDelegate delegate;
GURL url("http://blah/some_url");
EXPECT_NE(url, delegate.found_url_);
- storage->FindResponseForMainRequest(url, &delegate);
+ storage->FindResponseForMainRequest(url, GURL(), &delegate);
EXPECT_NE(url, delegate.found_url_);
MessageLoop::current()->RunAllPending(); // Do async task execution.
EXPECT_EQ(url, delegate.found_url_);
@@ -431,7 +431,7 @@ TEST_F(MockAppCacheStorageTest, BasicFindMainResponse) {
// Conduct the test.
MockStorageDelegate delegate;
EXPECT_NE(kEntryUrl, delegate.found_url_);
- storage->FindResponseForMainRequest(kEntryUrl, &delegate);
+ storage->FindResponseForMainRequest(kEntryUrl, GURL(), &delegate);
EXPECT_NE(kEntryUrl, delegate.found_url_);
MessageLoop::current()->RunAllPending(); // Do async task execution.
EXPECT_EQ(kEntryUrl, delegate.found_url_);
@@ -486,7 +486,7 @@ TEST_F(MockAppCacheStorageTest, BasicFindMainFallbackResponse) {
// Conduct the test.
MockStorageDelegate delegate;
EXPECT_NE(kTestUrl, delegate.found_url_);
- storage->FindResponseForMainRequest(kTestUrl, &delegate);
+ storage->FindResponseForMainRequest(kTestUrl, GURL(), &delegate);
EXPECT_NE(kTestUrl, delegate.found_url_);
MessageLoop::current()->RunAllPending(); // Do async task execution.
EXPECT_EQ(kTestUrl, delegate.found_url_);
@@ -543,7 +543,7 @@ TEST_F(MockAppCacheStorageTest, FindMainResponseWithMultipleCandidates) {
// since it's "in use".
MockStorageDelegate delegate;
EXPECT_NE(kEntryUrl, delegate.found_url_);
- storage->FindResponseForMainRequest(kEntryUrl, &delegate);
+ storage->FindResponseForMainRequest(kEntryUrl, GURL(), &delegate);
EXPECT_NE(kEntryUrl, delegate.found_url_);
MessageLoop::current()->RunAllPending(); // Do async task execution.
EXPECT_EQ(kEntryUrl, delegate.found_url_);
@@ -589,7 +589,7 @@ TEST_F(MockAppCacheStorageTest, FindMainResponseExclusions) {
// We should not find anything for the foreign entry.
EXPECT_NE(kEntryUrl, delegate.found_url_);
- storage->FindResponseForMainRequest(kEntryUrl, &delegate);
+ storage->FindResponseForMainRequest(kEntryUrl, GURL(), &delegate);
EXPECT_NE(kEntryUrl, delegate.found_url_);
MessageLoop::current()->RunAllPending(); // Do async task execution.
EXPECT_EQ(kEntryUrl, delegate.found_url_);
@@ -603,7 +603,7 @@ TEST_F(MockAppCacheStorageTest, FindMainResponseExclusions) {
// We should not find anything for the online namespace.
EXPECT_NE(kOnlineNamespaceUrl, delegate.found_url_);
- storage->FindResponseForMainRequest(kOnlineNamespaceUrl, &delegate);
+ storage->FindResponseForMainRequest(kOnlineNamespaceUrl, GURL(), &delegate);
EXPECT_NE(kOnlineNamespaceUrl, delegate.found_url_);
MessageLoop::current()->RunAllPending(); // Do async task execution.
EXPECT_EQ(kOnlineNamespaceUrl, delegate.found_url_);
diff --git a/webkit/appcache/web_application_cache_host_impl.cc b/webkit/appcache/web_application_cache_host_impl.cc
index 981894d..4fbcc21 100644
--- a/webkit/appcache/web_application_cache_host_impl.cc
+++ b/webkit/appcache/web_application_cache_host_impl.cc
@@ -53,7 +53,7 @@ WebApplicationCacheHostImpl* WebApplicationCacheHostImpl::FromId(int id) {
}
WebApplicationCacheHostImpl* WebApplicationCacheHostImpl::FromFrame(
- WebFrame* frame) {
+ const WebFrame* frame) {
if (!frame)
return NULL;
WebDataSource* data_source = frame->dataSource();
@@ -166,10 +166,15 @@ void WebApplicationCacheHostImpl::willStartMainResourceRequest(
DCHECK(method == StringToUpperASCII(method));
if (frame) {
- if (WebApplicationCacheHostImpl* parent = FromFrame(frame->parent()))
- backend_->SetSpawningHostId(host_id_, parent->host_id());
- else if (WebApplicationCacheHostImpl* opener = FromFrame(frame->opener()))
- backend_->SetSpawningHostId(host_id_, opener->host_id());
+ const WebFrame* spawning_frame = frame->parent();
+ if (!spawning_frame)
+ spawning_frame = frame->opener();
+ if (!spawning_frame)
+ spawning_frame = frame;
+
+ WebApplicationCacheHostImpl* spawning_host = FromFrame(spawning_frame);
+ if (spawning_host && (spawning_host != this))
+ backend_->SetSpawningHostId(host_id_, spawning_host->host_id());
}
}
diff --git a/webkit/appcache/web_application_cache_host_impl.h b/webkit/appcache/web_application_cache_host_impl.h
index 03020f0..7b6789a 100644
--- a/webkit/appcache/web_application_cache_host_impl.h
+++ b/webkit/appcache/web_application_cache_host_impl.h
@@ -25,7 +25,7 @@ class WebApplicationCacheHostImpl : public WebKit::WebApplicationCacheHost {
static WebApplicationCacheHostImpl* FromId(int id);
// Returns the host associated with the current document in frame.
- static WebApplicationCacheHostImpl* FromFrame(WebKit::WebFrame* frame);
+ static WebApplicationCacheHostImpl* FromFrame(const WebKit::WebFrame* frame);
WebApplicationCacheHostImpl(WebKit::WebApplicationCacheHostClient* client,
AppCacheBackend* backend);