summaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorrdsmith@chromium.org <rdsmith@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-12-23 17:25:08 +0000
committerrdsmith@chromium.org <rdsmith@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-12-23 17:25:08 +0000
commit2be41d781304fbd79cbdcdbf586f42e9f000cd2b (patch)
treef621baa9342b2170ea3db620d7ab6792aad0dc3b /net
parent57fd125f91b7269317be61277084c7b6e1181eed (diff)
downloadchromium_src-2be41d781304fbd79cbdcdbf586f42e9f000cd2b.zip
chromium_src-2be41d781304fbd79cbdcdbf586f42e9f000cd2b.tar.gz
chromium_src-2be41d781304fbd79cbdcdbf586f42e9f000cd2b.tar.bz2
Add Flush(Task*) method to CookieMonster.
Flushes cookies to disk immediately, rather than waiting for the 30-second timer. It takes an optional completion callback. Patch from husky@google.com. BUG=None TEST=CookieMonsterTest, Additional SQLitePersistentCookieStore tests. Review URL: http://codereview.chromium.org/5365010 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@70067 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net')
-rw-r--r--net/base/cookie_monster.cc10
-rw-r--r--net/base/cookie_monster.h11
-rw-r--r--net/base/cookie_monster_store_test.h11
-rw-r--r--net/base/cookie_monster_unittest.cc104
4 files changed, 135 insertions, 1 deletions
diff --git a/net/base/cookie_monster.cc b/net/base/cookie_monster.cc
index 8eb3a49..85f061d 100644
--- a/net/base/cookie_monster.cc
+++ b/net/base/cookie_monster.cc
@@ -49,6 +49,7 @@
#include "base/basictypes.h"
#include "base/format_macros.h"
#include "base/logging.h"
+#include "base/message_loop.h"
#include "base/metrics/histogram.h"
#include "base/scoped_ptr.h"
#include "base/string_tokenizer.h"
@@ -411,6 +412,14 @@ void CookieMonster::SetClearPersistentStoreOnExit(bool clear_local_store) {
store_->SetClearLocalStateOnExit(clear_local_store);
}
+void CookieMonster::FlushStore(Task* completion_task) {
+ AutoLock autolock(lock_);
+ if (initialized_ && store_)
+ store_->Flush(completion_task);
+ else if (completion_task)
+ MessageLoop::current()->PostTask(FROM_HERE, completion_task);
+}
+
// The system resolution is not high enough, so we can have multiple
// set cookies that result in the same system time. When this happens, we
// increment by one Time unit. Let's hope computers don't get too fast.
@@ -2012,4 +2021,3 @@ std::string CookieMonster::CanonicalCookie::DebugString() const {
}
} // namespace
-
diff --git a/net/base/cookie_monster.h b/net/base/cookie_monster.h
index a985176..4e31488 100644
--- a/net/base/cookie_monster.h
+++ b/net/base/cookie_monster.h
@@ -18,6 +18,7 @@
#include "base/lock.h"
#include "base/ref_counted.h"
#include "base/scoped_ptr.h"
+#include "base/task.h"
#include "base/time.h"
#include "net/base/cookie_store.h"
@@ -223,6 +224,13 @@ class CookieMonster : public CookieStore {
static void EnableFileScheme();
static bool enable_file_scheme_;
+ // Flush the backing store (if any) to disk and post the given task when done.
+ // WARNING: THE CALLBACK WILL RUN ON A RANDOM THREAD. IT MUST BE THREAD SAFE.
+ // It may be posted to the current thread, or it may run on the thread that
+ // actually does the flushing. Your Task should generally post a notification
+ // to the thread you actually want to be notified on.
+ void FlushStore(Task* completion_task);
+
private:
~CookieMonster();
@@ -700,6 +708,9 @@ class CookieMonster::PersistentCookieStore
// must be deleted upon destruction.
virtual void SetClearLocalStateOnExit(bool clear_local_state) = 0;
+ // Flush the store and post the given Task when complete.
+ virtual void Flush(Task* completion_task) = 0;
+
protected:
PersistentCookieStore() {}
diff --git a/net/base/cookie_monster_store_test.h b/net/base/cookie_monster_store_test.h
index 65c91b7..84ead74 100644
--- a/net/base/cookie_monster_store_test.h
+++ b/net/base/cookie_monster_store_test.h
@@ -7,6 +7,7 @@
// that need to test out CookieMonster interactions with the backing store.
// It should only be included by test code.
+#include "base/message_loop.h"
#include "base/time.h"
#include "net/base/cookie_monster.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -66,6 +67,11 @@ class MockPersistentCookieStore
CookieStoreCommand(CookieStoreCommand::REMOVE, cookie));
}
+ virtual void Flush(Task* completion_task) {
+ if (completion_task)
+ MessageLoop::current()->PostTask(FROM_HERE, completion_task);
+ }
+
// No files are created so nothing to clear either
virtual void SetClearLocalStateOnExit(bool clear_local_state) {}
@@ -188,6 +194,11 @@ class MockSimplePersistentCookieStore
cookies_.erase(it);
}
+ virtual void Flush(Task* completion_task) {
+ if (completion_task)
+ MessageLoop::current()->PostTask(FROM_HERE, completion_task);
+ }
+
virtual void SetClearLocalStateOnExit(bool clear_local_state) {}
private:
diff --git a/net/base/cookie_monster_unittest.cc b/net/base/cookie_monster_unittest.cc
index a4bc58f..a0c16ea 100644
--- a/net/base/cookie_monster_unittest.cc
+++ b/net/base/cookie_monster_unittest.cc
@@ -2069,4 +2069,108 @@ TEST(CookieMonsterTest, ForceSessionOnly) {
ASSERT_EQ(0U, cookie_list.size());
}
+namespace {
+
+// Mock PersistentCookieStore that keeps track of the number of Flush() calls.
+class FlushablePersistentStore : public CookieMonster::PersistentCookieStore {
+ public:
+ FlushablePersistentStore() : flush_count_(0) {}
+
+ bool Load(std::vector<CookieMonster::CanonicalCookie*>*) {
+ return false;
+ }
+
+ void AddCookie(const CookieMonster::CanonicalCookie&) {}
+ void UpdateCookieAccessTime(const CookieMonster::CanonicalCookie&) {}
+ void DeleteCookie(const CookieMonster::CanonicalCookie&) {}
+ void SetClearLocalStateOnExit(bool clear_local_state) {}
+
+ void Flush(Task* completion_callback) {
+ ++flush_count_;
+ if (completion_callback) {
+ completion_callback->Run();
+ delete completion_callback;
+ }
+ }
+
+ int flush_count() {
+ return flush_count_;
+ }
+
+ private:
+ volatile int flush_count_;
+};
+
+// Counts the number of times Callback() has been run.
+class CallbackCounter : public base::RefCountedThreadSafe<CallbackCounter> {
+ public:
+ CallbackCounter() : callback_count_(0) {}
+
+ void Callback() {
+ ++callback_count_;
+ }
+
+ int callback_count() {
+ return callback_count_;
+ }
+
+ private:
+ friend class base::RefCountedThreadSafe<CallbackCounter>;
+ volatile int callback_count_;
+};
+
+} // namespace
+
+// Test that FlushStore() is forwarded to the store and callbacks are posted.
+TEST(CookieMonsterTest, FlushStore) {
+ scoped_refptr<CallbackCounter> counter(new CallbackCounter());
+ scoped_refptr<FlushablePersistentStore> store(new FlushablePersistentStore());
+ scoped_refptr<net::CookieMonster> cm(new net::CookieMonster(store, NULL));
+
+ ASSERT_EQ(0, store->flush_count());
+ ASSERT_EQ(0, counter->callback_count());
+
+ // Before initialization, FlushStore() should just run the callback.
+ cm->FlushStore(NewRunnableMethod(counter.get(), &CallbackCounter::Callback));
+ MessageLoop::current()->RunAllPending();
+
+ ASSERT_EQ(0, store->flush_count());
+ ASSERT_EQ(1, counter->callback_count());
+
+ // NULL callback is safe.
+ cm->FlushStore(NULL);
+ MessageLoop::current()->RunAllPending();
+
+ ASSERT_EQ(0, store->flush_count());
+ ASSERT_EQ(1, counter->callback_count());
+
+ // After initialization, FlushStore() should delegate to the store.
+ cm->GetAllCookies(); // Force init.
+ cm->FlushStore(NewRunnableMethod(counter.get(), &CallbackCounter::Callback));
+ MessageLoop::current()->RunAllPending();
+
+ ASSERT_EQ(1, store->flush_count());
+ ASSERT_EQ(2, counter->callback_count());
+
+ // NULL callback is still safe.
+ cm->FlushStore(NULL);
+ MessageLoop::current()->RunAllPending();
+
+ ASSERT_EQ(2, store->flush_count());
+ ASSERT_EQ(2, counter->callback_count());
+
+ // If there's no backing store, FlushStore() is always a safe no-op.
+ cm = new net::CookieMonster(NULL, NULL);
+ cm->GetAllCookies(); // Force init.
+ cm->FlushStore(NULL);
+ MessageLoop::current()->RunAllPending();
+
+ ASSERT_EQ(2, counter->callback_count());
+
+ cm->FlushStore(NewRunnableMethod(counter.get(), &CallbackCounter::Callback));
+ MessageLoop::current()->RunAllPending();
+
+ ASSERT_EQ(3, counter->callback_count());
+}
+
} // namespace