Index: chrome/browser/net/sqlite_persistent_cookie_store.cc |
=================================================================== |
--- chrome/browser/net/sqlite_persistent_cookie_store.cc (revision 99705) |
+++ chrome/browser/net/sqlite_persistent_cookie_store.cc (working copy) |
@@ -7,6 +7,7 @@ |
#include <list> |
#include "base/basictypes.h" |
+#include "base/bind.h" |
#include "base/file_path.h" |
#include "base/file_util.h" |
#include "base/logging.h" |
@@ -27,6 +28,12 @@ |
// This class is designed to be shared between any calling threads and the |
// database thread. It batches operations and commits them on a timer. |
+// This class expects to be Load()'ed once on any thread. Loading occurs |
+// asynchronously on the DB thread and the caller will be notified on the IO |
+// thread. Subsequent to loading, mutations may be queued by any thread using |
+// AddCookie, UpdateCookieAccessTime, and DeleteCookie. These are flushed to |
+// disk on the DB thread every 30 seconds, 512 operations, or call to Flush(), |
+// whichever occurs first. |
class SQLitePersistentCookieStore::Backend |
: public base::RefCountedThreadSafe<SQLitePersistentCookieStore::Backend> { |
public: |
@@ -38,7 +45,7 @@ |
} |
// Creates or load the SQLite database. |
- bool Load(std::vector<net::CookieMonster::CanonicalCookie*>* cookies); |
+ bool Load(const LoadedCallback& loaded_callback); |
// Batch a cookie addition. |
void AddCookie(const net::CookieMonster::CanonicalCookie& cc); |
@@ -91,6 +98,18 @@ |
}; |
private: |
+ // Creates or load the SQLite database on DB thread. |
+ void LoadAndNotifyOnDBThread(const LoadedCallback& loaded_callback); |
+ // Notify the CookieMonster when loading complete. |
+ void NotifyOnIOThread( |
+ const LoadedCallback& loaded_callback, |
+ bool load_success, |
+ const std::vector<net::CookieMonster::CanonicalCookie*>& cookies); |
+ // Initialize the data base. |
+ bool InitializeDatabase(); |
+ // Load cookies to the data base, and read cookies. |
+ bool LoadInternal(std::vector<net::CookieMonster::CanonicalCookie*>* cookies); |
+ |
// Batch a cookie operation (add or delete) |
void BatchOperation(PendingOperation::OperationType op, |
const net::CookieMonster::CanonicalCookie& cc); |
@@ -154,19 +173,40 @@ |
} // namespace |
bool SQLitePersistentCookieStore::Backend::Load( |
- std::vector<net::CookieMonster::CanonicalCookie*>* cookies) { |
+ const LoadedCallback& loaded_callback) { |
// This function should be called only once per instance. |
DCHECK(!db_.get()); |
+ BrowserThread::PostTask( |
+ BrowserThread::DB, FROM_HERE, |
+ base::Bind(&Backend::LoadAndNotifyOnDBThread, base::Unretained(this), |
+ loaded_callback)); |
+ return true; |
+} |
- // Ensure the parent directory for storing cookies is created before reading |
- // from it. We make an exception to allow IO on the UI thread here because |
- // we are going to disk anyway in db_->Open. (This code will be moved to the |
- // DB thread as part of http://crbug.com/52909.) |
- { |
- base::ThreadRestrictions::ScopedAllowIO allow_io; |
- const FilePath dir = path_.DirName(); |
- if (!file_util::PathExists(dir) && !file_util::CreateDirectory(dir)) |
- return false; |
+void SQLitePersistentCookieStore::Backend::LoadAndNotifyOnDBThread( |
+ const LoadedCallback& loaded_callback) { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); |
+ std::vector<net::CookieMonster::CanonicalCookie*> cookies; |
+ |
+ bool load_success = LoadInternal(&cookies); |
+ |
+ BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, base::Bind( |
+ &SQLitePersistentCookieStore::Backend::NotifyOnIOThread, |
+ base::Unretained(this), loaded_callback, load_success, cookies)); |
+} |
+ |
+void SQLitePersistentCookieStore::Backend::NotifyOnIOThread( |
+ const LoadedCallback& loaded_callback, |
+ bool load_success, |
+ const std::vector<net::CookieMonster::CanonicalCookie*>& cookies) { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
+ loaded_callback.Run(cookies); |
+} |
+ |
+bool SQLitePersistentCookieStore::Backend::InitializeDatabase() { |
+ const FilePath dir = path_.DirName(); |
+ if (!file_util::PathExists(dir) && !file_util::CreateDirectory(dir)) { |
+ return false; |
} |
db_.reset(new sql::Connection); |
@@ -185,7 +225,15 @@ |
} |
db_->Preload(); |
+ return true; |
+} |
+bool SQLitePersistentCookieStore::Backend::LoadInternal( |
+ std::vector<net::CookieMonster::CanonicalCookie*>* cookies) { |
+ if (!InitializeDatabase()) { |
+ return false; |
+ } |
+ |
// Slurp all the cookies into the out-vector. |
sql::Statement smt(db_->GetUniqueStatement( |
"SELECT creation_utc, host_key, name, value, path, expires_utc, secure, " |
@@ -447,11 +495,14 @@ |
// pending commit timer that will be holding a reference on us, but if/when |
// this fires we will already have been cleaned up and it will be ignored. |
void SQLitePersistentCookieStore::Backend::Close() { |
- DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::DB)); |
- // Must close the backend on the background thread. |
- BrowserThread::PostTask( |
- BrowserThread::DB, FROM_HERE, |
- NewRunnableMethod(this, &Backend::InternalBackgroundClose)); |
+ if (BrowserThread::CurrentlyOn(BrowserThread::DB)) { |
+ InternalBackgroundClose(); |
+ } else { |
+ // Must close the backend on the background thread. |
+ BrowserThread::PostTask( |
+ BrowserThread::DB, FROM_HERE, |
+ NewRunnableMethod(this, &Backend::InternalBackgroundClose)); |
+ } |
} |
void SQLitePersistentCookieStore::Backend::InternalBackgroundClose() { |
@@ -483,9 +534,8 @@ |
} |
} |
-bool SQLitePersistentCookieStore::Load( |
- std::vector<net::CookieMonster::CanonicalCookie*>* cookies) { |
- return backend_->Load(cookies); |
+bool SQLitePersistentCookieStore::Load(const LoadedCallback& loaded_callback) { |
+ return backend_->Load(loaded_callback); |
} |
void SQLitePersistentCookieStore::AddCookie( |