summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormichaeln@google.com <michaeln@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2011-05-10 21:43:35 +0000
committermichaeln@google.com <michaeln@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2011-05-10 21:43:35 +0000
commit3bbe097b9a6e516d3f1f60bec571033820038b3b (patch)
tree7f0f727d11437ee9031fa9f39491de4da21288e0
parent3b06fe1d485105136c5c958d1cb27a3bb4277d16 (diff)
downloadchromium_src-3bbe097b9a6e516d3f1f60bec571033820038b3b.zip
chromium_src-3bbe097b9a6e516d3f1f60bec571033820038b3b.tar.gz
chromium_src-3bbe097b9a6e516d3f1f60bec571033820038b3b.tar.bz2
Implementation of DatabaseQuotaClient for the WebSQLDatabase system.
In this CL the the 'client' interface is implemented, but the QuotaManager is not notified of changes as they occur, and the hard-coded 5MB limits imposed by the DB system are still being used. BUG=61676 TEST=database_quota_client_unittest.cc Review URL: http://codereview.chromium.org/6904111 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@84865 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/profiles/profile.cc10
-rw-r--r--chrome/browser/profiles/profile_impl.cc10
-rw-r--r--chrome/test/testing_profile.cc2
-rw-r--r--webkit/database/database_quota_client.cc218
-rw-r--r--webkit/database/database_quota_client.h81
-rw-r--r--webkit/database/database_quota_client_unittest.cc218
-rw-r--r--webkit/database/database_tracker.cc78
-rw-r--r--webkit/database/database_tracker.h24
-rw-r--r--webkit/database/database_tracker_unittest.cc6
-rw-r--r--webkit/database/webkit_database.gypi3
-rw-r--r--webkit/support/simple_database_system.cc2
-rw-r--r--webkit/tools/test_shell/test_shell.gypi1
12 files changed, 629 insertions, 24 deletions
diff --git a/chrome/browser/profiles/profile.cc b/chrome/browser/profiles/profile.cc
index bcb812a..20e84ee 100644
--- a/chrome/browser/profiles/profile.cc
+++ b/chrome/browser/profiles/profile.cc
@@ -287,10 +287,7 @@ class OffTheRecordProfileImpl : public Profile,
}
virtual webkit_database::DatabaseTracker* GetDatabaseTracker() {
- if (!db_tracker_.get()) {
- db_tracker_ = new webkit_database::DatabaseTracker(
- GetPath(), IsOffTheRecord(), GetExtensionSpecialStoragePolicy());
- }
+ CreateQuotaManagerAndClients();
return db_tracker_;
}
@@ -699,6 +696,7 @@ class OffTheRecordProfileImpl : public Profile,
void CreateQuotaManagerAndClients() {
if (quota_manager_.get()) {
DCHECK(file_system_context_.get());
+ DCHECK(db_tracker_.get());
return;
}
@@ -718,6 +716,10 @@ class OffTheRecordProfileImpl : public Profile,
GetPath(), IsOffTheRecord(),
GetExtensionSpecialStoragePolicy(),
quota_manager_->proxy());
+ db_tracker_ = new webkit_database::DatabaseTracker(
+ GetPath(), IsOffTheRecord(), GetExtensionSpecialStoragePolicy(),
+ quota_manager_->proxy(),
+ BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE));
}
NotificationRegistrar registrar_;
diff --git a/chrome/browser/profiles/profile_impl.cc b/chrome/browser/profiles/profile_impl.cc
index ae2a519..e168882 100644
--- a/chrome/browser/profiles/profile_impl.cc
+++ b/chrome/browser/profiles/profile_impl.cc
@@ -727,10 +727,7 @@ ChromeAppCacheService* ProfileImpl::GetAppCacheService() {
}
webkit_database::DatabaseTracker* ProfileImpl::GetDatabaseTracker() {
- if (!db_tracker_) {
- db_tracker_ = new webkit_database::DatabaseTracker(
- GetPath(), IsOffTheRecord(), GetExtensionSpecialStoragePolicy());
- }
+ CreateQuotaManagerAndClients();
return db_tracker_;
}
@@ -1273,6 +1270,7 @@ ExtensionPrefValueMap* ProfileImpl::GetExtensionPrefValueMap() {
void ProfileImpl::CreateQuotaManagerAndClients() {
if (quota_manager_.get()) {
DCHECK(file_system_context_.get());
+ DCHECK(db_tracker_.get());
return;
}
@@ -1292,6 +1290,10 @@ void ProfileImpl::CreateQuotaManagerAndClients() {
GetPath(), IsOffTheRecord(),
GetExtensionSpecialStoragePolicy(),
quota_manager_->proxy());
+ db_tracker_ = new webkit_database::DatabaseTracker(
+ GetPath(), IsOffTheRecord(), GetExtensionSpecialStoragePolicy(),
+ quota_manager_->proxy(),
+ BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE));
}
WebKitContext* ProfileImpl::GetWebKitContext() {
diff --git a/chrome/test/testing_profile.cc b/chrome/test/testing_profile.cc
index 06c08d6..1dd64b4 100644
--- a/chrome/test/testing_profile.cc
+++ b/chrome/test/testing_profile.cc
@@ -417,7 +417,7 @@ ChromeAppCacheService* TestingProfile::GetAppCacheService() {
webkit_database::DatabaseTracker* TestingProfile::GetDatabaseTracker() {
if (!db_tracker_) {
db_tracker_ = new webkit_database::DatabaseTracker(
- GetPath(), false, GetExtensionSpecialStoragePolicy());
+ GetPath(), false, GetExtensionSpecialStoragePolicy(), NULL, NULL);
}
return db_tracker_;
}
diff --git a/webkit/database/database_quota_client.cc b/webkit/database/database_quota_client.cc
new file mode 100644
index 0000000..4f3da01
--- /dev/null
+++ b/webkit/database/database_quota_client.cc
@@ -0,0 +1,218 @@
+// 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.
+
+#include "webkit/database/database_quota_client.h"
+
+#include "base/message_loop_proxy.h"
+#include "net/base/net_util.h"
+#include "webkit/database/database_tracker.h"
+#include "webkit/database/database_util.h"
+
+using quota::QuotaClient;
+
+namespace webkit_database {
+
+// Helper tasks ---------------------------------------------------------------
+
+class DatabaseQuotaClient::HelperTask : public quota::QuotaThreadTask {
+ protected:
+ HelperTask(
+ DatabaseQuotaClient* client,
+ scoped_refptr<base::MessageLoopProxy> db_tracker_thread)
+ : QuotaThreadTask(client, db_tracker_thread),
+ client_(client), db_tracker_(client->db_tracker_) {
+ }
+
+ DatabaseQuotaClient* client_;
+ scoped_refptr<DatabaseTracker> db_tracker_;
+};
+
+class DatabaseQuotaClient::GetOriginUsageTask : public HelperTask {
+ public:
+ GetOriginUsageTask(
+ DatabaseQuotaClient* client,
+ scoped_refptr<base::MessageLoopProxy> db_tracker_thread,
+ const GURL& origin_url)
+ : HelperTask(client, db_tracker_thread),
+ origin_url_(origin_url), usage_(0) {
+ }
+
+ private:
+ virtual void RunOnTargetThread() OVERRIDE {
+ OriginInfo info;
+ if (db_tracker_->GetOriginInfo(
+ DatabaseUtil::GetOriginIdentifier(origin_url_),
+ &info)) {
+ usage_ = info.TotalSize();
+ }
+ }
+ virtual void Completed() OVERRIDE {
+ client_->DidGetOriginUsage(origin_url_, usage_);
+ }
+ GURL origin_url_;
+ int64 usage_;
+};
+
+class DatabaseQuotaClient::GetOriginsTaskBase : public HelperTask {
+ protected:
+ GetOriginsTaskBase(
+ DatabaseQuotaClient* client,
+ scoped_refptr<base::MessageLoopProxy> db_tracker_thread)
+ : HelperTask(client, db_tracker_thread) {
+ }
+
+ virtual bool ShouldAddOrigin(const GURL& origin) = 0;
+
+ virtual void RunOnTargetThread() OVERRIDE {
+ std::vector<string16> origin_identifiers;
+ if (db_tracker_->GetAllOriginIdentifiers(&origin_identifiers)) {
+ for (std::vector<string16>::const_iterator iter =
+ origin_identifiers.begin();
+ iter != origin_identifiers.end(); ++iter) {
+ GURL origin = DatabaseUtil::GetOriginFromIdentifier(*iter);
+ if (ShouldAddOrigin(origin))
+ origins_.insert(origin);
+ }
+ }
+ }
+
+ std::set<GURL> origins_;
+};
+
+class DatabaseQuotaClient::GetAllOriginsTask : public GetOriginsTaskBase {
+ public:
+ GetAllOriginsTask(
+ DatabaseQuotaClient* client,
+ scoped_refptr<base::MessageLoopProxy> db_tracker_thread)
+ : GetOriginsTaskBase(client, db_tracker_thread) {
+ }
+
+ protected:
+ virtual bool ShouldAddOrigin(const GURL& origin) OVERRIDE {
+ return true;
+ }
+ virtual void Completed() OVERRIDE {
+ client_->DidGetAllOrigins(origins_);
+ }
+};
+
+class DatabaseQuotaClient::GetOriginsForHostTask : public GetOriginsTaskBase {
+ public:
+ GetOriginsForHostTask(
+ DatabaseQuotaClient* client,
+ scoped_refptr<base::MessageLoopProxy> db_tracker_thread,
+ const std::string& host)
+ : GetOriginsTaskBase(client, db_tracker_thread),
+ host_(host) {
+ }
+
+ private:
+ virtual bool ShouldAddOrigin(const GURL& origin) OVERRIDE {
+ return host_ == net::GetHostOrSpecFromURL(origin);
+ }
+ virtual void Completed() OVERRIDE {
+ client_->DidGetOriginsForHost(host_, origins_);
+ }
+ std::string host_;
+};
+
+// DatabaseQuotaClient --------------------------------------------------------
+
+DatabaseQuotaClient::DatabaseQuotaClient(
+ base::MessageLoopProxy* db_tracker_thread,
+ DatabaseTracker* db_tracker)
+ : db_tracker_thread_(db_tracker_thread), db_tracker_(db_tracker) {
+}
+
+DatabaseQuotaClient::~DatabaseQuotaClient() {
+}
+
+QuotaClient::ID DatabaseQuotaClient::id() const {
+ return kDatabase;
+}
+
+void DatabaseQuotaClient::OnQuotaManagerDestroyed() {
+ delete this;
+}
+
+void DatabaseQuotaClient::GetOriginUsage(
+ const GURL& origin_url,
+ quota::StorageType type,
+ GetUsageCallback* callback_ptr) {
+ DCHECK(callback_ptr);
+ DCHECK(db_tracker_.get());
+ scoped_ptr<GetUsageCallback> callback(callback_ptr);
+
+ // All databases are in the temp namespace for now.
+ if (type != quota::kStorageTypeTemporary) {
+ callback->Run(0);
+ return;
+ }
+
+ if (usage_for_origin_callbacks_.Add(origin_url, callback.release())) {
+ scoped_refptr<GetOriginUsageTask> task(
+ new GetOriginUsageTask(this, db_tracker_thread_, origin_url));
+ task->Start();
+ }
+}
+
+void DatabaseQuotaClient::GetOriginsForType(
+ quota::StorageType type,
+ GetOriginsCallback* callback_ptr) {
+ DCHECK(callback_ptr);
+ DCHECK(db_tracker_.get());
+ scoped_ptr<GetOriginsCallback> callback(callback_ptr);
+
+ // All databases are in the temp namespace for now.
+ if (type != quota::kStorageTypeTemporary) {
+ callback->Run(std::set<GURL>());
+ return;
+ }
+
+ if (origins_for_type_callbacks_.Add(callback.release())) {
+ scoped_refptr<GetAllOriginsTask> task(
+ new GetAllOriginsTask(this, db_tracker_thread_));
+ task->Start();
+ }
+}
+
+void DatabaseQuotaClient::GetOriginsForHost(
+ quota::StorageType type,
+ const std::string& host,
+ GetOriginsCallback* callback_ptr) {
+ DCHECK(callback_ptr);
+ DCHECK(db_tracker_.get());
+ scoped_ptr<GetOriginsCallback> callback(callback_ptr);
+
+ // All databases are in the temp namespace for now.
+ if (type != quota::kStorageTypeTemporary) {
+ callback->Run(std::set<GURL>());
+ return;
+ }
+
+ if (origins_for_host_callbacks_.Add(host, callback.release())) {
+ scoped_refptr<GetOriginsForHostTask> task(
+ new GetOriginsForHostTask(this, db_tracker_thread_, host));
+ task->Start();
+ }
+}
+
+void DatabaseQuotaClient::DidGetOriginUsage(
+ const GURL& origin_url, int64 usage) {
+ DCHECK(usage_for_origin_callbacks_.HasCallbacks(origin_url));
+ usage_for_origin_callbacks_.Run(origin_url, usage);
+}
+
+void DatabaseQuotaClient::DidGetAllOrigins(const std::set<GURL>& origins) {
+ DCHECK(origins_for_type_callbacks_.HasCallbacks());
+ origins_for_type_callbacks_.Run(origins);
+}
+
+void DatabaseQuotaClient::DidGetOriginsForHost(
+ const std::string& host, const std::set<GURL>& origins) {
+ DCHECK(origins_for_host_callbacks_.HasCallbacks(host));
+ origins_for_host_callbacks_.Run(host, origins);
+}
+
+} // namespace webkit_database
diff --git a/webkit/database/database_quota_client.h b/webkit/database/database_quota_client.h
new file mode 100644
index 0000000..5733e57
--- /dev/null
+++ b/webkit/database/database_quota_client.h
@@ -0,0 +1,81 @@
+// 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.
+
+#ifndef WEBKIT_DATABASE_DATABASE_QUOTA_CLIENT_H_
+#define WEBKIT_DATABASE_DATABASE_QUOTA_CLIENT_H_
+
+#include <set>
+#include <string>
+
+#include "base/memory/ref_counted.h"
+#include "base/message_loop_proxy.h"
+#include "webkit/quota/quota_client.h"
+#include "webkit/quota/quota_task.h"
+#include "webkit/quota/quota_types.h"
+
+namespace webkit_database {
+
+class DatabaseTracker;
+
+// A QuotaClient implementation to integrate WebSQLDatabases
+// with the quota management system. This interface is used
+// on the IO thread by the quota manager.
+class DatabaseQuotaClient : public quota::QuotaClient,
+ public quota::QuotaTaskObserver {
+ public:
+ DatabaseQuotaClient(
+ base::MessageLoopProxy* tracker_thread,
+ DatabaseTracker* tracker);
+ virtual ~DatabaseQuotaClient();
+
+ // QuotaClient method overrides
+ virtual ID id() const OVERRIDE;
+ virtual void OnQuotaManagerDestroyed();
+ virtual void GetOriginUsage(const GURL& origin_url,
+ quota::StorageType type,
+ GetUsageCallback* callback) OVERRIDE;
+ virtual void GetOriginsForType(quota::StorageType type,
+ GetOriginsCallback* callback) OVERRIDE;
+ virtual void GetOriginsForHost(quota::StorageType type,
+ const std::string& host,
+ GetOriginsCallback* callback) OVERRIDE;
+ private:
+ class HelperTask;
+ class GetOriginUsageTask;
+ class GetOriginsTaskBase;
+ class GetAllOriginsTask;
+ class GetOriginsForHostTask;
+
+ typedef quota::CallbackQueueMap1
+ <GetUsageCallback*,
+ GURL, // origin
+ int64
+ > UsageForOriginCallbackMap;
+ typedef quota::CallbackQueue1
+ <GetOriginsCallback*,
+ const std::set<GURL>&
+ > OriginsForTypeCallbackQueue;
+ typedef quota::CallbackQueueMap1
+ <GetOriginsCallback*,
+ std::string, // host
+ const std::set<GURL>&
+ > OriginsForHostCallbackMap;
+
+ void DidGetOriginUsage(const GURL& origin_url, int64 usage);
+ void DidGetAllOrigins(const std::set<GURL>& origins);
+ void DidGetOriginsForHost(
+ const std::string& host, const std::set<GURL>& origins);
+
+ scoped_refptr<base::MessageLoopProxy> db_tracker_thread_;
+ scoped_refptr<DatabaseTracker> db_tracker_; // only used on its thread
+ UsageForOriginCallbackMap usage_for_origin_callbacks_;
+ OriginsForTypeCallbackQueue origins_for_type_callbacks_;
+ OriginsForHostCallbackMap origins_for_host_callbacks_;
+
+ DISALLOW_COPY_AND_ASSIGN(DatabaseQuotaClient);
+};
+
+} // namespace webkit_database
+
+#endif // WEBKIT_DATABASE_DATABASE_QUOTA_CLIENT_H_
diff --git a/webkit/database/database_quota_client_unittest.cc b/webkit/database/database_quota_client_unittest.cc
new file mode 100644
index 0000000..38e3742
--- /dev/null
+++ b/webkit/database/database_quota_client_unittest.cc
@@ -0,0 +1,218 @@
+// 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.
+
+#include <map>
+
+#include "base/file_path.h"
+#include "base/memory/scoped_callback_factory.h"
+#include "base/message_loop.h"
+#include "base/message_loop_proxy.h"
+#include "base/utf_string_conversions.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "webkit/database/database_quota_client.h"
+#include "webkit/database/database_tracker.h"
+#include "webkit/database/database_util.h"
+
+namespace webkit_database {
+
+// Declared to shorten the line lengths.
+static const quota::StorageType kTemp = quota::kStorageTypeTemporary;
+static const quota::StorageType kPerm = quota::kStorageTypePersistent;
+
+// Mock tracker class the mocks up those methods of the tracker
+// that are used by the QuotaClient.
+class MockDatabaseTracker : public DatabaseTracker {
+ public:
+ MockDatabaseTracker()
+ : DatabaseTracker(FilePath(), false, NULL, NULL, NULL) {}
+
+ virtual ~MockDatabaseTracker() {}
+
+ virtual bool GetOriginInfo(
+ const string16& origin_identifier,
+ OriginInfo* info) OVERRIDE {
+ std::map<GURL, MockOriginInfo>::const_iterator found =
+ mock_origin_infos_.find(
+ DatabaseUtil::GetOriginFromIdentifier(origin_identifier));
+ if (found == mock_origin_infos_.end())
+ return false;
+ *info = OriginInfo(found->second);
+ return true;
+ }
+
+ virtual bool GetAllOriginIdentifiers(
+ std::vector<string16>* origins_identifiers) OVERRIDE {
+ std::map<GURL, MockOriginInfo>::const_iterator iter;
+ for (iter = mock_origin_infos_.begin();
+ iter != mock_origin_infos_.end();
+ ++iter) {
+ origins_identifiers->push_back(iter->second.GetOrigin());
+ }
+ return true;
+ }
+
+ virtual bool GetAllOriginsInfo(
+ std::vector<OriginInfo>* origins_info) OVERRIDE {
+ std::map<GURL, MockOriginInfo>::const_iterator iter;
+ for (iter = mock_origin_infos_.begin();
+ iter != mock_origin_infos_.end();
+ ++iter) {
+ origins_info->push_back(OriginInfo(iter->second));
+ }
+ return true;
+ }
+
+ void AddMockDatabase(const GURL& origin, const char* name, int size) {
+ MockOriginInfo& info = mock_origin_infos_[origin];
+ info.set_origin(DatabaseUtil::GetOriginIdentifier(origin));
+ info.AddMockDatabase(ASCIIToUTF16(name), size);
+ }
+
+ private:
+ class MockOriginInfo : public OriginInfo {
+ public:
+ void set_origin(const string16& origin_id) {
+ origin_ = origin_id;
+ }
+
+ void AddMockDatabase(const string16& name, int size) {
+ EXPECT_TRUE(database_info_.find(name) == database_info_.end());
+ database_info_[name].first = size;
+ total_size_ += size;
+ }
+ };
+
+ std::map<GURL, MockOriginInfo> mock_origin_infos_;
+};
+
+
+// Base class for our test fixtures.
+class DatabaseQuotaClientTest : public testing::Test {
+ public:
+ const GURL kOriginA;
+ const GURL kOriginB;
+ const GURL kOriginOther;
+
+ DatabaseQuotaClientTest()
+ : kOriginA("http://host"),
+ kOriginB("http://host:8000"),
+ kOriginOther("http://other"),
+ usage_(0),
+ mock_tracker_(new MockDatabaseTracker),
+ callback_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {
+ }
+
+ int64 GetOriginUsage(
+ quota::QuotaClient* client,
+ const GURL& origin,
+ quota::StorageType type) {
+ usage_ = 0;
+ client->GetOriginUsage(origin, type,
+ callback_factory_.NewCallback(
+ &DatabaseQuotaClientTest::OnGetOriginUsageComplete));
+ MessageLoop::current()->RunAllPending();
+ return usage_;
+ }
+
+ const std::set<GURL>& GetOriginsForType(
+ quota::QuotaClient* client,
+ quota::StorageType type) {
+ origins_.clear();
+ client->GetOriginsForType(type,
+ callback_factory_.NewCallback(
+ &DatabaseQuotaClientTest::OnGetOriginsComplete));
+ MessageLoop::current()->RunAllPending();
+ return origins_;
+ }
+
+ const std::set<GURL>& GetOriginsForHost(
+ quota::QuotaClient* client,
+ quota::StorageType type,
+ const std::string& host) {
+ origins_.clear();
+ client->GetOriginsForHost(type, host,
+ callback_factory_.NewCallback(
+ &DatabaseQuotaClientTest::OnGetOriginsComplete));
+ MessageLoop::current()->RunAllPending();
+ return origins_;
+ }
+
+ MockDatabaseTracker* mock_tracker() { return mock_tracker_.get(); }
+
+
+ private:
+ void OnGetOriginUsageComplete(int64 usage) {
+ usage_ = usage;
+ }
+
+ void OnGetOriginsComplete(const std::set<GURL>& origins) {
+ origins_ = origins;
+ }
+
+ int64 usage_;
+ std::set<GURL> origins_;
+ scoped_refptr<MockDatabaseTracker> mock_tracker_;
+ base::ScopedCallbackFactory<DatabaseQuotaClientTest> callback_factory_;
+};
+
+
+TEST_F(DatabaseQuotaClientTest, GetOriginUsage) {
+ DatabaseQuotaClient client(
+ base::MessageLoopProxy::CreateForCurrentThread(),
+ mock_tracker());
+
+ EXPECT_EQ(0, GetOriginUsage(&client, kOriginA, kTemp));
+ EXPECT_EQ(0, GetOriginUsage(&client, kOriginA, kPerm));
+
+ mock_tracker()->AddMockDatabase(kOriginA, "fooDB", 1000);
+ EXPECT_EQ(1000, GetOriginUsage(&client, kOriginA, kTemp));
+ EXPECT_EQ(0, GetOriginUsage(&client, kOriginA, kPerm));
+
+ EXPECT_EQ(0, GetOriginUsage(&client, kOriginB, kPerm));
+ EXPECT_EQ(0, GetOriginUsage(&client, kOriginB, kTemp));
+}
+
+TEST_F(DatabaseQuotaClientTest, GetOriginsForHost) {
+ DatabaseQuotaClient client(
+ base::MessageLoopProxy::CreateForCurrentThread(),
+ mock_tracker());
+
+ EXPECT_EQ(kOriginA.host(), kOriginB.host());
+ EXPECT_NE(kOriginA.host(), kOriginOther.host());
+
+ std::set<GURL> origins = GetOriginsForHost(&client, kTemp, kOriginA.host());
+ EXPECT_TRUE(origins.empty());
+
+ mock_tracker()->AddMockDatabase(kOriginA, "fooDB", 1000);
+ origins = GetOriginsForHost(&client, kTemp, kOriginA.host());
+ EXPECT_EQ(origins.size(), 1ul);
+ EXPECT_TRUE(origins.find(kOriginA) != origins.end());
+
+ mock_tracker()->AddMockDatabase(kOriginB, "barDB", 1000);
+ origins = GetOriginsForHost(&client, kTemp, kOriginA.host());
+ EXPECT_EQ(origins.size(), 2ul);
+ EXPECT_TRUE(origins.find(kOriginA) != origins.end());
+ EXPECT_TRUE(origins.find(kOriginB) != origins.end());
+
+ EXPECT_TRUE(GetOriginsForHost(&client, kPerm, kOriginA.host()).empty());
+ EXPECT_TRUE(GetOriginsForHost(&client, kTemp, kOriginOther.host()).empty());
+}
+
+TEST_F(DatabaseQuotaClientTest, GetOriginsForType) {
+ DatabaseQuotaClient client(
+ base::MessageLoopProxy::CreateForCurrentThread(),
+ mock_tracker());
+
+ EXPECT_TRUE(GetOriginsForType(&client, kTemp).empty());
+ EXPECT_TRUE(GetOriginsForType(&client, kPerm).empty());
+
+ mock_tracker()->AddMockDatabase(kOriginA, "fooDB", 1000);
+ std::set<GURL> origins = GetOriginsForType(&client, kTemp);
+ EXPECT_EQ(origins.size(), 1ul);
+ EXPECT_TRUE(origins.find(kOriginA) != origins.end());
+
+ EXPECT_TRUE(GetOriginsForType(&client, kPerm).empty());
+}
+
+} // namespace webkit_database
diff --git a/webkit/database/database_tracker.cc b/webkit/database/database_tracker.cc
index 5911ad2..1dc29db 100644
--- a/webkit/database/database_tracker.cc
+++ b/webkit/database/database_tracker.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.
@@ -14,12 +14,15 @@
#include "app/sql/transaction.h"
#include "base/basictypes.h"
#include "base/file_util.h"
+#include "base/message_loop_proxy.h"
#include "base/string_number_conversions.h"
#include "base/utf_string_conversions.h"
#include "net/base/net_errors.h"
+#include "webkit/database/database_quota_client.h"
#include "webkit/database/database_util.h"
#include "webkit/database/databases_table.h"
#include "webkit/database/quota_table.h"
+#include "webkit/quota/quota_manager.h"
#include "webkit/quota/special_storage_policy.h"
namespace {
@@ -47,6 +50,10 @@ static const int kCurrentVersion = 2;
static const int kCompatibleVersion = 1;
static const char* kExtensionOriginIdentifierPrefix = "chrome-extension_";
+OriginInfo::OriginInfo()
+ : total_size_(0),
+ quota_(0) {}
+
OriginInfo::OriginInfo(const OriginInfo& origin_info)
: origin_(origin_info.origin_),
total_size_(origin_info.total_size_),
@@ -83,7 +90,9 @@ OriginInfo::OriginInfo(const string16& origin, int64 total_size, int64 quota)
DatabaseTracker::DatabaseTracker(
const FilePath& profile_path,
bool is_incognito,
- quota::SpecialStoragePolicy* special_storage_policy)
+ quota::SpecialStoragePolicy* special_storage_policy,
+ quota::QuotaManagerProxy* quota_manager_proxy,
+ base::MessageLoopProxy* db_tracker_thread)
: is_initialized_(false),
is_incognito_(is_incognito),
shutting_down_(false),
@@ -96,7 +105,12 @@ DatabaseTracker::DatabaseTracker(
meta_table_(NULL),
default_quota_(5 * 1024 * 1024),
special_storage_policy_(special_storage_policy),
+ quota_manager_proxy_(quota_manager_proxy),
incognito_origin_directories_generator_(0) {
+ if (quota_manager_proxy) {
+ quota_manager_proxy->RegisterClient(
+ new DatabaseQuotaClient(db_tracker_thread, this));
+ }
}
DatabaseTracker::~DatabaseTracker() {
@@ -140,6 +154,17 @@ void DatabaseTracker::DatabaseModified(const string16& origin_identifier,
int64 space_available = GetOriginSpaceAvailable(origin_identifier);
FOR_EACH_OBSERVER(Observer, observers_, OnDatabaseSizeChanged(
origin_identifier, database_name, updated_db_size, space_available));
+
+ if (quota_manager_proxy_) {
+ // TODO(michaeln): notify the quota manager
+ // CachedOriginInfo* origin_info = GetCachedOriginInfo(origin_identifier);
+ // if (origin_info)
+ // quota_manager_proxy_->NotifyStorageConsumed(
+ // quota::QuotaClient::kDatabase,
+ // DatabaseUtil::GetOriginFromIdentifier(origin_identifier),
+ // quota::kStorageTypeTemporary,
+ // origin_info->TotalSize());
+ }
}
void DatabaseTracker::DatabaseClosed(const string16& origin_identifier,
@@ -259,14 +284,31 @@ FilePath DatabaseTracker::GetFullDBFilePath(
UTF16ToWide(GetOriginDirectory(origin_identifier)))).Append(file_name);
}
+bool DatabaseTracker::GetOriginInfo(const string16& origin_identifier,
+ OriginInfo* info) {
+ DCHECK(info);
+ CachedOriginInfo* cached_info = GetCachedOriginInfo(origin_identifier);
+ if (!cached_info)
+ return false;
+ *info = OriginInfo(*cached_info);
+ return true;
+}
+
+bool DatabaseTracker::GetAllOriginIdentifiers(
+ std::vector<string16>* origin_identifiers) {
+ DCHECK(origin_identifiers);
+ DCHECK(origin_identifiers->empty());
+ if (!LazyInit())
+ return false;
+ return databases_table_->GetAllOrigins(origin_identifiers);
+}
+
bool DatabaseTracker::GetAllOriginsInfo(std::vector<OriginInfo>* origins_info) {
DCHECK(origins_info);
DCHECK(origins_info->empty());
- if (!LazyInit())
- return false;
std::vector<string16> origins;
- if (!databases_table_->GetAllOrigins(&origins))
+ if (!GetAllOriginIdentifiers(&origins))
return false;
for (std::vector<string16>::const_iterator it = origins.begin();
@@ -314,11 +356,21 @@ bool DatabaseTracker::DeleteClosedDatabase(const string16& origin_identifier,
databases_table_->DeleteDatabaseDetails(origin_identifier, database_name);
origins_info_map_.erase(origin_identifier);
- // Try to delete the origin in case this was the last database.
std::vector<DatabaseDetails> details;
if (databases_table_->GetAllDatabaseDetailsForOrigin(
- origin_identifier, &details) && details.empty())
+ origin_identifier, &details) && details.empty()) {
+ // Try to delete the origin in case this was the last database.
DeleteOrigin(origin_identifier);
+ } else if (quota_manager_proxy_) {
+ // TODO(michaeln): notify the quota manager
+ // CachedOriginInfo* origin_info = GetCachedOriginInfo(origin_identifier);
+ // if (origin_info)
+ // quota_manager_proxy_->NotifyStorageConsumed(
+ // quota::QuotaClient::kDatabase,
+ // DatabaseUtil::GetOriginFromIdentifier(origin_identifier),
+ // quota::kStorageTypeTemporary,
+ // origin_info->TotalSize());
+ }
return true;
}
@@ -340,6 +392,16 @@ bool DatabaseTracker::DeleteOrigin(const string16& origin_identifier) {
return false;
databases_table_->DeleteOrigin(origin_identifier);
+
+ if (quota_manager_proxy_) {
+ // TODO(michaeln): notify the quota manager
+ // quota_manager_proxy_->NotifyStorageConsumed(
+ // quota::QuotaClient::kDatabase,
+ // DatabaseUtil::GetOriginFromIdentifier(origin_identifier),
+ // quota::kStorageTypeTemporary,
+ // 0);
+ }
+
return true;
}
@@ -488,6 +550,7 @@ int64 DatabaseTracker::GetDBFileSize(const string16& origin_identifier,
int64 DatabaseTracker::GetOriginSpaceAvailable(
const string16& origin_identifier) {
+ // TODO(michaeln): Come up with a value according to the the QuotaMgr.
CachedOriginInfo* origin_info = GetCachedOriginInfo(origin_identifier);
if (!origin_info)
return 0;
@@ -687,6 +750,7 @@ void DatabaseTracker::DeleteIncognitoDBDirectory() {
// static
void DatabaseTracker::ClearLocalState(const FilePath& profile_path) {
+ // TODO(michaeln): use SpecialStoragePolicy instead of kExtensionOriginPrefix
FilePath db_dir = profile_path.Append(FilePath(kDatabaseDirectoryName));
FilePath db_tracker = db_dir.Append(FilePath(kTrackerDatabaseFileName));
if (file_util::DirectoryExists(db_dir) &&
diff --git a/webkit/database/database_tracker.h b/webkit/database/database_tracker.h
index 69130a5..2246a13 100644
--- a/webkit/database/database_tracker.h
+++ b/webkit/database/database_tracker.h
@@ -20,12 +20,17 @@
#include "net/base/completion_callback.h"
#include "webkit/database/database_connections.h"
+namespace base {
+class MessageLoopProxy;
+}
+
namespace sql {
class Connection;
class MetaTable;
}
namespace quota {
+class QuotaManagerProxy;
class SpecialStoragePolicy;
}
@@ -40,6 +45,7 @@ class QuotaTable;
// This class is used to store information about all databases in an origin.
class OriginInfo {
public:
+ OriginInfo();
OriginInfo(const OriginInfo& origin_info);
~OriginInfo();
@@ -88,7 +94,9 @@ class DatabaseTracker
};
DatabaseTracker(const FilePath& profile_path, bool is_incognito,
- quota::SpecialStoragePolicy* special_storage_policy);
+ quota::SpecialStoragePolicy* special_storage_policy,
+ quota::QuotaManagerProxy* quota_manager_proxy,
+ base::MessageLoopProxy* db_tracker_thread);
void DatabaseOpened(const string16& origin_identifier,
const string16& database_name,
@@ -111,9 +119,12 @@ class DatabaseTracker
FilePath GetFullDBFilePath(const string16& origin_identifier,
const string16& database_name);
- bool GetAllOriginsInfo(std::vector<OriginInfo>* origins_info);
- void SetOriginQuota(const string16& origin_identifier, int64 new_quota);
+ // virtual for unittesting only
+ virtual bool GetOriginInfo(const string16& origin_id, OriginInfo* info);
+ virtual bool GetAllOriginIdentifiers(std::vector<string16>* origin_ids);
+ virtual bool GetAllOriginsInfo(std::vector<OriginInfo>* origins_info);
+ void SetOriginQuota(const string16& origin_identifier, int64 new_quota);
int64 GetDefaultQuota() { return default_quota_; }
// Sets the default quota for all origins. Should be used in tests only.
void SetDefaultQuota(int64 quota);
@@ -158,8 +169,8 @@ class DatabaseTracker
static void ClearLocalState(const FilePath& profile_path);
private:
- // Need this here to allow RefCountedThreadSafe to call ~DatabaseTracker().
friend class base::RefCountedThreadSafe<DatabaseTracker>;
+ friend class MockDatabaseTracker; // for testing
typedef std::map<string16, std::set<string16> > DatabaseSet;
typedef std::map<net::CompletionCallback*, DatabaseSet> PendingCompletionMap;
@@ -185,7 +196,8 @@ class DatabaseTracker
}
};
- ~DatabaseTracker();
+ // virtual for unittesting only
+ virtual ~DatabaseTracker();
bool DeleteClosedDatabase(const string16& origin_identifier,
const string16& database_name);
@@ -243,6 +255,8 @@ class DatabaseTracker
// Apps and Extensions can have special rights.
scoped_refptr<quota::SpecialStoragePolicy> special_storage_policy_;
+ scoped_refptr<quota::QuotaManagerProxy> quota_manager_proxy_;
+
// When in incognito mode, store a DELETE_ON_CLOSE handle to each
// main DB and journal file that was accessed. When the incognito profile
// goes away (or when the browser crashes), all these handles will be
diff --git a/webkit/database/database_tracker_unittest.cc b/webkit/database/database_tracker_unittest.cc
index 4ba3a54..66469bf 100644
--- a/webkit/database/database_tracker_unittest.cc
+++ b/webkit/database/database_tracker_unittest.cc
@@ -106,7 +106,8 @@ class DatabaseTracker_TestHelper_Test {
ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
scoped_refptr<DatabaseTracker> tracker(
new DatabaseTracker(temp_dir.path(), incognito_mode,
- new TestSpecialStoragePolicy));
+ new TestSpecialStoragePolicy,
+ NULL, NULL));
// Create and open three databases.
int64 database_size = 0;
@@ -209,7 +210,8 @@ class DatabaseTracker_TestHelper_Test {
ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
scoped_refptr<DatabaseTracker> tracker(
new DatabaseTracker(temp_dir.path(), incognito_mode,
- new TestSpecialStoragePolicy));
+ new TestSpecialStoragePolicy,
+ NULL, NULL));
// Add two observers.
TestObserver observer1;
diff --git a/webkit/database/webkit_database.gypi b/webkit/database/webkit_database.gypi
index 83ecf6b..11c30f5 100644
--- a/webkit/database/webkit_database.gypi
+++ b/webkit/database/webkit_database.gypi
@@ -12,12 +12,15 @@
'<(DEPTH)/app/app.gyp:app_base',
'<(DEPTH)/base/base.gyp:base',
'<(DEPTH)/third_party/sqlite/sqlite.gyp:sqlite',
+ '<(DEPTH)/webkit/support/webkit_support.gyp:quota',
],
'sources': [
'databases_table.cc',
'databases_table.h',
'database_connections.cc',
'database_connections.h',
+ 'database_quota_client.cc',
+ 'database_quota_client.h',
'database_tracker.cc',
'database_tracker.h',
'database_util.cc',
diff --git a/webkit/support/simple_database_system.cc b/webkit/support/simple_database_system.cc
index 62bd03e..a2f37ad 100644
--- a/webkit/support/simple_database_system.cc
+++ b/webkit/support/simple_database_system.cc
@@ -34,7 +34,7 @@ SimpleDatabaseSystem::SimpleDatabaseSystem()
DCHECK(!instance_);
instance_ = this;
CHECK(temp_dir_.CreateUniqueTempDir());
- db_tracker_ = new DatabaseTracker(temp_dir_.path(), false, NULL);
+ db_tracker_ = new DatabaseTracker(temp_dir_.path(), false, NULL, NULL, NULL);
db_tracker_->AddObserver(this);
db_thread_.Start();
db_thread_proxy_ = db_thread_.message_loop_proxy();
diff --git a/webkit/tools/test_shell/test_shell.gypi b/webkit/tools/test_shell/test_shell.gypi
index 699901e..d289200 100644
--- a/webkit/tools/test_shell/test_shell.gypi
+++ b/webkit/tools/test_shell/test_shell.gypi
@@ -372,6 +372,7 @@
'../../blob/blob_url_request_job_unittest.cc',
'../../blob/deletable_file_reference_unittest.cc',
'../../database/database_connections_unittest.cc',
+ '../../database/database_quota_client_unittest.cc',
'../../database/databases_table_unittest.cc',
'../../database/database_tracker_unittest.cc',
'../../database/database_util_unittest.cc',