summaryrefslogtreecommitdiffstats
path: root/webkit
diff options
context:
space:
mode:
Diffstat (limited to 'webkit')
-rw-r--r--webkit/appcache/appcache.cc18
-rw-r--r--webkit/appcache/appcache.h28
-rw-r--r--webkit/appcache/appcache_backend_impl.cc2
-rw-r--r--webkit/appcache/appcache_group.cc21
-rw-r--r--webkit/appcache/appcache_group.h9
-rw-r--r--webkit/appcache/appcache_group_unittest.cc96
-rw-r--r--webkit/appcache/appcache_host.cc24
-rw-r--r--webkit/appcache/appcache_host.h13
-rw-r--r--webkit/appcache/appcache_service_unittest.cc40
-rw-r--r--webkit/appcache/appcache_unittest.cc55
-rw-r--r--webkit/tools/test_shell/test_shell.gyp3
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',