diff options
Diffstat (limited to 'webkit')
-rw-r--r-- | webkit/appcache/appcache.cc | 18 | ||||
-rw-r--r-- | webkit/appcache/appcache.h | 28 | ||||
-rw-r--r-- | webkit/appcache/appcache_backend_impl.cc | 2 | ||||
-rw-r--r-- | webkit/appcache/appcache_group.cc | 21 | ||||
-rw-r--r-- | webkit/appcache/appcache_group.h | 9 | ||||
-rw-r--r-- | webkit/appcache/appcache_group_unittest.cc | 96 | ||||
-rw-r--r-- | webkit/appcache/appcache_host.cc | 24 | ||||
-rw-r--r-- | webkit/appcache/appcache_host.h | 13 | ||||
-rw-r--r-- | webkit/appcache/appcache_service_unittest.cc | 40 | ||||
-rw-r--r-- | webkit/appcache/appcache_unittest.cc | 55 | ||||
-rw-r--r-- | webkit/tools/test_shell/test_shell.gyp | 3 |
11 files changed, 271 insertions, 38 deletions
diff --git a/webkit/appcache/appcache.cc b/webkit/appcache/appcache.cc index d202308..5e7bca63 100644 --- a/webkit/appcache/appcache.cc +++ b/webkit/appcache/appcache.cc @@ -11,6 +11,16 @@ namespace appcache { +AppCache::AppCache(AppCacheService *service, int64 cache_id) + : cache_id_(cache_id), + manifest_(NULL), + owning_group_(NULL), + online_whitelist_all_(false), + is_complete_(false), + service_(service) { + service_->AddCache(this); +} + AppCache::~AppCache() { DCHECK(associated_hosts_.empty()); DCHECK(!owning_group_); @@ -21,12 +31,8 @@ void AppCache::UnassociateHost(AppCacheHost* host) { associated_hosts_.erase(host); // Inform group if this cache is no longer in use. - if (associated_hosts_.empty()) { - if (!owning_group_ || owning_group_->RemoveCache(this)) { - owning_group_ = NULL; - delete this; - } - } + if (associated_hosts_.empty() && owning_group_) + owning_group_->RemoveCache(this); } void AppCache::AddEntry(const GURL& url, const AppCacheEntry& entry) { diff --git a/webkit/appcache/appcache.h b/webkit/appcache/appcache.h index c56673d..15944b6 100644 --- a/webkit/appcache/appcache.h +++ b/webkit/appcache/appcache.h @@ -10,6 +10,7 @@ #include <string> #include <vector> +#include "base/ref_counted.h" #include "base/time.h" #include "googleurl/src/gurl.h" #include "webkit/appcache/appcache_entry.h" @@ -21,10 +22,12 @@ class AppCacheGroup; class AppCacheHost; class AppCacheService; -// Set of cached resources for an application. -class AppCache { +// Set of cached resources for an application. A cache exists as long as a +// host is associated with it, the cache is in an appcache group or the +// cache is being created during an appcache upate. +class AppCache : public base::RefCounted<AppCache> { public: - // TODO(jennb): need constructor to set cache_id and service + AppCache(AppCacheService *service, int64 cache_id); ~AppCache(); int64 cache_id() { return cache_id_; } @@ -32,13 +35,6 @@ class AppCache { AppCacheGroup* owning_group() { return owning_group_; } void set_owning_group(AppCacheGroup* group) { owning_group_ = group; } - void AssociateHost(AppCacheHost* host) { - associated_hosts_.insert(host); - } - - // Cache may be deleted after host is unassociated. - void UnassociateHost(AppCacheHost* host); - bool is_complete() { return is_complete_; } void set_complete(bool value) { is_complete_ = value; } @@ -59,7 +55,19 @@ class AppCache { return update_time_ > cache->update_time_; } + void set_update_time(base::TimeTicks ticks = base::TimeTicks::Now()) { + update_time_ = ticks; + } + private: + friend class AppCacheHost; + + // Use AppCacheHost::set_selected_cache() to manipulate host association. + void AssociateHost(AppCacheHost* host) { + associated_hosts_.insert(host); + } + void UnassociateHost(AppCacheHost* host); + int64 cache_id_; AppCacheEntry* manifest_; // also in entry map AppCacheGroup* owning_group_; diff --git a/webkit/appcache/appcache_backend_impl.cc b/webkit/appcache/appcache_backend_impl.cc index 82b40ee..22e4e0f 100644 --- a/webkit/appcache/appcache_backend_impl.cc +++ b/webkit/appcache/appcache_backend_impl.cc @@ -5,6 +5,8 @@ #include "webkit/appcache/appcache_backend_impl.h" #include "webkit/appcache/appcache_host.h" +#include "webkit/appcache/appcache.h" +#include "webkit/appcache/appcache_group.h" #include "webkit/appcache/appcache_service.h" #include "webkit/appcache/web_application_cache_host_impl.h" diff --git a/webkit/appcache/appcache_group.cc b/webkit/appcache/appcache_group.cc index 36f4fb0..4299a67 100644 --- a/webkit/appcache/appcache_group.cc +++ b/webkit/appcache/appcache_group.cc @@ -27,14 +27,14 @@ AppCacheGroup::~AppCacheGroup() { // Newest complete cache might never have been associated with a host // and thus would not be cleaned up by the backend impl during shutdown. - if (newest_complete_cache_) { - delete newest_complete_cache_; - } + if (newest_complete_cache_) + RemoveCache(newest_complete_cache_); service_->RemoveGroup(this); } void AppCacheGroup::AddCache(AppCache* complete_cache) { + DCHECK(complete_cache->is_complete()); if (!newest_complete_cache_) { newest_complete_cache_ = complete_cache; return; @@ -56,17 +56,16 @@ bool AppCacheGroup::RemoveCache(AppCache* cache) { if (!old_caches_.empty()) return false; - newest_complete_cache_ = NULL; // cache will be deleted by caller + newest_complete_cache_->set_owning_group(NULL); + newest_complete_cache_ = NULL; } else { // Unused old cache can always be removed. - std::vector<AppCache*>::iterator it = + Caches::iterator it = std::find(old_caches_.begin(), old_caches_.end(), cache); - if (it != old_caches_.end()) - old_caches_.erase(it); // cache will be deleted by caller - } - - if (old_caches_.empty() && !newest_complete_cache_) { - delete this; + if (it != old_caches_.end()) { + (*it)->set_owning_group(NULL); + old_caches_.erase(it); + } } return true; diff --git a/webkit/appcache/appcache_group.h b/webkit/appcache/appcache_group.h index 05f437d..49ba788 100644 --- a/webkit/appcache/appcache_group.h +++ b/webkit/appcache/appcache_group.h @@ -7,6 +7,7 @@ #include <vector> +#include "base/ref_counted.h" #include "googleurl/src/gurl.h" namespace appcache { @@ -15,7 +16,8 @@ class AppCache; class AppCacheService; // Collection of application caches identified by the same manifest URL. -class AppCacheGroup { +// A group exists as long as it is in use by a host or is being updated. +class AppCacheGroup : public base::RefCounted<AppCacheGroup> { public: enum UpdateStatus { @@ -49,10 +51,11 @@ class AppCacheGroup { bool is_obsolete_; // old complete app caches - std::vector<AppCache*> old_caches_; + typedef std::vector<scoped_refptr<AppCache> > Caches; + Caches old_caches_; // newest cache in this group to be complete, aka relevant cache - AppCache* newest_complete_cache_; + scoped_refptr<AppCache> newest_complete_cache_; // to notify service when group is no longer needed AppCacheService* service_; diff --git a/webkit/appcache/appcache_group_unittest.cc b/webkit/appcache/appcache_group_unittest.cc new file mode 100644 index 0000000..c4e0cd1 --- /dev/null +++ b/webkit/appcache/appcache_group_unittest.cc @@ -0,0 +1,96 @@ +// Copyright (c) 2009 The Chromium Authos. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "testing/gtest/include/gtest/gtest.h" +#include "webkit/appcache/appcache.h" +#include "webkit/appcache/appcache_host.h" +#include "webkit/appcache/appcache_group.h" +#include "webkit/appcache/appcache_service.h" + +using appcache::AppCache; +using appcache::AppCacheHost; +using appcache::AppCacheGroup; +using appcache::AppCacheService; + +namespace { + +class AppCacheGroupTest : public testing::Test { +}; + +} // namespace + +TEST(AppCacheGroupTest, AddRemoveCache) { + AppCacheService service; + scoped_refptr<AppCacheGroup> group = + new AppCacheGroup(&service, GURL::EmptyGURL()); + + base::TimeTicks ticks = base::TimeTicks::Now(); + + AppCache* cache1 = new AppCache(&service, 111); + cache1->set_complete(true); + cache1->set_update_time(ticks); + cache1->set_owning_group(group); + group->AddCache(cache1); + EXPECT_EQ(cache1, group->newest_complete_cache()); + + // Adding older cache does not change newest complete cache. + AppCache* cache2 = new AppCache(&service, 222); + cache2->set_complete(true); + cache2->set_update_time(ticks - base::TimeDelta::FromDays(1)); + cache2->set_owning_group(group); + group->AddCache(cache2); + EXPECT_EQ(cache1, group->newest_complete_cache()); + + // Adding newer cache does change newest complete cache. + AppCache* cache3 = new AppCache(&service, 333); + cache3->set_complete(true); + cache3->set_update_time(ticks + base::TimeDelta::FromDays(1)); + cache3->set_owning_group(group); + group->AddCache(cache3); + EXPECT_EQ(cache3, group->newest_complete_cache()); + + // Old caches can always be removed. + EXPECT_TRUE(group->RemoveCache(cache1)); + EXPECT_EQ(cache3, group->newest_complete_cache()); // newest unchanged + + // Cannot remove newest cache if there are older caches. + EXPECT_FALSE(group->RemoveCache(cache3)); + EXPECT_EQ(cache3, group->newest_complete_cache()); // newest unchanged + + // Can remove newest cache after all older caches are removed. + EXPECT_TRUE(group->RemoveCache(cache2)); + EXPECT_EQ(cache3, group->newest_complete_cache()); // newest unchanged + EXPECT_TRUE(group->RemoveCache(cache3)); +} + +TEST(AppCacheGroupTest, CleanupUnusedGroup) { + AppCacheService service; + AppCacheGroup* group = new AppCacheGroup(&service, GURL::EmptyGURL()); + + AppCacheHost host1(1, NULL); + AppCacheHost host2(2, NULL); + + base::TimeTicks ticks = base::TimeTicks::Now(); + + AppCache* cache1 = new AppCache(&service, 111); + cache1->set_complete(true); + cache1->set_update_time(ticks); + cache1->set_owning_group(group); + group->AddCache(cache1); + EXPECT_EQ(cache1, group->newest_complete_cache()); + + host1.set_selected_cache(cache1); + host2.set_selected_cache(cache1); + + AppCache* cache2 = new AppCache(&service, 222); + cache2->set_complete(true); + cache2->set_update_time(ticks + base::TimeDelta::FromDays(1)); + cache2->set_owning_group(group); + group->AddCache(cache2); + EXPECT_EQ(cache2, group->newest_complete_cache()); + + // Unassociate all hosts from older cache. + host1.set_selected_cache(NULL); + host2.set_selected_cache(NULL); +} diff --git a/webkit/appcache/appcache_host.cc b/webkit/appcache/appcache_host.cc index 7585f606..99f0544 100644 --- a/webkit/appcache/appcache_host.cc +++ b/webkit/appcache/appcache_host.cc @@ -6,19 +6,35 @@ #include "base/logging.h" #include "webkit/appcache/appcache.h" +#include "webkit/appcache/appcache_group.h" #include "webkit/appcache/appcache_interfaces.h" namespace appcache { AppCacheHost::AppCacheHost(int host_id, AppCacheFrontend* frontend) - : host_id_(host_id), - selected_cache_(NULL), - frontend_(frontend) { + : host_id_(host_id), + selected_cache_(NULL), + group_(NULL), + frontend_(frontend) { } AppCacheHost::~AppCacheHost() { - if (selected_cache_) { + if (selected_cache_) + set_selected_cache(NULL); + DCHECK(!group_); +} + +void AppCacheHost::set_selected_cache(AppCache *cache) { + if (selected_cache_) selected_cache_->UnassociateHost(this); + + selected_cache_ = cache; + + if (cache) { + cache->AssociateHost(this); + group_ = cache->owning_group(); + } else { + group_ = NULL; } } diff --git a/webkit/appcache/appcache_host.h b/webkit/appcache/appcache_host.h index bebc22d..420e3d4 100644 --- a/webkit/appcache/appcache_host.h +++ b/webkit/appcache/appcache_host.h @@ -5,10 +5,13 @@ #ifndef WEBKIT_APPCACHE_APPCACHE_HOST_H_ #define WEBKIT_APPCACHE_APPCACHE_HOST_H_ +#include "base/ref_counted.h" + namespace appcache { class AppCache; class AppCacheFrontend; +class AppCacheGroup; // Server-side representation of an application cache host. class AppCacheHost { @@ -20,9 +23,7 @@ class AppCacheHost { AppCacheFrontend* frontend() { return frontend_; } AppCache* selected_cache() { return selected_cache_; } - void set_selected_cache(AppCache* cache) { - selected_cache_ = cache; - } + void set_selected_cache(AppCache* cache); bool is_selection_pending() { return false; // TODO(michaeln) @@ -33,7 +34,11 @@ class AppCacheHost { int host_id_; // application cache associated with this host, if any - AppCache* selected_cache_; + scoped_refptr<AppCache> selected_cache_; + + // The reference to the appcache group ensures the group exists as long + // as there is a host using a cache belonging to that group. + scoped_refptr<AppCacheGroup> group_; // frontend to deliver notifications about this host to child process AppCacheFrontend* frontend_; diff --git a/webkit/appcache/appcache_service_unittest.cc b/webkit/appcache/appcache_service_unittest.cc new file mode 100644 index 0000000..c58374f --- /dev/null +++ b/webkit/appcache/appcache_service_unittest.cc @@ -0,0 +1,40 @@ +// Copyright (c) 2009 The Chromium Authos. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "testing/gtest/include/gtest/gtest.h" +#include "webkit/appcache/appcache.h" +#include "webkit/appcache/appcache_group.h" +#include "webkit/appcache/appcache_service.h" + +using appcache::AppCache; +using appcache::AppCacheGroup; +using appcache::AppCacheService; + +namespace { + +class AppCacheServiceTest : public testing::Test { +}; + +} // namespace + +TEST(AppCacheServiceTest, AddRemoveCache) { + AppCacheService service; + scoped_refptr<AppCache> cache = new AppCache(&service, 111); + service.RemoveCache(cache); + + // Removing non-existing cache from service should not fail. + AppCacheService dummy; + dummy.RemoveCache(cache); +} + +TEST(AppCacheServiceTest, AddRemoveGroup) { + AppCacheService service; + scoped_refptr<AppCacheGroup> group = + new AppCacheGroup(&service, GURL::EmptyGURL()); + service.RemoveGroup(group); + + // Removing non-existing group from service should not fail. + AppCacheService dummy; + dummy.RemoveGroup(group); +} diff --git a/webkit/appcache/appcache_unittest.cc b/webkit/appcache/appcache_unittest.cc new file mode 100644 index 0000000..951cb8b --- /dev/null +++ b/webkit/appcache/appcache_unittest.cc @@ -0,0 +1,55 @@ +// Copyright (c) 2009 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. + +#include "testing/gtest/include/gtest/gtest.h" +#include "webkit/appcache/appcache.h" +#include "webkit/appcache/appcache_host.h" +#include "webkit/appcache/appcache_service.h" + +using appcache::AppCache; +using appcache::AppCacheEntry; +using appcache::AppCacheHost; +using appcache::AppCacheService; + +namespace { + +class AppCacheTest : public testing::Test { +}; + +} // namespace + +TEST(AppCacheTest, CleanupUnusedCache) { + AppCacheService service; + AppCache* cache = new AppCache(&service, 111); + + AppCacheHost host1(1, NULL); + AppCacheHost host2(2, NULL); + + host1.set_selected_cache(cache); + host2.set_selected_cache(cache); + + host1.set_selected_cache(NULL); + host2.set_selected_cache(NULL); +} + +TEST(AppCacheTest, AddModifyEntry) { + AppCacheService service; + scoped_refptr<AppCache> cache = new AppCache(&service, 111); + + const GURL kUrl1("http://foo.com"); + AppCacheEntry entry1(AppCacheEntry::MASTER); + cache->AddEntry(kUrl1, entry1); + EXPECT_EQ(entry1.types(), cache->GetEntry(kUrl1)->types()); + + const GURL kUrl2("http://bar.com"); + AppCacheEntry entry2(AppCacheEntry::FALLBACK); + cache->AddOrModifyEntry(kUrl2, entry2); + EXPECT_EQ(entry2.types(), cache->GetEntry(kUrl2)->types()); + + AppCacheEntry entry3(AppCacheEntry::EXPLICIT); + cache->AddOrModifyEntry(kUrl1, entry3); + EXPECT_EQ((AppCacheEntry::MASTER | AppCacheEntry::EXPLICIT), + cache->GetEntry(kUrl1)->types()); + EXPECT_EQ(entry2.types(), cache->GetEntry(kUrl2)->types()); // unchanged +} diff --git a/webkit/tools/test_shell/test_shell.gyp b/webkit/tools/test_shell/test_shell.gyp index 94d3863..604e525 100644 --- a/webkit/tools/test_shell/test_shell.gyp +++ b/webkit/tools/test_shell/test_shell.gyp @@ -322,6 +322,9 @@ '../../../skia/ext/platform_canvas_unittest.cc', '../../../skia/ext/vector_canvas_unittest.cc', '../../appcache/manifest_parser_unittest.cc', + '../../appcache/appcache_unittest.cc', + '../../appcache/appcache_group_unittest.cc', + '../../appcache/appcache_service_unittest.cc', '../../glue/bookmarklet_unittest.cc', '../../glue/context_menu_unittest.cc', '../../glue/cpp_bound_class_unittest.cc', |