summaryrefslogtreecommitdiffstats
path: root/webkit/appcache
diff options
context:
space:
mode:
authormichaeln@chromium.org <michaeln@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-08-04 20:01:37 +0000
committermichaeln@chromium.org <michaeln@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-08-04 20:01:37 +0000
commitbae3069e31b61b1555f65272ec8973b2f4c56df5 (patch)
tree6edca4e598e62e1bbc87fc0a96ba99293d103686 /webkit/appcache
parent5fd7738372b76c4a1951e6b842e6387cd09d2521 (diff)
downloadchromium_src-bae3069e31b61b1555f65272ec8973b2f4c56df5.zip
chromium_src-bae3069e31b61b1555f65272ec8973b2f4c56df5.tar.gz
chromium_src-bae3069e31b61b1555f65272ec8973b2f4c56df5.tar.bz2
AppCache: Provide a way to override the default quota for an origin. The intent is to use this to support the 'unlimited_storage' privilege of Chrome Applications.
BUG=49993 TEST=AppCacheStorageImplTest.FailStoreGroup Review URL: http://codereview.chromium.org/3083014 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@54949 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'webkit/appcache')
-rw-r--r--webkit/appcache/appcache_storage.cc19
-rw-r--r--webkit/appcache/appcache_storage.h10
-rw-r--r--webkit/appcache/appcache_storage_impl.cc12
-rw-r--r--webkit/appcache/appcache_storage_impl_unittest.cc56
4 files changed, 92 insertions, 5 deletions
diff --git a/webkit/appcache/appcache_storage.cc b/webkit/appcache/appcache_storage.cc
index 05b6269..52767ad 100644
--- a/webkit/appcache/appcache_storage.cc
+++ b/webkit/appcache/appcache_storage.cc
@@ -72,5 +72,24 @@ void AppCacheStorage::LoadResponseInfo(
info_load->StartIfNeeded();
}
+void AppCacheStorage::SetOriginQuotaInMemory(const GURL& origin, int64 quota) {
+ DCHECK(quota >= 0);
+ DCHECK(origin == origin.GetOrigin());
+ in_memory_quotas_[origin] = quota;
+}
+
+void AppCacheStorage::ResetOriginQuotaInMemory(const GURL& origin) {
+ DCHECK(origin == origin.GetOrigin());
+ in_memory_quotas_.erase(origin);
+}
+
+int64 AppCacheStorage::GetOriginQuotaInMemory(const GURL& origin) {
+ DCHECK(origin == origin.GetOrigin());
+ QuotaMap::const_iterator found = in_memory_quotas_.find(origin);
+ if (found == in_memory_quotas_.end())
+ return -1;
+ return found->second;
+}
+
} // namespace appcache
diff --git a/webkit/appcache/appcache_storage.h b/webkit/appcache/appcache_storage.h
index 9b6596c..559237c 100644
--- a/webkit/appcache/appcache_storage.h
+++ b/webkit/appcache/appcache_storage.h
@@ -167,6 +167,11 @@ class AppCacheStorage {
virtual void PurgeMemory() = 0;
+ // Maintain a collection of quota overrides in memory.
+ void SetOriginQuotaInMemory(const GURL& origin, int64 quota);
+ void ResetOriginQuotaInMemory(const GURL& origin);
+ int64 GetOriginQuotaInMemory(const GURL& origin);
+
// Generates unique storage ids for different object types.
int64 NewCacheId() {
return ++last_cache_id_;
@@ -284,6 +289,11 @@ class AppCacheStorage {
return ++last_response_id_;
}
+ // Store quotas for extensions in memory, in order to prevent writing a row
+ // to quota_table_ every time an extention is loaded.
+ typedef std::map<GURL, int64> QuotaMap;
+ QuotaMap in_memory_quotas_;
+
// The last storage id used for different object types.
int64 last_cache_id_;
int64 last_group_id_;
diff --git a/webkit/appcache/appcache_storage_impl.cc b/webkit/appcache/appcache_storage_impl.cc
index c715863..2231234 100644
--- a/webkit/appcache/appcache_storage_impl.cc
+++ b/webkit/appcache/appcache_storage_impl.cc
@@ -402,13 +402,16 @@ class AppCacheStorageImpl::StoreGroupAndCacheTask : public StoreOrLoadTask {
scoped_refptr<AppCache> cache_;
bool success_;
bool would_exceed_quota_;
+ int64 quota_override_;
std::vector<int64> newly_deletable_response_ids_;
};
AppCacheStorageImpl::StoreGroupAndCacheTask::StoreGroupAndCacheTask(
AppCacheStorageImpl* storage, AppCacheGroup* group, AppCache* newest_cache)
: StoreOrLoadTask(storage), group_(group), cache_(newest_cache),
- success_(false), would_exceed_quota_(false) {
+ success_(false), would_exceed_quota_(false),
+ quota_override_(
+ storage->GetOriginQuotaInMemory(group->manifest_url().GetOrigin())) {
group_record_.group_id = group->group_id();
group_record_.manifest_url = group->manifest_url();
group_record_.origin = group_record_.manifest_url.GetOrigin();
@@ -485,8 +488,11 @@ void AppCacheStorageImpl::StoreGroupAndCacheTask::Run() {
if (!success_)
return;
- if (database_->GetOriginUsage(group_record_.origin) >
- database_->GetOriginQuota(group_record_.origin)) {
+ int64 quota = (quota_override_ >= 0) ?
+ quota_override_ :
+ database_->GetOriginQuota(group_record_.origin);
+
+ if (database_->GetOriginUsage(group_record_.origin) > quota) {
would_exceed_quota_ = true;
success_ = false;
return;
diff --git a/webkit/appcache/appcache_storage_impl_unittest.cc b/webkit/appcache/appcache_storage_impl_unittest.cc
index 8367cf8..5fccade 100644
--- a/webkit/appcache/appcache_storage_impl_unittest.cc
+++ b/webkit/appcache/appcache_storage_impl_unittest.cc
@@ -73,8 +73,9 @@ class AppCacheStorageImplTest : public testing::Test {
public:
explicit MockStorageDelegate(AppCacheStorageImplTest* test)
: loaded_cache_id_(0), stored_group_success_(false),
- obsoleted_success_(false), found_cache_id_(kNoCacheId),
- found_blocked_by_policy_(false), test_(test) {
+ would_exceed_quota_(false), obsoleted_success_(false),
+ found_cache_id_(kNoCacheId), found_blocked_by_policy_(false),
+ test_(test) {
}
void OnCacheLoaded(AppCache* cache, int64 cache_id) {
@@ -96,6 +97,7 @@ class AppCacheStorageImplTest : public testing::Test {
bool would_exceed_quota) {
stored_group_ = group;
stored_group_success_ = success;
+ would_exceed_quota_ = would_exceed_quota;
test_->ScheduleNextTask();
}
@@ -125,6 +127,7 @@ class AppCacheStorageImplTest : public testing::Test {
scoped_refptr<AppCache> loaded_groups_newest_cache_;
scoped_refptr<AppCacheGroup> stored_group_;
bool stored_group_success_;
+ bool would_exceed_quota_;
scoped_refptr<AppCacheGroup> obsoleted_group_;
bool obsoleted_success_;
GURL found_url_;
@@ -532,6 +535,51 @@ class AppCacheStorageImplTest : public testing::Test {
TestFinished();
}
+ // FailStoreGroup --------------------------------------
+
+ void FailStoreGroup() {
+ // Store a group and its newest cache. Should complete asyncly.
+ PushNextTask(NewRunnableMethod(
+ this, &AppCacheStorageImplTest::Verify_FailStoreGroup));
+
+ // Set a low quota to force a failure.
+ const GURL kOrigin(kManifestUrl.GetOrigin());
+ EXPECT_EQ(-1L, storage()->GetOriginQuotaInMemory(kOrigin));
+ storage()->SetOriginQuotaInMemory(kManifestUrl.GetOrigin(), 0);
+ EXPECT_EQ(0L, storage()->GetOriginQuotaInMemory(kOrigin));
+
+ // Setup some preconditions. Create a group and newest cache that
+ // appear to be "unstored".
+ group_ = new AppCacheGroup(
+ service(), kManifestUrl, storage()->NewGroupId());
+ cache_ = new AppCache(service(), storage()->NewCacheId());
+ cache_->AddEntry(kManifestUrl,
+ AppCacheEntry(AppCacheEntry::MANIFEST, 1, 1024));
+ // Hold a ref to the cache simulate the UpdateJob holding that ref,
+ // and hold a ref to the group to simulate the CacheHost holding that ref.
+
+ // Conduct the store test.
+ storage()->StoreGroupAndNewestCache(group_, cache_, delegate());
+ EXPECT_FALSE(delegate()->stored_group_success_); // Expected to be async.
+ }
+
+ void Verify_FailStoreGroup() {
+ EXPECT_FALSE(delegate()->stored_group_success_);
+ EXPECT_TRUE(delegate()->would_exceed_quota_);
+
+ // Should not have been stored in the database.
+ AppCacheDatabase::GroupRecord group_record;
+ AppCacheDatabase::CacheRecord cache_record;
+ EXPECT_FALSE(database()->FindGroup(group_->group_id(), &group_record));
+ EXPECT_FALSE(database()->FindCache(cache_->cache_id(), &cache_record));
+
+ const GURL kOrigin(kManifestUrl.GetOrigin());
+ storage()->ResetOriginQuotaInMemory(kOrigin);
+ EXPECT_EQ(-1L, storage()->GetOriginQuotaInMemory(kOrigin));
+
+ TestFinished();
+ }
+
// MakeGroupObsolete -------------------------------
void MakeGroupObsolete() {
@@ -1006,6 +1054,10 @@ TEST_F(AppCacheStorageImplTest, StoreExistingGroupExistingCache) {
RunTestOnIOThread(&AppCacheStorageImplTest::StoreExistingGroupExistingCache);
}
+TEST_F(AppCacheStorageImplTest, FailStoreGroup) {
+ RunTestOnIOThread(&AppCacheStorageImplTest::FailStoreGroup);
+}
+
TEST_F(AppCacheStorageImplTest, MakeGroupObsolete) {
RunTestOnIOThread(&AppCacheStorageImplTest::MakeGroupObsolete);
}