Commit 264807b5 authored by husky@chromium.org's avatar husky@chromium.org

Add CookieStore::DeleteSessionCookiesAsync method.

This is needed by the Android port of Chromium, which has a different
startup and shutdown control flow from other platforms. We also need
to support the Android framework's android.webkit package, which has
a public CookieManager.removeSessionCookie() API.

BUG=None
TEST=CookieMonsterTest


Review URL: http://codereview.chromium.org/9959011

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@133912 0039d316-1c4b-4281-b951-d872f2087c98
parent 056093a4
......@@ -918,6 +918,32 @@ void CookieMonster::DeleteCookieTask::Run() {
}
}
// Task class for DeleteSessionCookies call.
class CookieMonster::DeleteSessionCookiesTask
: public CookieMonster::CookieMonsterTask {
public:
DeleteSessionCookiesTask(
CookieMonster* cookie_monster,
const CookieMonster::DeleteCallback& callback)
: CookieMonsterTask(cookie_monster),
callback_(callback) { }
virtual void Run() OVERRIDE;
private:
CookieMonster::DeleteCallback callback_;
DISALLOW_COPY_AND_ASSIGN(DeleteSessionCookiesTask);
};
void CookieMonster::DeleteSessionCookiesTask::Run() {
int num_deleted = this->cookie_monster()->DeleteSessionCookies();
if (!callback_.is_null()) {
this->InvokeCallback(base::Bind(&CookieMonster::DeleteCallback::Run,
base::Unretained(&callback_), num_deleted));
}
}
// Asynchronous CookieMonster API
void CookieMonster::SetCookieWithDetailsAsync(
......@@ -1035,6 +1061,14 @@ void CookieMonster::DeleteCookieAsync(const GURL& url,
DoCookieTaskForURL(task, url);
}
void CookieMonster::DeleteSessionCookiesAsync(
const CookieStore::DeleteCallback& callback) {
scoped_refptr<DeleteSessionCookiesTask> task =
new DeleteSessionCookiesTask(this, callback);
DoCookieTask(task);
}
void CookieMonster::DoCookieTask(
const scoped_refptr<CookieMonsterTask>& task_item) {
{
......@@ -1390,6 +1424,26 @@ void CookieMonster::DeleteCookie(const GURL& url,
}
}
int CookieMonster::DeleteSessionCookies() {
base::AutoLock autolock(lock_);
int num_deleted = 0;
for (CookieMap::iterator it = cookies_.begin(); it != cookies_.end();) {
CookieMap::iterator curit = it;
CanonicalCookie* cc = curit->second;
++it;
if (!cc->IsPersistent()) {
InternalDeleteCookie(curit,
true, /*sync_to_store*/
DELETE_COOKIE_EXPIRED);
++num_deleted;
}
}
return num_deleted;
}
CookieMonster* CookieMonster::GetCookieMonster() {
return this;
}
......
......@@ -246,6 +246,8 @@ class NET_EXPORT CookieMonster : public CookieStore {
const base::Time& delete_end,
const DeleteCallback& callback) OVERRIDE;
virtual void DeleteSessionCookiesAsync(const DeleteCallback&) OVERRIDE;
virtual CookieMonster* GetCookieMonster() OVERRIDE;
// Enables writing session cookies into the cookie database. If this this
......@@ -281,6 +283,7 @@ class NET_EXPORT CookieMonster : public CookieStore {
class GetCookiesWithInfoTask;
class SetCookieWithDetailsTask;
class SetCookieWithOptionsTask;
class DeleteSessionCookiesTask;
// Testing support.
// For SetCookieWithCreationTime.
......@@ -412,6 +415,8 @@ class NET_EXPORT CookieMonster : public CookieStore {
const std::string& cookie_line,
const base::Time& creation_time);
int DeleteSessionCookies();
// Called by all non-static functions to ensure that the cookies store has
// been initialized. This is not done during creating so it doesn't block
// the window showing.
......
......@@ -473,6 +473,16 @@ class CookieMonsterTest : public CookieStoreTest<CookieMonsterTestTraits> {
return callback.result();
}
int DeleteSessionCookies(CookieMonster*cm) {
DCHECK(cm);
DeleteCallback callback;
cm->DeleteSessionCookiesAsync(
base::Bind(&DeleteCallback::Run, base::Unretained(&callback)));
RunFor(kTimeout);
EXPECT_TRUE(callback.did_run());
return callback.num_deleted();
}
// Helper for DeleteAllForHost test; repopulates CM with same layout
// each time.
void PopulateCmForDeleteAllForHost(scoped_refptr<CookieMonster> cm) {
......@@ -757,6 +767,10 @@ ACTION_P(PushCallbackAction, callback_vector) {
callback_vector->push(arg1);
}
ACTION_P2(DeleteSessionCookiesAction, cookie_monster, callback) {
cookie_monster->DeleteSessionCookiesAsync(callback->AsCallback());
}
} // namespace
// This test suite verifies the task deferral behaviour of the CookieMonster.
......@@ -1096,6 +1110,22 @@ TEST_F(DeferredCookieTaskTest, DeferredDeleteCanonicalCookie) {
CompleteLoadingAndWait();
}
TEST_F(DeferredCookieTaskTest, DeferredDeleteSessionCookies) {
MockDeleteCallback delete_callback;
BeginWith(DeleteSessionCookiesAction(
&cookie_monster(), &delete_callback));
WaitForLoadCall();
EXPECT_CALL(delete_callback, Invoke(false)).WillOnce(
DeleteSessionCookiesAction(&cookie_monster(), &delete_callback));
EXPECT_CALL(delete_callback, Invoke(false)).WillOnce(
QuitCurrentMessageLoop());
CompleteLoadingAndWait();
}
// Verify that a series of queued tasks are executed in order upon loading of
// the backing store and that new tasks received while the queued tasks are
// being dispatched go to the end of the queue.
......@@ -2410,6 +2440,11 @@ class MultiThreadedCookieMonsterTest : public CookieMonsterTest {
base::Bind(&SetCookieCallback::Run, base::Unretained(callback)));
}
void DeleteSessionCookiesTask(CookieMonster* cm, DeleteCallback* callback) {
cm->DeleteSessionCookiesAsync(
base::Bind(&DeleteCallback::Run, base::Unretained(callback)));
}
protected:
void RunOnOtherThread(const base::Closure& task) {
other_thread_.Start();
......@@ -2567,6 +2602,27 @@ TEST_F(MultiThreadedCookieMonsterTest, ThreadCheckDeleteCanonicalCookie) {
EXPECT_TRUE(callback.result());
}
TEST_F(MultiThreadedCookieMonsterTest, ThreadCheckDeleteSessionCookies) {
scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL));
CookieOptions options;
EXPECT_TRUE(SetCookieWithOptions(cm, url_google_, "A=B", options));
EXPECT_TRUE(SetCookieWithOptions(cm, url_google_,
"B=C; expires=Mon, 18-Apr-22 22:50:13 GMT",
options));
EXPECT_EQ(1, DeleteSessionCookies(cm));
EXPECT_EQ(0, DeleteSessionCookies(cm));
EXPECT_TRUE(SetCookieWithOptions(cm, url_google_, "A=B", options));
DeleteCallback callback(&other_thread_);
base::Closure task = base::Bind(
&net::MultiThreadedCookieMonsterTest::DeleteSessionCookiesTask,
base::Unretained(this),
cm, &callback);
RunOnOtherThread(task);
EXPECT_TRUE(callback.did_run());
EXPECT_EQ(1, callback.num_deleted());
}
TEST_F(CookieMonsterTest, ShortLivedSessionCookies) {
scoped_refptr<MockPersistentCookieStore> store(
new MockPersistentCookieStore);
......
......@@ -99,6 +99,8 @@ class NET_EXPORT CookieStore : public base::RefCountedThreadSafe<CookieStore> {
const base::Time& delete_end,
const DeleteCallback& callback) = 0;
virtual void DeleteSessionCookiesAsync(const DeleteCallback&) = 0;
// Returns the underlying CookieMonster.
virtual CookieMonster* GetCookieMonster() = 0;
......
......@@ -148,6 +148,10 @@ void DelayedCookieMonster::DeleteAllCreatedBetweenAsync(
ADD_FAILURE();
}
void DelayedCookieMonster::DeleteSessionCookiesAsync(const DeleteCallback&) {
ADD_FAILURE();
}
CookieMonster* DelayedCookieMonster::GetCookieMonster() {
return cookie_monster_;
}
......
......@@ -63,6 +63,8 @@ class DelayedCookieMonster : public CookieStore {
const base::Time& delete_end,
const DeleteCallback& callback) OVERRIDE;
virtual void DeleteSessionCookiesAsync(const DeleteCallback&) OVERRIDE;
virtual CookieMonster* GetCookieMonster() OVERRIDE;
private:
......
......@@ -221,6 +221,9 @@ class MockCookieStore : public net::CookieStore {
const DeleteCallback& callback) {
ADD_FAILURE();
}
virtual void DeleteSessionCookiesAsync(const DeleteCallback&) {
ADD_FAILURE();
}
virtual net::CookieMonster* GetCookieMonster() { return NULL; }
......
......@@ -221,6 +221,9 @@ class MockCookieStore : public net::CookieStore {
const DeleteCallback& callback) {
ADD_FAILURE();
}
virtual void DeleteSessionCookiesAsync(const DeleteCallback&) {
ADD_FAILURE();
}
virtual net::CookieMonster* GetCookieMonster() { return NULL; }
......
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