diff options
author | rdsmith@chromium.org <rdsmith@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-12-23 17:25:08 +0000 |
---|---|---|
committer | rdsmith@chromium.org <rdsmith@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-12-23 17:25:08 +0000 |
commit | 2be41d781304fbd79cbdcdbf586f42e9f000cd2b (patch) | |
tree | f621baa9342b2170ea3db620d7ab6792aad0dc3b /net | |
parent | 57fd125f91b7269317be61277084c7b6e1181eed (diff) | |
download | chromium_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.cc | 10 | ||||
-rw-r--r-- | net/base/cookie_monster.h | 11 | ||||
-rw-r--r-- | net/base/cookie_monster_store_test.h | 11 | ||||
-rw-r--r-- | net/base/cookie_monster_unittest.cc | 104 |
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 |