| OLD | NEW |
| 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 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 "app/sql/meta_table.h" | 9 #include "app/sql/meta_table.h" |
| 10 #include "app/sql/statement.h" | 10 #include "app/sql/statement.h" |
| (...skipping 13 matching lines...) Expand all Loading... |
| 24 using base::Time; | 24 using base::Time; |
| 25 | 25 |
| 26 // This class is designed to be shared between any calling threads and the | 26 // This class is designed to be shared between any calling threads and the |
| 27 // database thread. It batches operations and commits them on a timer. | 27 // database thread. It batches operations and commits them on a timer. |
| 28 class SQLitePersistentCookieStore::Backend | 28 class SQLitePersistentCookieStore::Backend |
| 29 : public base::RefCountedThreadSafe<SQLitePersistentCookieStore::Backend> { | 29 : public base::RefCountedThreadSafe<SQLitePersistentCookieStore::Backend> { |
| 30 public: | 30 public: |
| 31 explicit Backend(const FilePath& path) | 31 explicit Backend(const FilePath& path) |
| 32 : path_(path), | 32 : path_(path), |
| 33 db_(NULL), | 33 db_(NULL), |
| 34 num_pending_(0) { | 34 num_pending_(0), |
| 35 clear_local_state_on_exit_(false) { |
| 35 } | 36 } |
| 36 | 37 |
| 37 // Creates or load the SQLite database. | 38 // Creates or load the SQLite database. |
| 38 bool Load(std::vector<net::CookieMonster::CanonicalCookie*>* cookies); | 39 bool Load(std::vector<net::CookieMonster::CanonicalCookie*>* cookies); |
| 39 | 40 |
| 40 // Batch a cookie addition. | 41 // Batch a cookie addition. |
| 41 void AddCookie(const net::CookieMonster::CanonicalCookie& cc); | 42 void AddCookie(const net::CookieMonster::CanonicalCookie& cc); |
| 42 | 43 |
| 43 // Batch a cookie access time update. | 44 // Batch a cookie access time update. |
| 44 void UpdateCookieAccessTime(const net::CookieMonster::CanonicalCookie& cc); | 45 void UpdateCookieAccessTime(const net::CookieMonster::CanonicalCookie& cc); |
| 45 | 46 |
| 46 // Batch a cookie deletion. | 47 // Batch a cookie deletion. |
| 47 void DeleteCookie(const net::CookieMonster::CanonicalCookie& cc); | 48 void DeleteCookie(const net::CookieMonster::CanonicalCookie& cc); |
| 48 | 49 |
| 49 // Commit any pending operations and close the database. This must be called | 50 // Commit any pending operations and close the database. This must be called |
| 50 // before the object is destructed. | 51 // before the object is destructed. |
| 51 void Close(); | 52 void Close(); |
| 52 | 53 |
| 54 void SetClearLocalStateOnExit(bool clear_local_state); |
| 55 |
| 53 private: | 56 private: |
| 54 friend class base::RefCountedThreadSafe<SQLitePersistentCookieStore::Backend>; | 57 friend class base::RefCountedThreadSafe<SQLitePersistentCookieStore::Backend>; |
| 55 | 58 |
| 56 // You should call Close() before destructing this object. | 59 // You should call Close() before destructing this object. |
| 57 ~Backend() { | 60 ~Backend() { |
| 58 DCHECK(!db_.get()) << "Close should have already been called."; | 61 DCHECK(!db_.get()) << "Close should have already been called."; |
| 59 DCHECK(num_pending_ == 0 && pending_.empty()); | 62 DCHECK(num_pending_ == 0 && pending_.empty()); |
| 60 } | 63 } |
| 61 | 64 |
| 62 // Database upgrade statements. | 65 // Database upgrade statements. |
| (...skipping 28 matching lines...) Expand all Loading... |
| 91 // Close() executed on the background thread. | 94 // Close() executed on the background thread. |
| 92 void InternalBackgroundClose(); | 95 void InternalBackgroundClose(); |
| 93 | 96 |
| 94 FilePath path_; | 97 FilePath path_; |
| 95 scoped_ptr<sql::Connection> db_; | 98 scoped_ptr<sql::Connection> db_; |
| 96 sql::MetaTable meta_table_; | 99 sql::MetaTable meta_table_; |
| 97 | 100 |
| 98 typedef std::list<PendingOperation*> PendingOperationsList; | 101 typedef std::list<PendingOperation*> PendingOperationsList; |
| 99 PendingOperationsList pending_; | 102 PendingOperationsList pending_; |
| 100 PendingOperationsList::size_type num_pending_; | 103 PendingOperationsList::size_type num_pending_; |
| 101 Lock pending_lock_; // Guard pending_ and num_pending_ | 104 // True if the persistent store should be deleted upon destruction. |
| 105 bool clear_local_state_on_exit_; |
| 106 // Guard |pending_|, |num_pending_| and |clear_local_state_on_exit_|. |
| 107 Lock lock_; |
| 102 | 108 |
| 103 DISALLOW_COPY_AND_ASSIGN(Backend); | 109 DISALLOW_COPY_AND_ASSIGN(Backend); |
| 104 }; | 110 }; |
| 105 | 111 |
| 106 // Version number of the database. In version 4, we migrated the time epoch. | 112 // Version number of the database. In version 4, we migrated the time epoch. |
| 107 // If you open the DB with an older version on Mac or Linux, the times will | 113 // If you open the DB with an older version on Mac or Linux, the times will |
| 108 // look wonky, but the file will likely be usable. On Windows version 3 and 4 | 114 // look wonky, but the file will likely be usable. On Windows version 3 and 4 |
| 109 // are the same. | 115 // are the same. |
| 110 // | 116 // |
| 111 // Version 3 updated the database to include the last access time, so we can | 117 // Version 3 updated the database to include the last access time, so we can |
| (...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 290 static const int kCommitIntervalMs = 30 * 1000; | 296 static const int kCommitIntervalMs = 30 * 1000; |
| 291 // Commit right away if we have more than 512 outstanding operations. | 297 // Commit right away if we have more than 512 outstanding operations. |
| 292 static const size_t kCommitAfterBatchSize = 512; | 298 static const size_t kCommitAfterBatchSize = 512; |
| 293 DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::DB)); | 299 DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::DB)); |
| 294 | 300 |
| 295 // We do a full copy of the cookie here, and hopefully just here. | 301 // We do a full copy of the cookie here, and hopefully just here. |
| 296 scoped_ptr<PendingOperation> po(new PendingOperation(op, cc)); | 302 scoped_ptr<PendingOperation> po(new PendingOperation(op, cc)); |
| 297 | 303 |
| 298 PendingOperationsList::size_type num_pending; | 304 PendingOperationsList::size_type num_pending; |
| 299 { | 305 { |
| 300 AutoLock locked(pending_lock_); | 306 AutoLock locked(lock_); |
| 301 pending_.push_back(po.release()); | 307 pending_.push_back(po.release()); |
| 302 num_pending = ++num_pending_; | 308 num_pending = ++num_pending_; |
| 303 } | 309 } |
| 304 | 310 |
| 305 if (num_pending == 1) { | 311 if (num_pending == 1) { |
| 306 // We've gotten our first entry for this batch, fire off the timer. | 312 // We've gotten our first entry for this batch, fire off the timer. |
| 307 BrowserThread::PostDelayedTask( | 313 BrowserThread::PostDelayedTask( |
| 308 BrowserThread::DB, FROM_HERE, | 314 BrowserThread::DB, FROM_HERE, |
| 309 NewRunnableMethod(this, &Backend::Commit), kCommitIntervalMs); | 315 NewRunnableMethod(this, &Backend::Commit), kCommitIntervalMs); |
| 310 } else if (num_pending == kCommitAfterBatchSize) { | 316 } else if (num_pending == kCommitAfterBatchSize) { |
| 311 // We've reached a big enough batch, fire off a commit now. | 317 // We've reached a big enough batch, fire off a commit now. |
| 312 BrowserThread::PostTask( | 318 BrowserThread::PostTask( |
| 313 BrowserThread::DB, FROM_HERE, | 319 BrowserThread::DB, FROM_HERE, |
| 314 NewRunnableMethod(this, &Backend::Commit)); | 320 NewRunnableMethod(this, &Backend::Commit)); |
| 315 } | 321 } |
| 316 } | 322 } |
| 317 | 323 |
| 318 void SQLitePersistentCookieStore::Backend::Commit() { | 324 void SQLitePersistentCookieStore::Backend::Commit() { |
| 319 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); | 325 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); |
| 320 PendingOperationsList ops; | 326 PendingOperationsList ops; |
| 321 { | 327 { |
| 322 AutoLock locked(pending_lock_); | 328 AutoLock locked(lock_); |
| 323 pending_.swap(ops); | 329 pending_.swap(ops); |
| 324 num_pending_ = 0; | 330 num_pending_ = 0; |
| 325 } | 331 } |
| 326 | 332 |
| 327 // Maybe an old timer fired or we are already Close()'ed. | 333 // Maybe an old timer fired or we are already Close()'ed. |
| 328 if (!db_.get() || ops.empty()) | 334 if (!db_.get() || ops.empty()) |
| 329 return; | 335 return; |
| 330 | 336 |
| 331 sql::Statement add_smt(db_->GetCachedStatement(SQL_FROM_HERE, | 337 sql::Statement add_smt(db_->GetCachedStatement(SQL_FROM_HERE, |
| 332 "INSERT INTO cookies (creation_utc, host_key, name, value, path, " | 338 "INSERT INTO cookies (creation_utc, host_key, name, value, path, " |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 413 BrowserThread::DB, FROM_HERE, | 419 BrowserThread::DB, FROM_HERE, |
| 414 NewRunnableMethod(this, &Backend::InternalBackgroundClose)); | 420 NewRunnableMethod(this, &Backend::InternalBackgroundClose)); |
| 415 } | 421 } |
| 416 | 422 |
| 417 void SQLitePersistentCookieStore::Backend::InternalBackgroundClose() { | 423 void SQLitePersistentCookieStore::Backend::InternalBackgroundClose() { |
| 418 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); | 424 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); |
| 419 // Commit any pending operations | 425 // Commit any pending operations |
| 420 Commit(); | 426 Commit(); |
| 421 | 427 |
| 422 db_.reset(); | 428 db_.reset(); |
| 429 |
| 430 if (clear_local_state_on_exit_) |
| 431 file_util::Delete(path_, false); |
| 423 } | 432 } |
| 424 | 433 |
| 434 void SQLitePersistentCookieStore::Backend::SetClearLocalStateOnExit( |
| 435 bool clear_local_state) { |
| 436 AutoLock locked(lock_); |
| 437 clear_local_state_on_exit_ = clear_local_state; |
| 438 } |
| 425 SQLitePersistentCookieStore::SQLitePersistentCookieStore(const FilePath& path) | 439 SQLitePersistentCookieStore::SQLitePersistentCookieStore(const FilePath& path) |
| 426 : backend_(new Backend(path)) { | 440 : backend_(new Backend(path)) { |
| 427 } | 441 } |
| 428 | 442 |
| 429 SQLitePersistentCookieStore::~SQLitePersistentCookieStore() { | 443 SQLitePersistentCookieStore::~SQLitePersistentCookieStore() { |
| 430 if (backend_.get()) { | 444 if (backend_.get()) { |
| 431 backend_->Close(); | 445 backend_->Close(); |
| 432 // Release our reference, it will probably still have a reference if the | 446 // Release our reference, it will probably still have a reference if the |
| 433 // background thread has not run Close() yet. | 447 // background thread has not run Close() yet. |
| 434 backend_ = NULL; | 448 backend_ = NULL; |
| (...skipping 16 matching lines...) Expand all Loading... |
| 451 if (backend_.get()) | 465 if (backend_.get()) |
| 452 backend_->UpdateCookieAccessTime(cc); | 466 backend_->UpdateCookieAccessTime(cc); |
| 453 } | 467 } |
| 454 | 468 |
| 455 void SQLitePersistentCookieStore::DeleteCookie( | 469 void SQLitePersistentCookieStore::DeleteCookie( |
| 456 const net::CookieMonster::CanonicalCookie& cc) { | 470 const net::CookieMonster::CanonicalCookie& cc) { |
| 457 if (backend_.get()) | 471 if (backend_.get()) |
| 458 backend_->DeleteCookie(cc); | 472 backend_->DeleteCookie(cc); |
| 459 } | 473 } |
| 460 | 474 |
| 461 // static | 475 void SQLitePersistentCookieStore::SetClearLocalStateOnExit( |
| 462 void SQLitePersistentCookieStore::ClearLocalState( | 476 bool clear_local_state) { |
| 463 const FilePath& path) { | 477 if (backend_.get()) |
| 464 file_util::Delete(path, false); | 478 backend_->SetClearLocalStateOnExit(clear_local_state); |
| 465 } | 479 } |
| OLD | NEW |