| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 #include <map> | 8 #include <map> |
| 9 #include <set> | 9 #include <set> |
| 10 #include <utility> | 10 #include <utility> |
| (...skipping 14 matching lines...) Expand all Loading... |
| 25 #include "base/time.h" | 25 #include "base/time.h" |
| 26 #include "chrome/browser/diagnostics/sqlite_diagnostics.h" | 26 #include "chrome/browser/diagnostics/sqlite_diagnostics.h" |
| 27 #include "chrome/browser/net/clear_on_exit_policy.h" | 27 #include "chrome/browser/net/clear_on_exit_policy.h" |
| 28 #include "content/public/browser/browser_thread.h" | 28 #include "content/public/browser/browser_thread.h" |
| 29 #include "googleurl/src/gurl.h" | 29 #include "googleurl/src/gurl.h" |
| 30 #include "net/base/registry_controlled_domains/registry_controlled_domain.h" | 30 #include "net/base/registry_controlled_domains/registry_controlled_domain.h" |
| 31 #include "net/cookies/canonical_cookie.h" | 31 #include "net/cookies/canonical_cookie.h" |
| 32 #include "sql/meta_table.h" | 32 #include "sql/meta_table.h" |
| 33 #include "sql/statement.h" | 33 #include "sql/statement.h" |
| 34 #include "sql/transaction.h" | 34 #include "sql/transaction.h" |
| 35 #include "third_party/sqlite/sqlite3.h" |
| 35 | 36 |
| 36 using base::Time; | 37 using base::Time; |
| 37 using content::BrowserThread; | 38 using content::BrowserThread; |
| 38 | 39 |
| 39 // This class is designed to be shared between any calling threads and the | 40 // This class is designed to be shared between any calling threads and the |
| 40 // database thread. It batches operations and commits them on a timer. | 41 // database thread. It batches operations and commits them on a timer. |
| 41 // | 42 // |
| 42 // SQLitePersistentCookieStore::Load is called to load all cookies. It | 43 // SQLitePersistentCookieStore::Load is called to load all cookies. It |
| 43 // delegates to Backend::Load, which posts a Backend::LoadAndNotifyOnDBThread | 44 // delegates to Backend::Load, which posts a Backend::LoadAndNotifyOnDBThread |
| 44 // task to the DB thread. This task calls Backend::ChainLoadCookies(), which | 45 // task to the DB thread. This task calls Backend::ChainLoadCookies(), which |
| (...skipping 22 matching lines...) Expand all Loading... |
| 67 : path_(path), | 68 : path_(path), |
| 68 db_(NULL), | 69 db_(NULL), |
| 69 num_pending_(0), | 70 num_pending_(0), |
| 70 force_keep_session_state_(false), | 71 force_keep_session_state_(false), |
| 71 initialized_(false), | 72 initialized_(false), |
| 72 restore_old_session_cookies_(restore_old_session_cookies), | 73 restore_old_session_cookies_(restore_old_session_cookies), |
| 73 clear_on_exit_policy_(clear_on_exit_policy), | 74 clear_on_exit_policy_(clear_on_exit_policy), |
| 74 num_cookies_read_(0), | 75 num_cookies_read_(0), |
| 75 num_priority_waiting_(0), | 76 num_priority_waiting_(0), |
| 76 total_priority_requests_(0) { | 77 total_priority_requests_(0) { |
| 78 error_delegate_ = |
| 79 new KillDatabaseErrorDelegate(this, GetErrorHandlerForCookieDb()); |
| 77 } | 80 } |
| 78 | 81 |
| 79 // Creates or loads the SQLite database. | 82 // Creates or loads the SQLite database. |
| 80 void Load(const LoadedCallback& loaded_callback); | 83 void Load(const LoadedCallback& loaded_callback); |
| 81 | 84 |
| 82 // Loads cookies for the domain key (eTLD+1). | 85 // Loads cookies for the domain key (eTLD+1). |
| 83 void LoadCookiesForKey(const std::string& domain, | 86 void LoadCookiesForKey(const std::string& domain, |
| 84 const LoadedCallback& loaded_callback); | 87 const LoadedCallback& loaded_callback); |
| 85 | 88 |
| 86 // Batch a cookie addition. | 89 // Batch a cookie addition. |
| (...skipping 10 matching lines...) Expand all Loading... |
| 97 | 100 |
| 98 // Commit any pending operations and close the database. This must be called | 101 // Commit any pending operations and close the database. This must be called |
| 99 // before the object is destructed. | 102 // before the object is destructed. |
| 100 void Close(); | 103 void Close(); |
| 101 | 104 |
| 102 void SetForceKeepSessionState(); | 105 void SetForceKeepSessionState(); |
| 103 | 106 |
| 104 private: | 107 private: |
| 105 friend class base::RefCountedThreadSafe<SQLitePersistentCookieStore::Backend>; | 108 friend class base::RefCountedThreadSafe<SQLitePersistentCookieStore::Backend>; |
| 106 | 109 |
| 110 class KillDatabaseErrorDelegate : public sql::ErrorDelegate { |
| 111 public: |
| 112 KillDatabaseErrorDelegate(Backend* backend, |
| 113 sql::ErrorDelegate* wrapped_delegate); |
| 114 // ErrorDelegate implementation. |
| 115 virtual int OnError(int error, |
| 116 sql::Connection* connection, |
| 117 sql::Statement* stmt) OVERRIDE; |
| 118 |
| 119 void reset_backend() { |
| 120 backend_ = NULL; |
| 121 } |
| 122 |
| 123 protected: |
| 124 virtual ~KillDatabaseErrorDelegate() {} |
| 125 |
| 126 private: |
| 127 |
| 128 // Do not increment the count on Backend, as that would create a circular |
| 129 // reference (Backend -> Connection -> ErrorDelegate -> Backend). Instead, |
| 130 // Backend will call reset_backend() when it is going away. |
| 131 Backend* backend_; |
| 132 scoped_refptr<sql::ErrorDelegate> wrapped_delegate_; |
| 133 |
| 134 DISALLOW_COPY_AND_ASSIGN(KillDatabaseErrorDelegate); |
| 135 }; |
| 136 |
| 107 // You should call Close() before destructing this object. | 137 // You should call Close() before destructing this object. |
| 108 ~Backend() { | 138 ~Backend() { |
| 139 if (error_delegate_.get()) { |
| 140 error_delegate_->reset_backend(); |
| 141 error_delegate_ = NULL; |
| 142 } |
| 109 DCHECK(!db_.get()) << "Close should have already been called."; | 143 DCHECK(!db_.get()) << "Close should have already been called."; |
| 110 DCHECK(num_pending_ == 0 && pending_.empty()); | 144 DCHECK(num_pending_ == 0 && pending_.empty()); |
| 111 } | 145 } |
| 112 | 146 |
| 113 // Database upgrade statements. | 147 // Database upgrade statements. |
| 114 bool EnsureDatabaseVersion(); | 148 bool EnsureDatabaseVersion(); |
| 115 | 149 |
| 116 class PendingOperation { | 150 class PendingOperation { |
| 117 public: | 151 public: |
| 118 typedef enum { | 152 typedef enum { |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 182 const net::CanonicalCookie& cc); | 216 const net::CanonicalCookie& cc); |
| 183 // Commit our pending operations to the database. | 217 // Commit our pending operations to the database. |
| 184 void Commit(); | 218 void Commit(); |
| 185 // Close() executed on the background thread. | 219 // Close() executed on the background thread. |
| 186 void InternalBackgroundClose(); | 220 void InternalBackgroundClose(); |
| 187 | 221 |
| 188 void DeleteSessionCookiesOnStartup(); | 222 void DeleteSessionCookiesOnStartup(); |
| 189 | 223 |
| 190 void DeleteSessionCookiesOnShutdown(); | 224 void DeleteSessionCookiesOnShutdown(); |
| 191 | 225 |
| 226 void KillDatabase(); |
| 227 |
| 192 FilePath path_; | 228 FilePath path_; |
| 193 scoped_ptr<sql::Connection> db_; | 229 scoped_ptr<sql::Connection> db_; |
| 230 scoped_refptr<KillDatabaseErrorDelegate> error_delegate_; |
| 194 sql::MetaTable meta_table_; | 231 sql::MetaTable meta_table_; |
| 195 | 232 |
| 196 typedef std::list<PendingOperation*> PendingOperationsList; | 233 typedef std::list<PendingOperation*> PendingOperationsList; |
| 197 PendingOperationsList pending_; | 234 PendingOperationsList pending_; |
| 198 PendingOperationsList::size_type num_pending_; | 235 PendingOperationsList::size_type num_pending_; |
| 199 // True if the persistent store should skip delete on exit rules. | 236 // True if the persistent store should skip delete on exit rules. |
| 200 bool force_keep_session_state_; | 237 bool force_keep_session_state_; |
| 201 // Guard |cookies_|, |pending_|, |num_pending_|, |force_keep_session_state_| | 238 // Guard |cookies_|, |pending_|, |num_pending_|, |force_keep_session_state_| |
| 202 base::Lock lock_; | 239 base::Lock lock_; |
| 203 | 240 |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 240 int total_priority_requests_; | 277 int total_priority_requests_; |
| 241 // The time when |num_priority_waiting_| incremented to 1. | 278 // The time when |num_priority_waiting_| incremented to 1. |
| 242 base::Time current_priority_wait_start_; | 279 base::Time current_priority_wait_start_; |
| 243 // The cumulative duration of time when |num_priority_waiting_| was greater | 280 // The cumulative duration of time when |num_priority_waiting_| was greater |
| 244 // than 1. | 281 // than 1. |
| 245 base::TimeDelta priority_wait_duration_; | 282 base::TimeDelta priority_wait_duration_; |
| 246 | 283 |
| 247 DISALLOW_COPY_AND_ASSIGN(Backend); | 284 DISALLOW_COPY_AND_ASSIGN(Backend); |
| 248 }; | 285 }; |
| 249 | 286 |
| 287 SQLitePersistentCookieStore::Backend::KillDatabaseErrorDelegate:: |
| 288 KillDatabaseErrorDelegate(Backend* backend, |
| 289 sql::ErrorDelegate* wrapped_delegate) |
| 290 : backend_(backend), |
| 291 wrapped_delegate_(wrapped_delegate) { |
| 292 } |
| 293 |
| 294 int SQLitePersistentCookieStore::Backend::KillDatabaseErrorDelegate::OnError( |
| 295 int error, sql::Connection* connection, sql::Statement* stmt) { |
| 296 if (wrapped_delegate_.get()) |
| 297 error = wrapped_delegate_->OnError(error, connection, stmt); |
| 298 |
| 299 bool delete_db = false; |
| 300 |
| 301 switch (error) { |
| 302 case SQLITE_DONE: |
| 303 case SQLITE_OK: |
| 304 // Theoretically, the wrapped delegate might have resolved the error, and |
| 305 // we would end up here. |
| 306 break; |
| 307 |
| 308 case SQLITE_CORRUPT: |
| 309 case SQLITE_NOTADB: |
| 310 // Highly unlikely we would ever recover from these. |
| 311 delete_db = true; |
| 312 break; |
| 313 |
| 314 case SQLITE_CANTOPEN: |
| 315 // TODO(erikwright): Figure out what this means. |
| 316 break; |
| 317 |
| 318 case SQLITE_IOERR: |
| 319 // This could be broken blocks, in which case deleting the DB would be a |
| 320 // good idea. But it might also be transient. |
| 321 // TODO(erikwright): Figure out if we can distinguish between the two, |
| 322 // or determine through metrics analysis to what extent these failures are |
| 323 // transient. |
| 324 break; |
| 325 |
| 326 case SQLITE_BUSY: |
| 327 // Presumably transient. |
| 328 break; |
| 329 |
| 330 case SQLITE_TOOBIG: |
| 331 case SQLITE_FULL: |
| 332 case SQLITE_NOMEM: |
| 333 // Not a problem with the database. |
| 334 break; |
| 335 |
| 336 case SQLITE_READONLY: |
| 337 // Presumably either transient or we don't have the privileges to |
| 338 // move/delete the file anyway. |
| 339 break; |
| 340 |
| 341 case SQLITE_CONSTRAINT: |
| 342 case SQLITE_ERROR: |
| 343 // These probably indicate a programming error or a migration failure that |
| 344 // we prefer not to mask. |
| 345 break; |
| 346 |
| 347 case SQLITE_LOCKED: |
| 348 case SQLITE_INTERNAL: |
| 349 case SQLITE_PERM: |
| 350 case SQLITE_ABORT: |
| 351 case SQLITE_INTERRUPT: |
| 352 case SQLITE_NOTFOUND: |
| 353 case SQLITE_PROTOCOL: |
| 354 case SQLITE_EMPTY: |
| 355 case SQLITE_SCHEMA: |
| 356 case SQLITE_MISMATCH: |
| 357 case SQLITE_MISUSE: |
| 358 case SQLITE_NOLFS: |
| 359 case SQLITE_AUTH: |
| 360 case SQLITE_FORMAT: |
| 361 case SQLITE_RANGE: |
| 362 case SQLITE_ROW: |
| 363 // None of these appear in error reports, so for now let's not try to |
| 364 // guess at how to handle them. |
| 365 break; |
| 366 } |
| 367 |
| 368 if (delete_db && backend_) { |
| 369 // Don't just do the close/delete here, as we are being called by |db| and |
| 370 // that seems dangerous. |
| 371 MessageLoop::current()->PostTask( |
| 372 FROM_HERE, base::Bind(&Backend::KillDatabase, backend_)); |
| 373 |
| 374 // Avoid being called more than once. There should still be a reference to |
| 375 // this ErrorDelegate in the backend, but just in case don't refer to any |
| 376 // members from here forward. |
| 377 connection->set_error_delegate(wrapped_delegate_.get()); |
| 378 } |
| 379 |
| 380 return error; |
| 381 } |
| 382 |
| 250 // Version number of the database. | 383 // Version number of the database. |
| 251 // | 384 // |
| 252 // Version 5 adds the columns has_expires and is_persistent, so that the | 385 // Version 5 adds the columns has_expires and is_persistent, so that the |
| 253 // database can store session cookies as well as persistent cookies. Databases | 386 // database can store session cookies as well as persistent cookies. Databases |
| 254 // of version 5 are incompatible with older versions of code. If a database of | 387 // of version 5 are incompatible with older versions of code. If a database of |
| 255 // version 5 is read by older code, session cookies will be treated as normal | 388 // version 5 is read by older code, session cookies will be treated as normal |
| 256 // cookies. Currently, these fields are written, but not read anymore. | 389 // cookies. Currently, these fields are written, but not read anymore. |
| 257 // | 390 // |
| 258 // In version 4, we migrated the time epoch. If you open the DB with an older | 391 // In version 4, we migrated the time epoch. If you open the DB with an older |
| 259 // version on Mac or Linux, the times will look wonky, but the file will likely | 392 // version on Mac or Linux, the times will look wonky, but the file will likely |
| (...skipping 227 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 487 return false; | 620 return false; |
| 488 } | 621 } |
| 489 | 622 |
| 490 int64 db_size = 0; | 623 int64 db_size = 0; |
| 491 if (file_util::GetFileSize(path_, &db_size)) { | 624 if (file_util::GetFileSize(path_, &db_size)) { |
| 492 base::ThreadRestrictions::ScopedAllowIO allow_io; | 625 base::ThreadRestrictions::ScopedAllowIO allow_io; |
| 493 UMA_HISTOGRAM_COUNTS("Cookie.DBSizeInKB", db_size / 1024 ); | 626 UMA_HISTOGRAM_COUNTS("Cookie.DBSizeInKB", db_size / 1024 ); |
| 494 } | 627 } |
| 495 | 628 |
| 496 db_.reset(new sql::Connection); | 629 db_.reset(new sql::Connection); |
| 630 db_->set_error_delegate(error_delegate_.get()); |
| 631 |
| 497 if (!db_->Open(path_)) { | 632 if (!db_->Open(path_)) { |
| 498 NOTREACHED() << "Unable to open cookie DB."; | 633 NOTREACHED() << "Unable to open cookie DB."; |
| 499 db_.reset(); | 634 db_.reset(); |
| 500 return false; | 635 return false; |
| 501 } | 636 } |
| 502 | 637 |
| 503 db_->set_error_delegate(GetErrorHandlerForCookieDb()); | |
| 504 | |
| 505 if (!EnsureDatabaseVersion() || !InitTable(db_.get())) { | 638 if (!EnsureDatabaseVersion() || !InitTable(db_.get())) { |
| 506 NOTREACHED() << "Unable to open cookie DB."; | 639 NOTREACHED() << "Unable to open cookie DB."; |
| 507 db_.reset(); | 640 db_.reset(); |
| 508 return false; | 641 return false; |
| 509 } | 642 } |
| 510 | 643 |
| 511 UMA_HISTOGRAM_CUSTOM_TIMES( | 644 UMA_HISTOGRAM_CUSTOM_TIMES( |
| 512 "Cookie.TimeInitializeDB", | 645 "Cookie.TimeInitializeDB", |
| 513 base::Time::Now() - start, | 646 base::Time::Now() - start, |
| 514 base::TimeDelta::FromMilliseconds(1), base::TimeDelta::FromMinutes(1), | 647 base::TimeDelta::FromMilliseconds(1), base::TimeDelta::FromMinutes(1), |
| (...skipping 446 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 961 del_smt.BindString(0, it->first.first); | 1094 del_smt.BindString(0, it->first.first); |
| 962 del_smt.BindInt(1, it->first.second); | 1095 del_smt.BindInt(1, it->first.second); |
| 963 if (!del_smt.Run()) | 1096 if (!del_smt.Run()) |
| 964 NOTREACHED() << "Could not delete a cookie from the DB."; | 1097 NOTREACHED() << "Could not delete a cookie from the DB."; |
| 965 } | 1098 } |
| 966 | 1099 |
| 967 if (!transaction.Commit()) | 1100 if (!transaction.Commit()) |
| 968 LOG(WARNING) << "Unable to delete cookies on shutdown."; | 1101 LOG(WARNING) << "Unable to delete cookies on shutdown."; |
| 969 } | 1102 } |
| 970 | 1103 |
| 1104 void SQLitePersistentCookieStore::Backend::KillDatabase() { |
| 1105 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); |
| 1106 |
| 1107 if (db_.get()) { |
| 1108 // This Backend will now be in-memory only. In a future run we will recreate |
| 1109 // the database. Hopefully things go better then! |
| 1110 bool success = db_->Raze(); |
| 1111 UMA_HISTOGRAM_BOOLEAN("Cookie.KillDatabaseResult", success); |
| 1112 db_->Close(); |
| 1113 db_.reset(); |
| 1114 } |
| 1115 } |
| 1116 |
| 971 void SQLitePersistentCookieStore::Backend::SetForceKeepSessionState() { | 1117 void SQLitePersistentCookieStore::Backend::SetForceKeepSessionState() { |
| 972 base::AutoLock locked(lock_); | 1118 base::AutoLock locked(lock_); |
| 973 force_keep_session_state_ = true; | 1119 force_keep_session_state_ = true; |
| 974 } | 1120 } |
| 975 | 1121 |
| 976 void SQLitePersistentCookieStore::Backend::DeleteSessionCookiesOnStartup() { | 1122 void SQLitePersistentCookieStore::Backend::DeleteSessionCookiesOnStartup() { |
| 977 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); | 1123 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); |
| 978 if (!db_->Execute("DELETE FROM cookies WHERE persistent == 0")) | 1124 if (!db_->Execute("DELETE FROM cookies WHERE persistent == 0")) |
| 979 LOG(WARNING) << "Unable to delete session cookies."; | 1125 LOG(WARNING) << "Unable to delete session cookies."; |
| 980 } | 1126 } |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1026 } | 1172 } |
| 1027 | 1173 |
| 1028 SQLitePersistentCookieStore::~SQLitePersistentCookieStore() { | 1174 SQLitePersistentCookieStore::~SQLitePersistentCookieStore() { |
| 1029 if (backend_.get()) { | 1175 if (backend_.get()) { |
| 1030 backend_->Close(); | 1176 backend_->Close(); |
| 1031 // Release our reference, it will probably still have a reference if the | 1177 // Release our reference, it will probably still have a reference if the |
| 1032 // background thread has not run Close() yet. | 1178 // background thread has not run Close() yet. |
| 1033 backend_ = NULL; | 1179 backend_ = NULL; |
| 1034 } | 1180 } |
| 1035 } | 1181 } |
| OLD | NEW |