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 |