diff options
author | kinuko@chromium.org <kinuko@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-05-13 11:49:57 +0000 |
---|---|---|
committer | kinuko@chromium.org <kinuko@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-05-13 11:49:57 +0000 |
commit | e855d81135b9a6e4d3b8b3f3d36315fc1c464393 (patch) | |
tree | a0490ad6e949d67416e4b3bee0054dbb8fdbf09a /webkit/quota | |
parent | 549b7e2b1e215aba3617e346c822272e1ec8f04f (diff) | |
download | chromium_src-e855d81135b9a6e4d3b8b3f3d36315fc1c464393.zip chromium_src-e855d81135b9a6e4d3b8b3f3d36315fc1c464393.tar.gz chromium_src-e855d81135b9a6e4d3b8b3f3d36315fc1c464393.tar.bz2 |
Added {Get,Set}PersistentHostQuota and Get{Global,Host}Usage to QuotaManager.
Fixed version of issue 6904042.
BUG=61676
TEST='QuotaManagerTests.*'
Review URL: http://codereview.chromium.org/7004019
Patch from Taiju Tsuiki <tzik@google.com>.
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@85263 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'webkit/quota')
-rw-r--r-- | webkit/quota/mock_storage_client.cc | 32 | ||||
-rw-r--r-- | webkit/quota/mock_storage_client.h | 14 | ||||
-rw-r--r-- | webkit/quota/quota_manager.cc | 193 | ||||
-rw-r--r-- | webkit/quota/quota_manager.h | 27 | ||||
-rw-r--r-- | webkit/quota/quota_manager_unittest.cc | 397 | ||||
-rw-r--r-- | webkit/quota/quota_task.cc | 15 | ||||
-rw-r--r-- | webkit/quota/quota_task.h | 9 | ||||
-rw-r--r-- | webkit/quota/quota_types.h | 61 | ||||
-rw-r--r-- | webkit/quota/usage_tracker.cc | 10 |
9 files changed, 647 insertions, 111 deletions
diff --git a/webkit/quota/mock_storage_client.cc b/webkit/quota/mock_storage_client.cc index ee1a0b1..e2e8a69 100644 --- a/webkit/quota/mock_storage_client.cc +++ b/webkit/quota/mock_storage_client.cc @@ -19,6 +19,8 @@ namespace quota { namespace { +using std::make_pair; + class MockStorageClientIDSequencer { public: static MockStorageClientIDSequencer* GetInstance() { @@ -54,17 +56,21 @@ MockStorageClient::~MockStorageClient() { void MockStorageClient::AddMockOriginData( const GURL& origin_url, StorageType type, int64 size) { - origin_data_.insert(std::make_pair(origin_url, MockOriginData(type, size))); + origin_data_[make_pair(origin_url, type)] = size; } void MockStorageClient::ModifyMockOriginDataSize( const GURL& origin_url, StorageType type, int64 delta) { - std::map<GURL, MockOriginData>::iterator find = origin_data_.find(origin_url); - if (find == origin_data_.end() || find->second.type != type) { - DCHECK(delta >= 0); + OriginDataMap::iterator find = origin_data_.find(make_pair(origin_url, type)); + if (find == origin_data_.end()) { + DCHECK_GE(delta, 0); AddMockOriginData(origin_url, type, delta); return; } + find->second += delta; + DCHECK_GE(find->second, 0); + + // TODO(tzik): Check quota to prevent usage exceed quota_manager_proxy_->NotifyStorageModified(id(), origin_url, type, delta); } @@ -109,11 +115,11 @@ void MockStorageClient::RunGetOriginUsage( const GURL& origin_url, StorageType type, GetUsageCallback* callback_ptr) { usage_callbacks_.erase(callback_ptr); scoped_ptr<GetUsageCallback> callback(callback_ptr); - std::map<GURL, MockOriginData>::iterator find = origin_data_.find(origin_url); + OriginDataMap::iterator find = origin_data_.find(make_pair(origin_url, type)); if (find == origin_data_.end()) { callback->Run(0); } else { - callback->Run(find->second.usage); + callback->Run(find->second); } } @@ -122,10 +128,10 @@ void MockStorageClient::RunGetOriginsForType( scoped_ptr<GetOriginsCallback> callback(callback_ptr); origins_callbacks_.erase(callback_ptr); std::set<GURL> origins; - for (std::map<GURL, MockOriginData>::iterator iter = origin_data_.begin(); + for (OriginDataMap::iterator iter = origin_data_.begin(); iter != origin_data_.end(); ++iter) { - if (type == iter->second.type) - origins.insert(iter->first); + if (type == iter->first.second) + origins.insert(iter->first.first); } callback->Run(origins); } @@ -136,11 +142,11 @@ void MockStorageClient::RunGetOriginsForHost( scoped_ptr<GetOriginsCallback> callback(callback_ptr); origins_callbacks_.erase(callback_ptr); std::set<GURL> origins; - for (std::map<GURL, MockOriginData>::iterator iter = origin_data_.begin(); + for (OriginDataMap::iterator iter = origin_data_.begin(); iter != origin_data_.end(); ++iter) { - std::string host_or_spec = net::GetHostOrSpecFromURL(iter->first); - if (type == iter->second.type && host == host_or_spec) - origins.insert(iter->first); + std::string host_or_spec = net::GetHostOrSpecFromURL(iter->first.first); + if (type == iter->first.second && host == host_or_spec) + origins.insert(iter->first.first); } callback->Run(origins); } diff --git a/webkit/quota/mock_storage_client.h b/webkit/quota/mock_storage_client.h index ac2545b..cf0299a 100644 --- a/webkit/quota/mock_storage_client.h +++ b/webkit/quota/mock_storage_client.h @@ -6,6 +6,8 @@ #define WEBKIT_QUOTA_MOCK_STORAGE_CLIENT_H_ #include <map> +#include <set> +#include <string> #include "base/compiler_specific.h" #include "base/task.h" @@ -19,7 +21,7 @@ class QuotaManagerProxy; // Mock storage class for testing. class MockStorageClient : public QuotaClient { public: - MockStorageClient(QuotaManagerProxy* quota_manager_proxy); + explicit MockStorageClient(QuotaManagerProxy* quota_manager_proxy); virtual ~MockStorageClient(); // To add or modify mock data in this client. @@ -51,12 +53,8 @@ class MockStorageClient : public QuotaClient { scoped_refptr<QuotaManagerProxy> quota_manager_proxy_; const ID id_; - struct MockOriginData { - MockOriginData(StorageType type, int64 usage) : type(type), usage(usage) { } - StorageType type; - int64 usage; - }; - std::map<GURL, MockOriginData> origin_data_; + typedef std::map<std::pair<GURL, StorageType>, int64> OriginDataMap; + OriginDataMap origin_data_; std::set<GetUsageCallback*> usage_callbacks_; std::set<GetOriginsCallback*> origins_callbacks_; @@ -68,4 +66,4 @@ class MockStorageClient : public QuotaClient { } // namespace quota -#endif // WEBKIT_QUOTA_MOCK_STORAGE_H_ +#endif // WEBKIT_QUOTA_MOCK_STORAGE_CLIENT_H_ diff --git a/webkit/quota/quota_manager.cc b/webkit/quota/quota_manager.cc index 060d379..b9a787c 100644 --- a/webkit/quota/quota_manager.cc +++ b/webkit/quota/quota_manager.cc @@ -84,12 +84,16 @@ class QuotaManager::UsageAndQuotaDispatcherTask : public QuotaTask { CheckCompleted(); } - void DidGetGlobalQuota(int64 quota) { + void DidGetGlobalQuota(QuotaStatusCode status, int64 quota) { + quota_status_ = status; quota_ = quota; CheckCompleted(); } - void DidGetHostQuota(const std::string& host_unused, int64 quota) { + void DidGetHostQuota(QuotaStatusCode status, + const std::string& host_unused, + int64 quota) { + quota_status_ = status; quota_ = quota; CheckCompleted(); } @@ -105,6 +109,7 @@ class QuotaManager::UsageAndQuotaDispatcherTask : public QuotaTask { quota_(-1), global_usage_(-1), host_usage_(-1), + quota_status_(kQuotaStatusUnknown), callback_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {} virtual ~UsageAndQuotaDispatcherTask() { @@ -123,10 +128,12 @@ class QuotaManager::UsageAndQuotaDispatcherTask : public QuotaTask { delete *iter; } callbacks_.clear(); - delete this; + DeleteSoon(); } - virtual void Completed() OVERRIDE { delete this; } + virtual void Completed() OVERRIDE { + DeleteSoon(); + } QuotaManager* manager() const { return static_cast<QuotaManager*>(observer()); } @@ -136,6 +143,7 @@ class QuotaManager::UsageAndQuotaDispatcherTask : public QuotaTask { int64 quota() const { return quota_; } int64 global_usage() const { return global_usage_; } int64 host_usage() const { return host_usage_; } + QuotaStatusCode status() const { return quota_status_; } UsageCallback* NewGlobalUsageCallback() { return callback_factory_.NewCallback( @@ -182,6 +190,7 @@ class QuotaManager::UsageAndQuotaDispatcherTask : public QuotaTask { int64 quota_; int64 global_usage_; int64 host_usage_; + QuotaStatusCode quota_status_; CallbackList callbacks_; ScopedCallbackFactory<UsageAndQuotaDispatcherTask> callback_factory_; @@ -213,7 +222,7 @@ class QuotaManager::UsageAndQuotaDispatcherTaskForTemporary // to return {usage, quota - nonevictable_usage} once eviction is // supported. int64 other_usage = global_usage() - host_usage(); - callback->Run(kQuotaStatusOk, host_usage(), quota() - other_usage); + callback->Run(status(), host_usage(), quota() - other_usage); } }; @@ -237,7 +246,7 @@ class QuotaManager::UsageAndQuotaDispatcherTaskForPersistent } virtual void DispatchCallback(GetUsageAndQuotaCallback* callback) OVERRIDE { - callback->Run(kQuotaStatusOk, host_usage(), quota()); + callback->Run(status(), host_usage(), quota()); } }; @@ -292,10 +301,10 @@ class QuotaManager::InitializeTask : public QuotaThreadTask { virtual void Completed() OVERRIDE { DCHECK(manager_); - if (manager_->temporary_global_quota_ < 0) - manager_->DidGetTemporaryGlobalQuota(temporary_storage_quota_); manager_->db_initialized_ = !db_disabled_; manager_->db_disabled_ = db_disabled_; + if (manager_->temporary_global_quota_ < 0) + manager_->DidGetTemporaryGlobalQuota(temporary_storage_quota_); } private: @@ -306,36 +315,122 @@ class QuotaManager::InitializeTask : public QuotaThreadTask { bool db_disabled_; }; -class QuotaManager::TemporaryGlobalQuotaUpdateTask : public QuotaThreadTask { +class QuotaManager::TemporaryGlobalQuotaUpdateTask + : public QuotaThreadTask { public: TemporaryGlobalQuotaUpdateTask( QuotaManager* manager, QuotaDatabase* database, scoped_refptr<base::MessageLoopProxy> db_message_loop, - int64 new_quota) + int64 new_quota, + QuotaCallback* callback) : QuotaThreadTask(manager, db_message_loop), manager_(manager), database_(database), new_quota_(new_quota), + callback_(callback), db_disabled_(false) { DCHECK(database_); + DCHECK_GE(new_quota, 0); } protected: virtual void RunOnTargetThread() OVERRIDE { - if (!database_->SetGlobalQuota(kStorageTypeTemporary, new_quota_)) + if (!database_->SetGlobalQuota(kStorageTypeTemporary, new_quota_)) { db_disabled_ = true; + new_quota_ = 0; + } } virtual void Completed() OVERRIDE { DCHECK(manager_); manager_->db_disabled_ = db_disabled_; + callback_->Run(db_disabled_ ? kQuotaErrorInvalidAccess : kQuotaStatusOk, + new_quota_); } private: QuotaManager* manager_; QuotaDatabase* database_; int64 new_quota_; + scoped_ptr<QuotaCallback> callback_; + bool db_disabled_; +}; + +class QuotaManager::PersistentHostQuotaQueryTask : public QuotaThreadTask { + public: + PersistentHostQuotaQueryTask( + QuotaManager* manager, + QuotaDatabase* database, + scoped_refptr<base::MessageLoopProxy> db_message_loop, + const std::string& host, + HostQuotaCallback* callback) + : QuotaThreadTask(manager, db_message_loop), + manager_(manager), + database_(database), + host_(host), + quota_(-1), + callback_(callback) { + DCHECK(manager_); + DCHECK(database_); + DCHECK(!host_.empty()); + } + protected: + virtual void RunOnTargetThread() OVERRIDE { + if (!database_->GetHostQuota(host_, kStorageTypePersistent, "a_)) + quota_ = 0; + } + virtual void Completed() OVERRIDE { + callback_->Run(kQuotaStatusOk, host_, quota_); + } + private: + QuotaManager* manager_; + QuotaDatabase* database_; + std::string host_; + int64 quota_; + scoped_ptr<HostQuotaCallback> callback_; +}; + +class QuotaManager::PersistentHostQuotaUpdateTask : public QuotaThreadTask { + public: + PersistentHostQuotaUpdateTask( + QuotaManager* manager, + QuotaDatabase* database, + scoped_refptr<base::MessageLoopProxy> db_message_loop, + const std::string& host, + int new_quota, + HostQuotaCallback* callback) + : QuotaThreadTask(manager, db_message_loop), + manager_(manager), + database_(database), + host_(host), + new_quota_(new_quota), + callback_(callback), + db_disabled_(false) { + DCHECK(manager_); + DCHECK(database_); + DCHECK(!host_.empty()); + DCHECK_GE(new_quota_, 0); + } + protected: + virtual void RunOnTargetThread() OVERRIDE { + if (!database_->SetHostQuota(host_, kStorageTypePersistent, new_quota_)) { + db_disabled_ = true; + new_quota_ = 0; + } + } + + virtual void Completed() OVERRIDE { + manager_->db_disabled_ = db_disabled_; + callback_->Run(db_disabled_ ? kQuotaErrorInvalidAccess : kQuotaStatusOk, + host_, new_quota_); + } + private: + QuotaManager* manager_; + QuotaDatabase* database_; + std::string host_; + int64 new_quota_; + scoped_ptr<HostQuotaCallback> callback_; bool db_disabled_; }; @@ -411,7 +506,7 @@ void QuotaManager::GetTemporaryGlobalQuota(QuotaCallback* callback) { if (temporary_global_quota_ >= 0) { // TODO(kinuko): The in-memory quota value should be periodically // updated not to exceed the current available space in the hard drive. - callback->Run(temporary_global_quota_); + callback->Run(kQuotaStatusOk, temporary_global_quota_); delete callback; return; } @@ -419,39 +514,55 @@ void QuotaManager::GetTemporaryGlobalQuota(QuotaCallback* callback) { temporary_global_quota_callbacks_.Add(callback); } -void QuotaManager::SetTemporaryGlobalQuota(int64 new_quota) { +void QuotaManager::SetTemporaryGlobalQuota(int64 new_quota, + QuotaCallback* callback) { LazyInitialize(); - DCHECK(new_quota >= 0); + if (new_quota < 0) { + callback->Run(kQuotaErrorInvalidModification, -1); + delete callback; + return; + } + DidGetTemporaryGlobalQuota(new_quota); if (!db_disabled_) { scoped_refptr<TemporaryGlobalQuotaUpdateTask> task( new TemporaryGlobalQuotaUpdateTask( - this, database_.get(), db_thread_, new_quota)); + this, database_.get(), db_thread_, new_quota, callback)); task->Start(); + } else { + callback->Run(kQuotaErrorInvalidAccess, -1); + delete callback; } } void QuotaManager::GetPersistentHostQuota(const std::string& host, HostQuotaCallback* callback) { LazyInitialize(); - std::map<std::string, int64>::iterator found = - persistent_host_quota_.find(host); - if (found != persistent_host_quota_.end()) { - callback->Run(host, found->second); - delete callback; - return; - } - if (persistent_host_quota_callbacks_.Add(host, callback)) { - // This is the first call for this host. - // TODO(kinuko): Dispatch a task to get the host quota for the host - // once QuotaDatabase is updated to accept hosts instead of origins. - } + scoped_refptr<PersistentHostQuotaQueryTask> task( + new PersistentHostQuotaQueryTask( + this, database_.get(), db_thread_, host, callback)); + task->Start(); } void QuotaManager::SetPersistentHostQuota(const std::string& host, - int64 new_quota) { + int64 new_quota, + HostQuotaCallback* callback) { LazyInitialize(); - // TODO(kinuko): Implement once QuotaDatabase is updated. + if (new_quota < 0) { + callback->Run(kQuotaErrorInvalidModification, host, -1); + delete callback; + return; + } + + if (!db_disabled_) { + scoped_refptr<PersistentHostQuotaUpdateTask> task( + new PersistentHostQuotaUpdateTask( + this, database_.get(), db_thread_, host, new_quota, callback)); + task->Start(); + } else { + callback->Run(kQuotaErrorInvalidAccess, host, -1); + delete callback; + } } void QuotaManager::LazyInitialize() { @@ -524,14 +635,9 @@ UsageTracker* QuotaManager::GetUsageTracker(StorageType type) const { void QuotaManager::DidGetTemporaryGlobalQuota(int64 quota) { temporary_global_quota_ = quota; - temporary_global_quota_callbacks_.Run(quota); -} - -void QuotaManager::DidGetPersistentHostQuota(const std::string& host, - int64 quota) { - DCHECK(persistent_host_quota_.find(host) == persistent_host_quota_.end()); - persistent_host_quota_[host] = quota; - persistent_host_quota_callbacks_.Run(host, host, quota); + temporary_global_quota_callbacks_.Run( + db_disabled_ ? kQuotaErrorInvalidAccess : kQuotaStatusOk, + quota); } void QuotaManager::DeleteOnCorrectThread() const { @@ -542,6 +648,19 @@ void QuotaManager::DeleteOnCorrectThread() const { delete this; } +void QuotaManager::GetGlobalUsage( + StorageType type, + UsageCallback* callback) { + LazyInitialize(); + GetUsageTracker(type)->GetGlobalUsage(callback); +} + +void QuotaManager::GetHostUsage(const std::string& host, StorageType type, + HostUsageCallback* callback) { + LazyInitialize(); + GetUsageTracker(type)->GetHostUsage(host, callback); +} + // QuotaManagerProxy ---------------------------------------------------------- void QuotaManagerProxy::RegisterClient(QuotaClient* client) { diff --git a/webkit/quota/quota_manager.h b/webkit/quota/quota_manager.h index 684d2b0..cac13f4 100644 --- a/webkit/quota/quota_manager.h +++ b/webkit/quota/quota_manager.h @@ -9,6 +9,7 @@ #include <deque> #include <list> #include <map> +#include <string> #include "base/basictypes.h" #include "base/callback.h" @@ -94,24 +95,28 @@ class QuotaManager : public QuotaTaskObserver, // Called by UI and internal modules. void GetTemporaryGlobalQuota(QuotaCallback* callback); - void SetTemporaryGlobalQuota(int64 new_quota); + void SetTemporaryGlobalQuota(int64 new_quota, QuotaCallback* callback); void GetPersistentHostQuota(const std::string& host, HostQuotaCallback* callback); - void SetPersistentHostQuota(const std::string& host, int64 new_quota); + void SetPersistentHostQuota(const std::string& host, + int64 new_quota, + HostQuotaCallback* callback); - // TODO(kinuko): Add more APIs for UI: - // - Get temporary global/per-host usage - // - Get persistent global/per-host usage + void GetGlobalUsage(StorageType type, UsageCallback* callback); + void GetHostUsage(const std::string& host, StorageType type, + HostUsageCallback* callback); - const static int64 kTemporaryStorageQuotaDefaultSize; - const static int64 kTemporaryStorageQuotaMaxSize; - const static char kDatabaseName[]; + static const int64 kTemporaryStorageQuotaDefaultSize; + static const int64 kTemporaryStorageQuotaMaxSize; + static const char kDatabaseName[]; - const static int64 kIncognitoDefaultTemporaryQuota; + static const int64 kIncognitoDefaultTemporaryQuota; private: class InitializeTask; class TemporaryGlobalQuotaUpdateTask; + class PersistentHostQuotaUpdateTask; + class PersistentHostQuotaQueryTask; class UsageAndQuotaDispatcherTask; class UsageAndQuotaDispatcherTaskForTemporary; @@ -138,7 +143,6 @@ class QuotaManager : public QuotaTaskObserver, UsageTracker* GetUsageTracker(StorageType type) const; void DidGetTemporaryGlobalQuota(int64 quota); - void DidGetPersistentHostQuota(const std::string& host, int64 quota); void DeleteOnCorrectThread() const; @@ -162,9 +166,6 @@ class QuotaManager : public QuotaTaskObserver, int64 temporary_global_quota_; QuotaCallbackQueue temporary_global_quota_callbacks_; - std::map<std::string, int64> persistent_host_quota_; - HostQuotaCallbackMap persistent_host_quota_callbacks_; - // Map from origin to count. std::map<GURL, int> origins_in_use_; diff --git a/webkit/quota/quota_manager_unittest.cc b/webkit/quota/quota_manager_unittest.cc index a590a68..fd6e671 100644 --- a/webkit/quota/quota_manager_unittest.cc +++ b/webkit/quota/quota_manager_unittest.cc @@ -2,10 +2,10 @@ // 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 <vector> +#include "testing/gtest/include/gtest/gtest.h" + #include "base/file_util.h" #include "base/memory/scoped_callback_factory.h" #include "base/memory/scoped_ptr.h" @@ -72,7 +72,7 @@ class QuotaManagerTest : public testing::Test { } void GetUsageAndQuota(const GURL& origin, StorageType type) { - status_ = kQuotaStatusUnknown; + quota_status_ = kQuotaStatusUnknown; usage_ = -1; quota_ = -1; quota_manager_->GetUsageAndQuota(origin, type, @@ -80,6 +80,52 @@ class QuotaManagerTest : public testing::Test { &QuotaManagerTest::DidGetUsageAndQuota)); } + void GetTemporaryGlobalQuota() { + quota_status_ = kQuotaStatusUnknown; + quota_ = -1; + quota_manager_->GetTemporaryGlobalQuota( + callback_factory_.NewCallback( + &QuotaManagerTest::DidGetQuota)); + } + + void SetTemporaryGlobalQuota(int64 new_quota) { + quota_status_ = kQuotaStatusUnknown; + quota_ = -1; + quota_manager_->SetTemporaryGlobalQuota(new_quota, + callback_factory_.NewCallback( + &QuotaManagerTest::DidGetQuota)); + } + + void GetPersistentHostQuota(const std::string& host) { + quota_status_ = kQuotaStatusUnknown; + quota_ = -1; + quota_manager_->GetPersistentHostQuota(host, + callback_factory_.NewCallback( + &QuotaManagerTest::DidGetHostQuota)); + } + + void SetPersistentHostQuota(const std::string& host, int64 new_quota) { + quota_status_ = kQuotaStatusUnknown; + quota_ = -1; + quota_manager_->SetPersistentHostQuota(host, new_quota, + callback_factory_.NewCallback( + &QuotaManagerTest::DidGetHostQuota)); + } + + void GetGlobalUsage(StorageType type) { + usage_ = -1; + quota_manager_->GetGlobalUsage(type, + callback_factory_.NewCallback( + &QuotaManagerTest::DidGetGlobalUsage)); + } + + void GetHostUsage(const std::string& host, StorageType type) { + usage_ = -1; + quota_manager_->GetHostUsage(host, type, + callback_factory_.NewCallback( + &QuotaManagerTest::DidGetHostUsage)); + } + void RunAdditionalUsageAndQuotaTask(const GURL& origin, StorageType type) { quota_manager_->GetUsageAndQuota(origin, type, callback_factory_.NewCallback( @@ -87,11 +133,31 @@ class QuotaManagerTest : public testing::Test { } void DidGetUsageAndQuota(QuotaStatusCode status, int64 usage, int64 quota) { - status_ = status; + quota_status_ = status; usage_ = usage; quota_ = quota; } + void DidGetQuota(QuotaStatusCode status, int64 quota) { + quota_status_ = status; + quota_ = quota; + } + + void DidGetHostQuota(QuotaStatusCode status, + const std::string& host, int64 quota) { + quota_status_ = status; + host_ = host; + quota_ = quota; + } + + void DidGetGlobalUsage(int64 usage) { + usage_ = usage; + } + + void DidGetHostUsage(const std::string&, int64 usage) { + usage_ = usage; + } + void set_additional_callback_count(int c) { additional_callback_count_ = c; } int additional_callback_count() const { return additional_callback_count_; } void DidGetUsageAndQuotaAdditional( @@ -104,7 +170,7 @@ class QuotaManagerTest : public testing::Test { quota_manager_ = quota_manager; } - QuotaStatusCode status() const { return status_; } + QuotaStatusCode status() const { return quota_status_; } int64 usage() const { return usage_; } int64 quota() const { return quota_; } @@ -114,7 +180,8 @@ class QuotaManagerTest : public testing::Test { scoped_refptr<QuotaManager> quota_manager_; - QuotaStatusCode status_; + QuotaStatusCode quota_status_; + std::string host_; int64 usage_; int64 quota_; @@ -123,19 +190,25 @@ class QuotaManagerTest : public testing::Test { DISALLOW_COPY_AND_ASSIGN(QuotaManagerTest); }; -TEST_F(QuotaManagerTest, GetTemporaryUsageAndQuota_Simple) { - const static MockOriginData kData[] = { +TEST_F(QuotaManagerTest, GetUsageAndQuota_Simple) { + static const MockOriginData kData[] = { { "http://foo.com/", kStorageTypeTemporary, 10 }, { "http://foo.com/", kStorageTypePersistent, 80 }, }; RegisterClient(CreateClient(kData, ARRAYSIZE_UNSAFE(kData))); + GetUsageAndQuota(GURL("http://foo.com/"), kStorageTypePersistent); + MessageLoop::current()->RunAllPending(); + EXPECT_EQ(kQuotaStatusOk, status()); + EXPECT_EQ(80, usage()); + EXPECT_EQ(0, quota()); + GetUsageAndQuota(GURL("http://foo.com/"), kStorageTypeTemporary); MessageLoop::current()->RunAllPending(); EXPECT_EQ(kQuotaStatusOk, status()); EXPECT_EQ(10, usage()); - EXPECT_GT(quota(), 0); - EXPECT_LE(quota(), QuotaManager::kTemporaryStorageQuotaMaxSize); + EXPECT_LE(0, quota()); + EXPECT_GE(QuotaManager::kTemporaryStorageQuotaMaxSize, quota()); int64 quota_returned_for_foo = quota(); GetUsageAndQuota(GURL("http://bar.com/"), kStorageTypeTemporary); @@ -145,23 +218,65 @@ TEST_F(QuotaManagerTest, GetTemporaryUsageAndQuota_Simple) { EXPECT_EQ(quota_returned_for_foo - 10, quota()); } -TEST_F(QuotaManagerTest, GetTemporaryUsage_NoClient) { +TEST_F(QuotaManagerTest, GetUsage_NoClient) { GetUsageAndQuota(GURL("http://foo.com/"), kStorageTypeTemporary); MessageLoop::current()->RunAllPending(); EXPECT_EQ(kQuotaStatusOk, status()); EXPECT_EQ(0, usage()); + + GetUsageAndQuota(GURL("http://foo.com/"), kStorageTypePersistent); + MessageLoop::current()->RunAllPending(); + EXPECT_EQ(kQuotaStatusOk, status()); + EXPECT_EQ(0, usage()); + + GetHostUsage("foo.com", kStorageTypeTemporary); + MessageLoop::current()->RunAllPending(); + EXPECT_EQ(0, usage()); + + GetHostUsage("foo.com", kStorageTypePersistent); + MessageLoop::current()->RunAllPending(); + EXPECT_EQ(0, usage()); + + GetGlobalUsage(kStorageTypeTemporary); + MessageLoop::current()->RunAllPending(); + EXPECT_EQ(0, usage()); + + GetGlobalUsage(kStorageTypePersistent); + MessageLoop::current()->RunAllPending(); + EXPECT_EQ(0, usage()); } -TEST_F(QuotaManagerTest, GetTemporaryUsage_EmptyClient) { +TEST_F(QuotaManagerTest, GetUsage_EmptyClient) { RegisterClient(CreateClient(NULL, 0)); GetUsageAndQuota(GURL("http://foo.com/"), kStorageTypeTemporary); MessageLoop::current()->RunAllPending(); EXPECT_EQ(kQuotaStatusOk, status()); EXPECT_EQ(0, usage()); + + GetUsageAndQuota(GURL("http://foo.com/"), kStorageTypePersistent); + MessageLoop::current()->RunAllPending(); + EXPECT_EQ(kQuotaStatusOk, status()); + EXPECT_EQ(0, usage()); + + GetHostUsage("foo.com", kStorageTypeTemporary); + MessageLoop::current()->RunAllPending(); + EXPECT_EQ(0, usage()); + + GetHostUsage("foo.com", kStorageTypePersistent); + MessageLoop::current()->RunAllPending(); + EXPECT_EQ(0, usage()); + + GetGlobalUsage(kStorageTypeTemporary); + MessageLoop::current()->RunAllPending(); + EXPECT_EQ(0, usage()); + + GetGlobalUsage(kStorageTypePersistent); + MessageLoop::current()->RunAllPending(); + EXPECT_EQ(0, usage()); } TEST_F(QuotaManagerTest, GetTemporaryUsageAndQuota_MultiOrigins) { - const static MockOriginData kData[] = { + static const MockOriginData kData[] = { { "http://foo.com/", kStorageTypeTemporary, 10 }, { "http://foo.com:8080/", kStorageTypeTemporary, 20 }, { "http://bar.com/", kStorageTypeTemporary, 5 }, @@ -172,7 +287,10 @@ TEST_F(QuotaManagerTest, GetTemporaryUsageAndQuota_MultiOrigins) { RegisterClient(CreateClient(kData, ARRAYSIZE_UNSAFE(kData))); // This time explicitly sets a temporary global quota. - quota_manager()->SetTemporaryGlobalQuota(100); + SetTemporaryGlobalQuota(100); + MessageLoop::current()->RunAllPending(); + EXPECT_EQ(kQuotaStatusOk, status()); + EXPECT_EQ(100, quota()); GetUsageAndQuota(GURL("http://foo.com/"), kStorageTypeTemporary); MessageLoop::current()->RunAllPending(); @@ -189,12 +307,13 @@ TEST_F(QuotaManagerTest, GetTemporaryUsageAndQuota_MultiOrigins) { EXPECT_EQ(100 - (10 + 20 + 30), quota()); } -TEST_F(QuotaManagerTest, GetTemporaryUsage_MultipleClients) { - const static MockOriginData kData1[] = { +TEST_F(QuotaManagerTest, GetUsage_MultipleClients) { + static const MockOriginData kData1[] = { { "http://foo.com/", kStorageTypeTemporary, 10 }, { "http://bar.com/", kStorageTypeTemporary, 20 }, + { "http://bar.com/", kStorageTypePersistent, 50 }, }; - const static MockOriginData kData2[] = { + static const MockOriginData kData2[] = { { "https://foo.com/", kStorageTypeTemporary, 30 }, { "http://example.com/", kStorageTypePersistent, 40 }, }; @@ -205,10 +324,25 @@ TEST_F(QuotaManagerTest, GetTemporaryUsage_MultipleClients) { MessageLoop::current()->RunAllPending(); EXPECT_EQ(kQuotaStatusOk, status()); EXPECT_EQ(10 + 30, usage()); + + GetUsageAndQuota(GURL("http://bar.com/"), kStorageTypePersistent); + MessageLoop::current()->RunAllPending(); + EXPECT_EQ(kQuotaStatusOk, status()); + EXPECT_EQ(50, usage()); + + GetGlobalUsage(kStorageTypeTemporary); + MessageLoop::current()->RunAllPending(); + EXPECT_EQ(kQuotaStatusOk, status()); + EXPECT_EQ(10 + 20 + 30, usage()); + + GetGlobalUsage(kStorageTypePersistent); + MessageLoop::current()->RunAllPending(); + EXPECT_EQ(kQuotaStatusOk, status()); + EXPECT_EQ(40 + 50, usage()); } TEST_F(QuotaManagerTest, GetTemporaryUsage_WithModify) { - const static MockOriginData kData[] = { + static const MockOriginData kData[] = { { "http://foo.com/", kStorageTypeTemporary, 10 }, { "http://foo.com:1/", kStorageTypeTemporary, 20 }, }; @@ -239,14 +373,14 @@ TEST_F(QuotaManagerTest, GetTemporaryUsage_WithModify) { } TEST_F(QuotaManagerTest, GetTemporaryUsageAndQuota_WithAdditionalTasks) { - const static MockOriginData kData[] = { + static const MockOriginData kData[] = { { "http://foo.com/", kStorageTypeTemporary, 10 }, { "http://foo.com:8080/", kStorageTypeTemporary, 20 }, { "http://bar.com/", kStorageTypeTemporary, 13 }, { "http://foo.com/", kStorageTypePersistent, 40 }, }; RegisterClient(CreateClient(kData, ARRAYSIZE_UNSAFE(kData))); - quota_manager()->SetTemporaryGlobalQuota(100); + SetTemporaryGlobalQuota(100); GetUsageAndQuota(GURL("http://foo.com/"), kStorageTypeTemporary); GetUsageAndQuota(GURL("http://foo.com/"), kStorageTypeTemporary); @@ -270,14 +404,14 @@ TEST_F(QuotaManagerTest, GetTemporaryUsageAndQuota_WithAdditionalTasks) { } TEST_F(QuotaManagerTest, GetTemporaryUsageAndQuota_NukeManager) { - const static MockOriginData kData[] = { + static const MockOriginData kData[] = { { "http://foo.com/", kStorageTypeTemporary, 10 }, { "http://foo.com:8080/", kStorageTypeTemporary, 20 }, { "http://bar.com/", kStorageTypeTemporary, 13 }, { "http://foo.com/", kStorageTypePersistent, 40 }, }; RegisterClient(CreateClient(kData, ARRAYSIZE_UNSAFE(kData))); - quota_manager()->SetTemporaryGlobalQuota(100); + SetTemporaryGlobalQuota(100); set_additional_callback_count(0); GetUsageAndQuota(GURL("http://foo.com/"), kStorageTypeTemporary); @@ -314,4 +448,223 @@ TEST_F(QuotaManagerTest, OriginInUse) { EXPECT_FALSE(quota_manager()->IsOriginInUse(kFooOrigin)); } +TEST_F(QuotaManagerTest, GetAndSetPerststentHostQuota) { + RegisterClient(CreateClient(NULL, 0)); + + GetPersistentHostQuota("foo.com"); + MessageLoop::current()->RunAllPending(); + EXPECT_EQ(0, quota()); + + SetPersistentHostQuota("foo.com", 100); + MessageLoop::current()->RunAllPending(); + EXPECT_EQ(100, quota()); + + GetPersistentHostQuota("foo.com"); + SetPersistentHostQuota("foo.com", 200); + GetPersistentHostQuota("foo.com"); + SetPersistentHostQuota("foo.com", 300); + GetPersistentHostQuota("foo.com"); + MessageLoop::current()->RunAllPending(); + EXPECT_EQ(300, quota()); +} + +TEST_F(QuotaManagerTest, GetAndSetPersistentUsageAndQuota) { + RegisterClient(CreateClient(NULL, 0)); + + GetUsageAndQuota(GURL("http://foo.com/"), kStorageTypePersistent); + MessageLoop::current()->RunAllPending(); + EXPECT_EQ(kQuotaStatusOk, status()); + EXPECT_EQ(0, usage()); + EXPECT_EQ(0, quota()); + + SetPersistentHostQuota("foo.com", 100); + GetUsageAndQuota(GURL("http://foo.com/"), kStorageTypePersistent); + MessageLoop::current()->RunAllPending(); + EXPECT_EQ(kQuotaStatusOk, status()); + EXPECT_EQ(0, usage()); + EXPECT_EQ(100, quota()); +} + +TEST_F(QuotaManagerTest, GetPersistentUsageAndQuota_MultiOrigins) { + static const MockOriginData kData[] = { + { "http://foo.com/", kStorageTypePersistent, 10 }, + { "http://foo.com:8080/", kStorageTypePersistent, 20 }, + { "https://foo.com/", kStorageTypePersistent, 13 }, + { "https://foo.com:8081/", kStorageTypePersistent, 19 }, + { "http://bar.com/", kStorageTypePersistent, 5 }, + { "https://bar.com/", kStorageTypePersistent, 7 }, + { "http://baz.com/", kStorageTypePersistent, 30 }, + { "http://foo.com/", kStorageTypeTemporary, 40 }, + }; + RegisterClient(CreateClient(kData, ARRAYSIZE_UNSAFE(kData))); + + SetPersistentHostQuota("foo.com", 100); + GetUsageAndQuota(GURL("http://foo.com/"), kStorageTypePersistent); + MessageLoop::current()->RunAllPending(); + EXPECT_EQ(kQuotaStatusOk, status()); + EXPECT_EQ(10 + 20 + 13 + 19, usage()); + EXPECT_EQ(100, quota()); +} + +TEST_F(QuotaManagerTest, GetPersistentUsage_WithModify) { + static const MockOriginData kData[] = { + { "http://foo.com/", kStorageTypePersistent, 10 }, + { "http://foo.com:1/", kStorageTypePersistent, 20 }, + }; + MockStorageClient* client = CreateClient(kData, ARRAYSIZE_UNSAFE(kData)); + RegisterClient(client); + + GetUsageAndQuota(GURL("http://foo.com/"), kStorageTypePersistent); + MessageLoop::current()->RunAllPending(); + EXPECT_EQ(kQuotaStatusOk, status()); + EXPECT_EQ(10 + 20, usage()); + + client->ModifyMockOriginDataSize( + GURL("http://foo.com/"), kStorageTypePersistent, 20); + client->ModifyMockOriginDataSize( + GURL("http://foo.com:1/"), kStorageTypePersistent, -5); + client->ModifyMockOriginDataSize( + GURL("http://bar.com/"), kStorageTypePersistent, 33); + + GetUsageAndQuota(GURL("http://foo.com/"), kStorageTypePersistent); + MessageLoop::current()->RunAllPending(); + EXPECT_EQ(kQuotaStatusOk, status()); + EXPECT_EQ(10 + 20 + 20 - 5, usage()); + + GetUsageAndQuota(GURL("http://bar.com/"), kStorageTypePersistent); + MessageLoop::current()->RunAllPending(); + EXPECT_EQ(kQuotaStatusOk, status()); + EXPECT_EQ(33, usage()); +} + +TEST_F(QuotaManagerTest, GetPersistentUsageAndQuota_WithAdditionalTasks) { + static const MockOriginData kData[] = { + { "http://foo.com/", kStorageTypePersistent, 10 }, + { "http://foo.com:8080/", kStorageTypePersistent, 20 }, + { "http://bar.com/", kStorageTypePersistent, 13 }, + { "http://foo.com/", kStorageTypeTemporary, 40 }, + }; + RegisterClient(CreateClient(kData, ARRAYSIZE_UNSAFE(kData))); + SetPersistentHostQuota("foo.com", 100); + + GetUsageAndQuota(GURL("http://foo.com/"), kStorageTypePersistent); + GetUsageAndQuota(GURL("http://foo.com/"), kStorageTypePersistent); + GetUsageAndQuota(GURL("http://foo.com/"), kStorageTypePersistent); + MessageLoop::current()->RunAllPending(); + EXPECT_EQ(kQuotaStatusOk, status()); + EXPECT_EQ(10 + 20, usage()); + EXPECT_EQ(100, quota()); + + set_additional_callback_count(0); + RunAdditionalUsageAndQuotaTask(GURL("http://foo.com/"), + kStorageTypePersistent); + GetUsageAndQuota(GURL("http://foo.com/"), kStorageTypePersistent); + RunAdditionalUsageAndQuotaTask(GURL("http://bar.com/"), + kStorageTypePersistent); + MessageLoop::current()->RunAllPending(); + EXPECT_EQ(kQuotaStatusOk, status()); + EXPECT_EQ(10 + 20, usage()); + EXPECT_EQ(2, additional_callback_count()); +} + +TEST_F(QuotaManagerTest, GetPersistentUsageAndQuota_NukeManager) { + static const MockOriginData kData[] = { + { "http://foo.com/", kStorageTypePersistent, 10 }, + { "http://foo.com:8080/", kStorageTypePersistent, 20 }, + { "http://bar.com/", kStorageTypePersistent, 13 }, + { "http://foo.com/", kStorageTypeTemporary, 40 }, + }; + RegisterClient(CreateClient(kData, ARRAYSIZE_UNSAFE(kData))); + SetPersistentHostQuota("foo.com", 100); + + set_additional_callback_count(0); + GetUsageAndQuota(GURL("http://foo.com/"), kStorageTypePersistent); + RunAdditionalUsageAndQuotaTask(GURL("http://foo.com/"), + kStorageTypePersistent); + RunAdditionalUsageAndQuotaTask(GURL("http://bar.com/"), + kStorageTypePersistent); + + // Nuke before waiting for callbacks. + set_quota_manager(NULL); + MessageLoop::current()->RunAllPending(); + EXPECT_EQ(kQuotaErrorAbort, status()); +} + +TEST_F(QuotaManagerTest, GetUsage_Simple) { + static const MockOriginData kData[] = { + { "http://foo.com/", kStorageTypePersistent, 1 }, + { "http://foo.com:1/", kStorageTypePersistent, 20 }, + { "http://bar.com/", kStorageTypeTemporary, 300 }, + { "https://buz.com/", kStorageTypeTemporary, 4000 }, + { "http://buz.com/", kStorageTypeTemporary, 50000 }, + { "http://bar.com:1/", kStorageTypePersistent, 600000 }, + { "http://foo.com/", kStorageTypeTemporary, 7000000 }, + }; + RegisterClient(CreateClient(kData, ARRAYSIZE_UNSAFE(kData))); + + GetGlobalUsage(kStorageTypePersistent); + MessageLoop::current()->RunAllPending(); + EXPECT_EQ(usage(), 1 + 20 + 600000); + + GetGlobalUsage(kStorageTypeTemporary); + MessageLoop::current()->RunAllPending(); + EXPECT_EQ(usage(), 300 + 4000 + 50000 + 7000000); + + GetHostUsage("foo.com", kStorageTypePersistent); + MessageLoop::current()->RunAllPending(); + EXPECT_EQ(usage(), 1 + 20); + + GetHostUsage("buz.com", kStorageTypeTemporary); + MessageLoop::current()->RunAllPending(); + EXPECT_EQ(usage(), 4000 + 50000); +} + +TEST_F(QuotaManagerTest, GetUsage_WithModification) { + static const MockOriginData kData[] = { + { "http://foo.com/", kStorageTypePersistent, 1 }, + { "http://foo.com:1/", kStorageTypePersistent, 20 }, + { "http://bar.com/", kStorageTypeTemporary, 300 }, + { "https://buz.com/", kStorageTypeTemporary, 4000 }, + { "http://buz.com/", kStorageTypeTemporary, 50000 }, + { "http://bar.com:1/", kStorageTypePersistent, 600000 }, + { "http://foo.com/", kStorageTypeTemporary, 7000000 }, + }; + + MockStorageClient* client = CreateClient(kData, ARRAYSIZE_UNSAFE(kData)); + RegisterClient(client); + + GetGlobalUsage(kStorageTypePersistent); + MessageLoop::current()->RunAllPending(); + EXPECT_EQ(usage(), 1 + 20 + 600000); + + client->ModifyMockOriginDataSize( + GURL("http://foo.com/"), kStorageTypePersistent, 80000000); + + GetGlobalUsage(kStorageTypePersistent); + MessageLoop::current()->RunAllPending(); + EXPECT_EQ(usage(), 1 + 20 + 600000 + 80000000); + + GetGlobalUsage(kStorageTypeTemporary); + MessageLoop::current()->RunAllPending(); + EXPECT_EQ(usage(), 300 + 4000 + 50000 + 7000000); + + client->ModifyMockOriginDataSize( + GURL("http://foo.com/"), kStorageTypeTemporary, 1); + + GetGlobalUsage(kStorageTypeTemporary); + MessageLoop::current()->RunAllPending(); + EXPECT_EQ(usage(), 300 + 4000 + 50000 + 7000000 + 1); + + GetHostUsage("buz.com", kStorageTypeTemporary); + MessageLoop::current()->RunAllPending(); + EXPECT_EQ(usage(), 4000 + 50000); + + client->ModifyMockOriginDataSize( + GURL("http://buz.com/"), kStorageTypeTemporary, 900000000); + + GetHostUsage("buz.com", kStorageTypeTemporary); + MessageLoop::current()->RunAllPending(); + EXPECT_EQ(usage(), 4000 + 50000 + 900000000); +} + } // namespace quota diff --git a/webkit/quota/quota_task.cc b/webkit/quota/quota_task.cc index b9872fe..78a8b36 100644 --- a/webkit/quota/quota_task.cc +++ b/webkit/quota/quota_task.cc @@ -7,6 +7,7 @@ #include <algorithm> #include <functional> +#include "base/message_loop.h" #include "base/message_loop_proxy.h" using base::MessageLoopProxy; @@ -15,11 +16,6 @@ namespace quota { // QuotaTask --------------------------------------------------------------- -QuotaTask::QuotaTask(QuotaTaskObserver* observer) - : observer_(observer), - original_message_loop_(MessageLoopProxy::CreateForCurrentThread()) { -} - QuotaTask::~QuotaTask() { } @@ -29,6 +25,11 @@ void QuotaTask::Start() { Run(); } +QuotaTask::QuotaTask(QuotaTaskObserver* observer) + : observer_(observer), + original_message_loop_(MessageLoopProxy::CreateForCurrentThread()) { +} + void QuotaTask::CallCompleted() { DCHECK(original_message_loop_->BelongsToCurrentThread()); if (observer_) { @@ -43,6 +44,10 @@ void QuotaTask::Abort() { Aborted(); } +void QuotaTask::DeleteSoon() { + MessageLoop::current()->DeleteSoon(FROM_HERE, this); +} + // QuotaThreadTask --------------------------------------------------------- QuotaThreadTask::QuotaThreadTask( diff --git a/webkit/quota/quota_task.h b/webkit/quota/quota_task.h index f866743..860ec0d 100644 --- a/webkit/quota/quota_task.h +++ b/webkit/quota/quota_task.h @@ -24,11 +24,11 @@ class QuotaTaskObserver; // A base class for quota tasks. class QuotaTask { public: + virtual ~QuotaTask(); void Start(); protected: - QuotaTask(QuotaTaskObserver* observer); - virtual ~QuotaTask(); + explicit QuotaTask(QuotaTaskObserver* observer); // The task body. virtual void Run() = 0; @@ -40,6 +40,10 @@ class QuotaTask { virtual void Aborted() {} void CallCompleted(); + + // Call this to delete itself. + void DeleteSoon(); + QuotaTaskObserver* observer() const { return observer_; } scoped_refptr<base::MessageLoopProxy> original_message_loop() const { return original_message_loop_; @@ -93,7 +97,6 @@ class QuotaTaskObserver { typedef std::set<QuotaTask*> TaskSet; TaskSet running_quota_tasks_; }; - } #endif // WEBKIT_QUOTA_QUOTA_TASK_H_ diff --git a/webkit/quota/quota_types.h b/webkit/quota/quota_types.h index 2d42440..7356b70e 100644 --- a/webkit/quota/quota_types.h +++ b/webkit/quota/quota_types.h @@ -22,19 +22,26 @@ enum StorageType { kStorageTypeUnknown, }; +// TODO(tzik): Add assertions to +// content/browser/renderer_host/quota_dispatcher_host.cc +// ref) third_party/WebKit/Source/WebCore/dom/ExceptionCode.h, enum QuotaStatusCode { kQuotaStatusOk = 0, - kQuotaErrorNotSupported = 9, - kQuotaErrorAbort = 20, + kQuotaErrorNotSupported = 9, // NOT_SUPPORTED_ERR + kQuotaErrorInvalidModification = 13, // INVALID_MODIFICATION_ERR + kQuotaErrorInvalidAccess = 15, // INVALID_ACCESS_ERR + kQuotaErrorAbort = 20, // ABORT_ERR kQuotaStatusUnknown = -1, }; // Common callback types that are used throughout in the quota module. typedef Callback1<int64>::Type UsageCallback; -typedef Callback1<int64>::Type QuotaCallback; +typedef Callback2<QuotaStatusCode, + int64>::Type QuotaCallback; typedef Callback2<const std::string& /* host */, int64>::Type HostUsageCallback; -typedef Callback2<const std::string& /* host */, +typedef Callback3<QuotaStatusCode, + const std::string& /* host */, int64>::Type HostQuotaCallback; // Simple template wrapper for a callback queue. @@ -93,8 +100,24 @@ class CallbackQueue2 : public CallbackQueueBase<CallbackType2> { } }; +template <typename CallbackType3, typename A1, typename A2, typename A3> +class CallbackQueue3 : public CallbackQueueBase<CallbackType3> { + public: + typedef typename CallbackQueueBase<CallbackType3>::Queue Queue; + // Runs the callbacks added to the queue and clears the queue. + void Run(A1 arg1, A2 arg2, A3 arg3) { + for (typename Queue::iterator iter = this->callbacks_.begin(); + iter != this->callbacks_.end(); ++iter) { + (*iter)->Run(arg1, arg2, arg3); + delete *iter; + } + this->callbacks_.clear(); + } +}; + typedef CallbackQueue1<UsageCallback*, int64> UsageCallbackQueue; -typedef CallbackQueue1<QuotaCallback*, int64> QuotaCallbackQueue; +typedef CallbackQueue2<QuotaCallback*, + QuotaStatusCode, int64> QuotaCallbackQueue; template <typename CallbackType, typename CallbackQueueType, typename KEY> class CallbackQueueMapBase { @@ -165,9 +188,35 @@ class CallbackQueueMap2 } }; +template <typename CallbackType3, typename KEY, + typename ARG1, typename ARG2, typename ARG3> +class CallbackQueueMap3 + : public CallbackQueueMapBase<CallbackType3, + CallbackQueue3<CallbackType3, + ARG1, ARG2, ARG3>, + KEY> { + public: + typedef typename CallbackQueueMapBase< + CallbackType3, + CallbackQueue3<CallbackType3, ARG1, ARG2, ARG3>, + KEY>::iterator iterator; + typedef CallbackQueue3<CallbackType3, ARG1, ARG2, ARG3> Queue; + + // Runs the callbacks added for the given |key| and clears the key + // from the map. + void Run(const KEY& key, ARG1 arg1, ARG2 arg2, ARG3 arg3) { + if (!this->HasCallbacks(key)) + return; + Queue& queue = this->callback_map_[key]; + queue.Run(arg1, arg2, arg3); + this->callback_map_.erase(key); + } +}; + typedef CallbackQueueMap2<HostUsageCallback*, std::string, const std::string&, int64> HostUsageCallbackMap; -typedef CallbackQueueMap2<HostUsageCallback*, std::string, +typedef CallbackQueueMap3<HostQuotaCallback*, std::string, + QuotaStatusCode, const std::string&, int64> HostQuotaCallbackMap; } // namespace quota diff --git a/webkit/quota/usage_tracker.cc b/webkit/quota/usage_tracker.cc index 52d9782..f9c9a77 100644 --- a/webkit/quota/usage_tracker.cc +++ b/webkit/quota/usage_tracker.cc @@ -5,6 +5,8 @@ #include "webkit/quota/usage_tracker.h" #include <deque> +#include <set> +#include <string> #include "base/message_loop_proxy.h" #include "base/stl_util-inl.h" @@ -39,7 +41,7 @@ class ClientUsageTracker::GatherUsageTaskBase : public QuotaTask { if (origins_to_process.empty()) { // Nothing to be done. CallCompleted(); - delete this; + DeleteSoon(); } for (std::set<GURL>::const_iterator iter = origins_to_process.begin(); iter != origins_to_process.end(); @@ -59,7 +61,7 @@ class ClientUsageTracker::GatherUsageTaskBase : public QuotaTask { protected: virtual void Aborted() OVERRIDE { - delete this; + DeleteSoon(); } UsageTracker* tracker() const { return tracker_; } @@ -80,7 +82,7 @@ class ClientUsageTracker::GatherUsageTaskBase : public QuotaTask { if (pending_origins_.empty()) { // We're done. CallCompleted(); - delete this; + DeleteSoon(); } } @@ -121,7 +123,7 @@ class ClientUsageTracker::GatherGlobalUsageTask client_tracker()->DidGetGlobalUsage(origin_usage_map()); } -private: + private: QuotaClient* client_; base::ScopedCallbackFactory<GatherUsageTaskBase> callback_factory_; |