Commit 42472adb authored by michaeln@google.com's avatar michaeln@google.com

Implement DatabaseQuotaClient's DeteleteOriginData method.

TEST=database_quota_client_unittest.cc
BUG=61676
Review URL: http://codereview.chromium.org/7046019

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@86561 0039d316-1c4b-4281-b951-d872f2087c98
parent 5f0ce949
......@@ -6,7 +6,10 @@
#include <vector>
#include "base/memory/scoped_ptr.h"
#include "base/message_loop_proxy.h"
#include "net/base/completion_callback.h"
#include "net/base/net_errors.h"
#include "net/base/net_util.h"
#include "webkit/database/database_tracker.h"
#include "webkit/database/database_util.h"
......@@ -21,7 +24,7 @@ class DatabaseQuotaClient::HelperTask : public quota::QuotaThreadTask {
protected:
HelperTask(
DatabaseQuotaClient* client,
scoped_refptr<base::MessageLoopProxy> db_tracker_thread)
base::MessageLoopProxy* db_tracker_thread)
: QuotaThreadTask(client, db_tracker_thread),
client_(client), db_tracker_(client->db_tracker_) {
}
......@@ -34,7 +37,7 @@ class DatabaseQuotaClient::GetOriginUsageTask : public HelperTask {
public:
GetOriginUsageTask(
DatabaseQuotaClient* client,
scoped_refptr<base::MessageLoopProxy> db_tracker_thread,
base::MessageLoopProxy* db_tracker_thread,
const GURL& origin_url)
: HelperTask(client, db_tracker_thread),
origin_url_(origin_url), usage_(0) {
......@@ -60,7 +63,7 @@ class DatabaseQuotaClient::GetOriginsTaskBase : public HelperTask {
protected:
GetOriginsTaskBase(
DatabaseQuotaClient* client,
scoped_refptr<base::MessageLoopProxy> db_tracker_thread)
base::MessageLoopProxy* db_tracker_thread)
: HelperTask(client, db_tracker_thread) {
}
......@@ -86,7 +89,7 @@ class DatabaseQuotaClient::GetAllOriginsTask : public GetOriginsTaskBase {
public:
GetAllOriginsTask(
DatabaseQuotaClient* client,
scoped_refptr<base::MessageLoopProxy> db_tracker_thread)
base::MessageLoopProxy* db_tracker_thread)
: GetOriginsTaskBase(client, db_tracker_thread) {
}
......@@ -103,7 +106,7 @@ class DatabaseQuotaClient::GetOriginsForHostTask : public GetOriginsTaskBase {
public:
GetOriginsForHostTask(
DatabaseQuotaClient* client,
scoped_refptr<base::MessageLoopProxy> db_tracker_thread,
base::MessageLoopProxy* db_tracker_thread,
const std::string& host)
: GetOriginsTaskBase(client, db_tracker_thread),
host_(host) {
......@@ -119,6 +122,57 @@ class DatabaseQuotaClient::GetOriginsForHostTask : public GetOriginsTaskBase {
std::string host_;
};
class DatabaseQuotaClient::DeleteOriginTask : public HelperTask {
public:
DeleteOriginTask(
DatabaseQuotaClient* client,
base::MessageLoopProxy* db_tracker_thread,
const GURL& origin_url,
DeletionCallback* caller_callback)
: HelperTask(client, db_tracker_thread),
origin_url_(origin_url),
result_(quota::kQuotaStatusUnknown),
caller_callback_(caller_callback),
ALLOW_THIS_IN_INITIALIZER_LIST(completion_callback_(
this, &DeleteOriginTask::OnCompletionCallback)) {
}
private:
virtual void Completed() OVERRIDE {
if (!caller_callback_.get())
return;
caller_callback_->Run(result_);
caller_callback_.reset();
}
virtual void Aborted() OVERRIDE {
caller_callback_.reset();
}
virtual bool RunOnTargetThreadAsync() OVERRIDE {
AddRef(); // balanced in OnCompletionCallback
string16 origin_id = DatabaseUtil::GetOriginIdentifier(origin_url_);
int rv = db_tracker_->DeleteDataForOrigin(origin_id, &completion_callback_);
if (rv == net::ERR_IO_PENDING)
return false; // we wait for the callback
OnCompletionCallback(rv);
return false;
}
void OnCompletionCallback(int rv) {
if (rv == net::OK)
result_ = quota::kQuotaStatusOk;
original_message_loop()->PostTask(
FROM_HERE, NewRunnableMethod(this, &DeleteOriginTask::CallCompleted));
Release(); // balanced in RunOnTargetThreadAsync
}
const GURL origin_url_;
quota::QuotaStatusCode result_;
scoped_ptr<DeletionCallback> caller_callback_;
net::CompletionCallbackImpl<DeleteOriginTask> completion_callback_;
};
// DatabaseQuotaClient --------------------------------------------------------
DatabaseQuotaClient::DatabaseQuotaClient(
......@@ -202,10 +256,21 @@ void DatabaseQuotaClient::GetOriginsForHost(
void DatabaseQuotaClient::DeleteOriginData(const GURL& origin,
quota::StorageType type,
DeletionCallback* callback) {
// TODO(tzik): implement me
callback->Run(quota::kQuotaErrorNotSupported);
delete callback;
DeletionCallback* callback_ptr) {
DCHECK(callback_ptr);
DCHECK(db_tracker_.get());
scoped_ptr<DeletionCallback> callback(callback_ptr);
// All databases are in the temp namespace for now, so nothing to delete.
if (type != quota::kStorageTypeTemporary) {
callback->Run(quota::kQuotaStatusOk);
return;
}
scoped_refptr<DeleteOriginTask> task(
new DeleteOriginTask(this, db_tracker_thread_,
origin, callback.release()));
task->Start();
}
void DatabaseQuotaClient::DidGetOriginUsage(
......
......@@ -49,6 +49,7 @@ class DatabaseQuotaClient : public quota::QuotaClient,
class GetOriginsTaskBase;
class GetAllOriginsTask;
class GetOriginsForHostTask;
class DeleteOriginTask;
typedef quota::CallbackQueueMap1
<GetUsageCallback*,
......
......@@ -9,6 +9,7 @@
#include "base/message_loop.h"
#include "base/message_loop_proxy.h"
#include "base/utf_string_conversions.h"
#include "net/base/net_errors.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "webkit/database/database_quota_client.h"
#include "webkit/database/database_tracker.h"
......@@ -25,7 +26,9 @@ static const quota::StorageType kPerm = quota::kStorageTypePersistent;
class MockDatabaseTracker : public DatabaseTracker {
public:
MockDatabaseTracker()
: DatabaseTracker(FilePath(), false, NULL, NULL, NULL) {}
: DatabaseTracker(FilePath(), false, NULL, NULL, NULL),
delete_called_count_(0),
async_delete_(false) {}
virtual ~MockDatabaseTracker() {}
......@@ -63,12 +66,33 @@ class MockDatabaseTracker : public DatabaseTracker {
return true;
}
virtual int DeleteDataForOrigin(
const string16& origin_id,
net::CompletionCallback* callback) {
++delete_called_count_;
if (async_delete()) {
base::MessageLoopProxy::CreateForCurrentThread()->PostTask(FROM_HERE,
NewRunnableMethod(this,
&MockDatabaseTracker::AsyncDeleteDataForOrigin, callback));
return net::ERR_IO_PENDING;
}
return net::OK;
}
void AsyncDeleteDataForOrigin(net::CompletionCallback* callback) {
callback->Run(net::OK);
}
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);
}
int delete_called_count() { return delete_called_count_; }
bool async_delete() { return async_delete_; }
void set_async_delete(bool async) { async_delete_ = async; }
private:
class MockOriginInfo : public OriginInfo {
public:
......@@ -83,6 +107,8 @@ class MockDatabaseTracker : public DatabaseTracker {
}
};
int delete_called_count_;
bool async_delete_;
std::map<GURL, MockOriginInfo> mock_origin_infos_;
};
......@@ -121,7 +147,7 @@ class DatabaseQuotaClientTest : public testing::Test {
origins_.clear();
client->GetOriginsForType(type,
callback_factory_.NewCallback(
&DatabaseQuotaClientTest::OnGetOriginsComplete));
&DatabaseQuotaClientTest::OnGetOriginsComplete));
MessageLoop::current()->RunAllPending();
return origins_;
}
......@@ -133,11 +159,23 @@ class DatabaseQuotaClientTest : public testing::Test {
origins_.clear();
client->GetOriginsForHost(type, host,
callback_factory_.NewCallback(
&DatabaseQuotaClientTest::OnGetOriginsComplete));
&DatabaseQuotaClientTest::OnGetOriginsComplete));
MessageLoop::current()->RunAllPending();
return origins_;
}
bool DeleteOriginData(
quota::QuotaClient* client,
quota::StorageType type,
const GURL& origin) {
delete_status_ = quota::kQuotaStatusUnknown;
client->DeleteOriginData(origin, type,
callback_factory_.NewCallback(
&DatabaseQuotaClientTest::OnDeleteOriginDataComplete));
MessageLoop::current()->RunAllPending();
return delete_status_ == quota::kQuotaStatusOk;
}
MockDatabaseTracker* mock_tracker() { return mock_tracker_.get(); }
......@@ -150,8 +188,13 @@ class DatabaseQuotaClientTest : public testing::Test {
origins_ = origins;
}
void OnDeleteOriginDataComplete(quota::QuotaStatusCode status) {
delete_status_ = status;
}
int64 usage_;
std::set<GURL> origins_;
quota::QuotaStatusCode delete_status_;
scoped_refptr<MockDatabaseTracker> mock_tracker_;
base::ScopedCallbackFactory<DatabaseQuotaClientTest> callback_factory_;
};
......@@ -215,4 +258,23 @@ TEST_F(DatabaseQuotaClientTest, GetOriginsForType) {
EXPECT_TRUE(GetOriginsForType(&client, kPerm).empty());
}
TEST_F(DatabaseQuotaClientTest, DeleteOriginData) {
DatabaseQuotaClient client(
base::MessageLoopProxy::CreateForCurrentThread(),
mock_tracker());
// Perm deletions are short circuited in the Client and
// should not reach the DatabaseTracker.
EXPECT_TRUE(DeleteOriginData(&client, kPerm, kOriginA));
EXPECT_EQ(0, mock_tracker()->delete_called_count());
mock_tracker()->set_async_delete(false);
EXPECT_TRUE(DeleteOriginData(&client, kTemp, kOriginA));
EXPECT_EQ(1, mock_tracker()->delete_called_count());
mock_tracker()->set_async_delete(true);
EXPECT_TRUE(DeleteOriginData(&client, kTemp, kOriginA));
EXPECT_EQ(2, mock_tracker()->delete_called_count());
}
} // namespace webkit_database
......@@ -67,9 +67,17 @@ void QuotaThreadTask::Run() {
void QuotaThreadTask::CallRunOnTargetThread() {
DCHECK(target_message_loop_->BelongsToCurrentThread());
if (RunOnTargetThreadAsync())
original_message_loop()->PostTask(
FROM_HERE, NewRunnableMethod(this, &QuotaThreadTask::CallCompleted));
}
bool QuotaThreadTask::RunOnTargetThreadAsync() {
RunOnTargetThread();
original_message_loop()->PostTask(
FROM_HERE, NewRunnableMethod(this, &QuotaThreadTask::CallCompleted));
return true;
}
void QuotaThreadTask::RunOnTargetThread() {
}
// QuotaTaskObserver -------------------------------------------------------
......
......@@ -66,8 +66,18 @@ class QuotaThreadTask : public QuotaTask,
protected:
virtual ~QuotaThreadTask();
// Called on the target message loop.
virtual void RunOnTargetThread() = 0;
// One of the following Run methods should be overriden for execution
// on the target thread.
// A task to invoke the CallCompleted() method on the original thread will
// be scheduled immediately upon return from RunOnTargetThread().
virtual void RunOnTargetThread();
// A task to invoke the CallCompleted() method on the original thread will
// only be scheduled if RunOnTargetThreadAsync returns true. If false is
// returned, the derived class should schedule a task to do so upon actual
// completion.
virtual bool RunOnTargetThreadAsync();
virtual void Run() OVERRIDE;
scoped_refptr<base::MessageLoopProxy> target_message_loop() const {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment