Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(829)

Side by Side Diff: chrome/browser/net/sqlite_persistent_cookie_store.cc

Issue 7833042: Finalize a CL originally by departed intern ycxiao@ that detaches the loading of cookies from the... (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: '' Created 9 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/net/sqlite_persistent_cookie_store.h" 5 #include "chrome/browser/net/sqlite_persistent_cookie_store.h"
6 6
7 #include <list> 7 #include <list>
8 8
9 #include "base/basictypes.h" 9 #include "base/basictypes.h"
10 #include "base/bind.h"
10 #include "base/file_path.h" 11 #include "base/file_path.h"
11 #include "base/file_util.h" 12 #include "base/file_util.h"
12 #include "base/logging.h" 13 #include "base/logging.h"
13 #include "base/memory/ref_counted.h" 14 #include "base/memory/ref_counted.h"
14 #include "base/memory/scoped_ptr.h" 15 #include "base/memory/scoped_ptr.h"
15 #include "base/metrics/histogram.h" 16 #include "base/metrics/histogram.h"
16 #include "base/string_util.h" 17 #include "base/string_util.h"
17 #include "base/threading/thread.h" 18 #include "base/threading/thread.h"
18 #include "base/threading/thread_restrictions.h" 19 #include "base/threading/thread_restrictions.h"
19 #include "chrome/browser/diagnostics/sqlite_diagnostics.h" 20 #include "chrome/browser/diagnostics/sqlite_diagnostics.h"
20 #include "content/browser/browser_thread.h" 21 #include "content/browser/browser_thread.h"
21 #include "googleurl/src/gurl.h" 22 #include "googleurl/src/gurl.h"
22 #include "sql/meta_table.h" 23 #include "sql/meta_table.h"
23 #include "sql/statement.h" 24 #include "sql/statement.h"
24 #include "sql/transaction.h" 25 #include "sql/transaction.h"
25 26
26 using base::Time; 27 using base::Time;
27 28
28 // This class is designed to be shared between any calling threads and the 29 // This class is designed to be shared between any calling threads and the
29 // database thread. It batches operations and commits them on a timer. 30 // database thread. It batches operations and commits them on a timer.
31 // This class expects to be Load()'ed once on any thread. Loading occurs
32 // asynchronously on the DB thread and the caller will be notified on the IO
33 // thread. Subsequent to loading, mutations may be queued by any thread using
34 // AddCookie, UpdateCookieAccessTime, and DeleteCookie. These are flushed to
35 // disk on the DB thread every 30 seconds, 512 operations, or call to Flush(),
36 // whichever occurs first.
30 class SQLitePersistentCookieStore::Backend 37 class SQLitePersistentCookieStore::Backend
31 : public base::RefCountedThreadSafe<SQLitePersistentCookieStore::Backend> { 38 : public base::RefCountedThreadSafe<SQLitePersistentCookieStore::Backend> {
32 public: 39 public:
33 explicit Backend(const FilePath& path) 40 explicit Backend(const FilePath& path)
34 : path_(path), 41 : path_(path),
35 db_(NULL), 42 db_(NULL),
36 num_pending_(0), 43 num_pending_(0),
37 clear_local_state_on_exit_(false) { 44 clear_local_state_on_exit_(false) {
38 } 45 }
39 46
40 // Creates or load the SQLite database. 47 // Creates or load the SQLite database.
41 bool Load(std::vector<net::CookieMonster::CanonicalCookie*>* cookies); 48 bool Load(const LoadedCallback& loaded_callback);
42 49
43 // Batch a cookie addition. 50 // Batch a cookie addition.
44 void AddCookie(const net::CookieMonster::CanonicalCookie& cc); 51 void AddCookie(const net::CookieMonster::CanonicalCookie& cc);
45 52
46 // Batch a cookie access time update. 53 // Batch a cookie access time update.
47 void UpdateCookieAccessTime(const net::CookieMonster::CanonicalCookie& cc); 54 void UpdateCookieAccessTime(const net::CookieMonster::CanonicalCookie& cc);
48 55
49 // Batch a cookie deletion. 56 // Batch a cookie deletion.
50 void DeleteCookie(const net::CookieMonster::CanonicalCookie& cc); 57 void DeleteCookie(const net::CookieMonster::CanonicalCookie& cc);
51 58
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
84 91
85 OperationType op() const { return op_; } 92 OperationType op() const { return op_; }
86 const net::CookieMonster::CanonicalCookie& cc() const { return cc_; } 93 const net::CookieMonster::CanonicalCookie& cc() const { return cc_; }
87 94
88 private: 95 private:
89 OperationType op_; 96 OperationType op_;
90 net::CookieMonster::CanonicalCookie cc_; 97 net::CookieMonster::CanonicalCookie cc_;
91 }; 98 };
92 99
93 private: 100 private:
101 // Creates or load the SQLite database on DB thread.
102 void LoadAndNotifyOnDBThread(const LoadedCallback& loaded_callback);
103 // Notify the CookieMonster when loading complete.
104 void NotifyOnIOThread(
105 const LoadedCallback& loaded_callback,
106 bool load_success,
107 const std::vector<net::CookieMonster::CanonicalCookie*>& cookies);
108 // Initialize the data base.
109 bool InitializeDatabase();
110 // Load cookies to the data base, and read cookies.
111 bool LoadInternal(std::vector<net::CookieMonster::CanonicalCookie*>* cookies);
112
94 // Batch a cookie operation (add or delete) 113 // Batch a cookie operation (add or delete)
95 void BatchOperation(PendingOperation::OperationType op, 114 void BatchOperation(PendingOperation::OperationType op,
96 const net::CookieMonster::CanonicalCookie& cc); 115 const net::CookieMonster::CanonicalCookie& cc);
97 // Commit our pending operations to the database. 116 // Commit our pending operations to the database.
98 void Commit(); 117 void Commit();
99 // Close() executed on the background thread. 118 // Close() executed on the background thread.
100 void InternalBackgroundClose(); 119 void InternalBackgroundClose();
101 120
102 FilePath path_; 121 FilePath path_;
103 scoped_ptr<sql::Connection> db_; 122 scoped_ptr<sql::Connection> db_;
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
147 // Try to create the index every time. Older versions did not have this index, 166 // Try to create the index every time. Older versions did not have this index,
148 // so we want those people to get it. Ignore errors, since it may exist. 167 // so we want those people to get it. Ignore errors, since it may exist.
149 db->Execute("CREATE INDEX IF NOT EXISTS cookie_times ON cookies" 168 db->Execute("CREATE INDEX IF NOT EXISTS cookie_times ON cookies"
150 " (creation_utc)"); 169 " (creation_utc)");
151 return true; 170 return true;
152 } 171 }
153 172
154 } // namespace 173 } // namespace
155 174
156 bool SQLitePersistentCookieStore::Backend::Load( 175 bool SQLitePersistentCookieStore::Backend::Load(
157 std::vector<net::CookieMonster::CanonicalCookie*>* cookies) { 176 const LoadedCallback& loaded_callback) {
158 // This function should be called only once per instance. 177 // This function should be called only once per instance.
159 DCHECK(!db_.get()); 178 DCHECK(!db_.get());
179 BrowserThread::PostTask(
180 BrowserThread::DB, FROM_HERE,
181 base::Bind(&Backend::LoadAndNotifyOnDBThread, base::Unretained(this),
182 loaded_callback));
183 return true;
184 }
160 185
161 // Ensure the parent directory for storing cookies is created before reading 186 void SQLitePersistentCookieStore::Backend::LoadAndNotifyOnDBThread(
162 // from it. We make an exception to allow IO on the UI thread here because 187 const LoadedCallback& loaded_callback) {
163 // we are going to disk anyway in db_->Open. (This code will be moved to the 188 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
164 // DB thread as part of http://crbug.com/52909.) 189 std::vector<net::CookieMonster::CanonicalCookie*> cookies;
165 { 190
166 base::ThreadRestrictions::ScopedAllowIO allow_io; 191 bool load_success = LoadInternal(&cookies);
167 const FilePath dir = path_.DirName(); 192
168 if (!file_util::PathExists(dir) && !file_util::CreateDirectory(dir)) 193 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, base::Bind(
169 return false; 194 &SQLitePersistentCookieStore::Backend::NotifyOnIOThread,
195 base::Unretained(this), loaded_callback, load_success, cookies));
196 }
197
198 void SQLitePersistentCookieStore::Backend::NotifyOnIOThread(
199 const LoadedCallback& loaded_callback,
200 bool load_success,
201 const std::vector<net::CookieMonster::CanonicalCookie*>& cookies) {
202 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
203 loaded_callback.Run(cookies);
204 }
205
206 bool SQLitePersistentCookieStore::Backend::InitializeDatabase() {
207 const FilePath dir = path_.DirName();
208 if (!file_util::PathExists(dir) && !file_util::CreateDirectory(dir)) {
209 return false;
170 } 210 }
171 211
172 db_.reset(new sql::Connection); 212 db_.reset(new sql::Connection);
173 if (!db_->Open(path_)) { 213 if (!db_->Open(path_)) {
174 NOTREACHED() << "Unable to open cookie DB."; 214 NOTREACHED() << "Unable to open cookie DB.";
175 db_.reset(); 215 db_.reset();
176 return false; 216 return false;
177 } 217 }
178 218
179 db_->set_error_delegate(GetErrorHandlerForCookieDb()); 219 db_->set_error_delegate(GetErrorHandlerForCookieDb());
180 220
181 if (!EnsureDatabaseVersion() || !InitTable(db_.get())) { 221 if (!EnsureDatabaseVersion() || !InitTable(db_.get())) {
182 NOTREACHED() << "Unable to open cookie DB."; 222 NOTREACHED() << "Unable to open cookie DB.";
183 db_.reset(); 223 db_.reset();
184 return false; 224 return false;
185 } 225 }
186 226
187 db_->Preload(); 227 db_->Preload();
228 return true;
229 }
230
231 bool SQLitePersistentCookieStore::Backend::LoadInternal(
232 std::vector<net::CookieMonster::CanonicalCookie*>* cookies) {
233 if (!InitializeDatabase()) {
234 return false;
235 }
188 236
189 // Slurp all the cookies into the out-vector. 237 // Slurp all the cookies into the out-vector.
190 sql::Statement smt(db_->GetUniqueStatement( 238 sql::Statement smt(db_->GetUniqueStatement(
191 "SELECT creation_utc, host_key, name, value, path, expires_utc, secure, " 239 "SELECT creation_utc, host_key, name, value, path, expires_utc, secure, "
192 "httponly, last_access_utc FROM cookies")); 240 "httponly, last_access_utc FROM cookies"));
193 if (!smt) { 241 if (!smt) {
194 NOTREACHED() << "select statement prep failed"; 242 NOTREACHED() << "select statement prep failed";
195 db_.reset(); 243 db_.reset();
196 return false; 244 return false;
197 } 245 }
(...skipping 242 matching lines...) Expand 10 before | Expand all | Expand 10 after
440 // Posting it from here means there is less chance of another task getting 488 // Posting it from here means there is less chance of another task getting
441 // onto the message queue first, than if we posted it from Commit() itself. 489 // onto the message queue first, than if we posted it from Commit() itself.
442 BrowserThread::PostTask(BrowserThread::DB, FROM_HERE, completion_task); 490 BrowserThread::PostTask(BrowserThread::DB, FROM_HERE, completion_task);
443 } 491 }
444 } 492 }
445 493
446 // Fire off a close message to the background thread. We could still have a 494 // Fire off a close message to the background thread. We could still have a
447 // pending commit timer that will be holding a reference on us, but if/when 495 // pending commit timer that will be holding a reference on us, but if/when
448 // this fires we will already have been cleaned up and it will be ignored. 496 // this fires we will already have been cleaned up and it will be ignored.
449 void SQLitePersistentCookieStore::Backend::Close() { 497 void SQLitePersistentCookieStore::Backend::Close() {
450 DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::DB)); 498 if (BrowserThread::CurrentlyOn(BrowserThread::DB)) {
451 // Must close the backend on the background thread. 499 InternalBackgroundClose();
452 BrowserThread::PostTask( 500 } else {
453 BrowserThread::DB, FROM_HERE, 501 // Must close the backend on the background thread.
454 NewRunnableMethod(this, &Backend::InternalBackgroundClose)); 502 BrowserThread::PostTask(
503 BrowserThread::DB, FROM_HERE,
504 NewRunnableMethod(this, &Backend::InternalBackgroundClose));
505 }
455 } 506 }
456 507
457 void SQLitePersistentCookieStore::Backend::InternalBackgroundClose() { 508 void SQLitePersistentCookieStore::Backend::InternalBackgroundClose() {
458 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); 509 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
459 // Commit any pending operations 510 // Commit any pending operations
460 Commit(); 511 Commit();
461 512
462 db_.reset(); 513 db_.reset();
463 514
464 if (clear_local_state_on_exit_) 515 if (clear_local_state_on_exit_)
(...skipping 11 matching lines...) Expand all
476 527
477 SQLitePersistentCookieStore::~SQLitePersistentCookieStore() { 528 SQLitePersistentCookieStore::~SQLitePersistentCookieStore() {
478 if (backend_.get()) { 529 if (backend_.get()) {
479 backend_->Close(); 530 backend_->Close();
480 // Release our reference, it will probably still have a reference if the 531 // Release our reference, it will probably still have a reference if the
481 // background thread has not run Close() yet. 532 // background thread has not run Close() yet.
482 backend_ = NULL; 533 backend_ = NULL;
483 } 534 }
484 } 535 }
485 536
486 bool SQLitePersistentCookieStore::Load( 537 bool SQLitePersistentCookieStore::Load(const LoadedCallback& loaded_callback) {
487 std::vector<net::CookieMonster::CanonicalCookie*>* cookies) { 538 return backend_->Load(loaded_callback);
488 return backend_->Load(cookies);
489 } 539 }
490 540
491 void SQLitePersistentCookieStore::AddCookie( 541 void SQLitePersistentCookieStore::AddCookie(
492 const net::CookieMonster::CanonicalCookie& cc) { 542 const net::CookieMonster::CanonicalCookie& cc) {
493 if (backend_.get()) 543 if (backend_.get())
494 backend_->AddCookie(cc); 544 backend_->AddCookie(cc);
495 } 545 }
496 546
497 void SQLitePersistentCookieStore::UpdateCookieAccessTime( 547 void SQLitePersistentCookieStore::UpdateCookieAccessTime(
498 const net::CookieMonster::CanonicalCookie& cc) { 548 const net::CookieMonster::CanonicalCookie& cc) {
(...skipping 12 matching lines...) Expand all
511 if (backend_.get()) 561 if (backend_.get())
512 backend_->SetClearLocalStateOnExit(clear_local_state); 562 backend_->SetClearLocalStateOnExit(clear_local_state);
513 } 563 }
514 564
515 void SQLitePersistentCookieStore::Flush(Task* completion_task) { 565 void SQLitePersistentCookieStore::Flush(Task* completion_task) {
516 if (backend_.get()) 566 if (backend_.get())
517 backend_->Flush(completion_task); 567 backend_->Flush(completion_task);
518 else if (completion_task) 568 else if (completion_task)
519 MessageLoop::current()->PostTask(FROM_HERE, completion_task); 569 MessageLoop::current()->PostTask(FROM_HERE, completion_task);
520 } 570 }
OLDNEW
« no previous file with comments | « chrome/browser/net/sqlite_persistent_cookie_store.h ('k') | chrome/browser/net/sqlite_persistent_cookie_store_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698