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 11 matching lines...) Expand all Loading... |
22 #include "base/synchronization/lock.h" | 22 #include "base/synchronization/lock.h" |
23 #include "base/threading/thread.h" | 23 #include "base/threading/thread.h" |
24 #include "base/threading/thread_restrictions.h" | 24 #include "base/threading/thread_restrictions.h" |
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/error_delegate_util.h" |
32 #include "sql/meta_table.h" | 33 #include "sql/meta_table.h" |
33 #include "sql/statement.h" | 34 #include "sql/statement.h" |
34 #include "sql/transaction.h" | 35 #include "sql/transaction.h" |
35 #include "third_party/sqlite/sqlite3.h" | 36 #include "third_party/sqlite/sqlite3.h" |
36 | 37 |
37 using base::Time; | 38 using base::Time; |
38 using content::BrowserThread; | 39 using content::BrowserThread; |
39 | 40 |
40 // This class is designed to be shared between any calling threads and the | 41 // This class is designed to be shared between any calling threads and the |
41 // database thread. It batches operations and commits them on a timer. | 42 // database thread. It batches operations and commits them on a timer. |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
100 // before the object is destructed. | 101 // before the object is destructed. |
101 void Close(); | 102 void Close(); |
102 | 103 |
103 void SetForceKeepSessionState(); | 104 void SetForceKeepSessionState(); |
104 | 105 |
105 private: | 106 private: |
106 friend class base::RefCountedThreadSafe<SQLitePersistentCookieStore::Backend>; | 107 friend class base::RefCountedThreadSafe<SQLitePersistentCookieStore::Backend>; |
107 | 108 |
108 class KillDatabaseErrorDelegate : public sql::ErrorDelegate { | 109 class KillDatabaseErrorDelegate : public sql::ErrorDelegate { |
109 public: | 110 public: |
110 KillDatabaseErrorDelegate(Backend* backend, | 111 KillDatabaseErrorDelegate(Backend* backend); |
111 sql::ErrorDelegate* wrapped_delegate); | |
112 | 112 |
113 virtual ~KillDatabaseErrorDelegate() {} | 113 virtual ~KillDatabaseErrorDelegate() {} |
114 | 114 |
115 // ErrorDelegate implementation. | 115 // ErrorDelegate implementation. |
116 virtual int OnError(int error, | 116 virtual int OnError(int error, |
117 sql::Connection* connection, | 117 sql::Connection* connection, |
118 sql::Statement* stmt) OVERRIDE; | 118 sql::Statement* stmt) OVERRIDE; |
119 | 119 |
120 private: | 120 private: |
121 | 121 |
| 122 class HistogramUniquifier { |
| 123 public: |
| 124 static const char* name() { return "Sqlite.Cookie.Error"; } |
| 125 }; |
| 126 |
122 // Do not increment the count on Backend, as that would create a circular | 127 // Do not increment the count on Backend, as that would create a circular |
123 // reference (Backend -> Connection -> ErrorDelegate -> Backend). | 128 // reference (Backend -> Connection -> ErrorDelegate -> Backend). |
124 Backend* backend_; | 129 Backend* backend_; |
125 scoped_ptr<sql::ErrorDelegate> wrapped_delegate_; | 130 |
| 131 // True if the delegate has previously attempted to kill the database. |
| 132 bool attempted_to_kill_database_; |
126 | 133 |
127 DISALLOW_COPY_AND_ASSIGN(KillDatabaseErrorDelegate); | 134 DISALLOW_COPY_AND_ASSIGN(KillDatabaseErrorDelegate); |
128 }; | 135 }; |
129 | 136 |
130 // You should call Close() before destructing this object. | 137 // You should call Close() before destructing this object. |
131 ~Backend() { | 138 ~Backend() { |
132 DCHECK(!db_.get()) << "Close should have already been called."; | 139 DCHECK(!db_.get()) << "Close should have already been called."; |
133 DCHECK(num_pending_ == 0 && pending_.empty()); | 140 DCHECK(num_pending_ == 0 && pending_.empty()); |
134 } | 141 } |
135 | 142 |
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
266 // The time when |num_priority_waiting_| incremented to 1. | 273 // The time when |num_priority_waiting_| incremented to 1. |
267 base::Time current_priority_wait_start_; | 274 base::Time current_priority_wait_start_; |
268 // The cumulative duration of time when |num_priority_waiting_| was greater | 275 // The cumulative duration of time when |num_priority_waiting_| was greater |
269 // than 1. | 276 // than 1. |
270 base::TimeDelta priority_wait_duration_; | 277 base::TimeDelta priority_wait_duration_; |
271 | 278 |
272 DISALLOW_COPY_AND_ASSIGN(Backend); | 279 DISALLOW_COPY_AND_ASSIGN(Backend); |
273 }; | 280 }; |
274 | 281 |
275 SQLitePersistentCookieStore::Backend::KillDatabaseErrorDelegate:: | 282 SQLitePersistentCookieStore::Backend::KillDatabaseErrorDelegate:: |
276 KillDatabaseErrorDelegate(Backend* backend, | 283 KillDatabaseErrorDelegate(Backend* backend) |
277 sql::ErrorDelegate* wrapped_delegate) | |
278 : backend_(backend), | 284 : backend_(backend), |
279 wrapped_delegate_(wrapped_delegate) { | 285 attempted_to_kill_database_(false) { |
280 } | 286 } |
281 | 287 |
282 int SQLitePersistentCookieStore::Backend::KillDatabaseErrorDelegate::OnError( | 288 int SQLitePersistentCookieStore::Backend::KillDatabaseErrorDelegate::OnError( |
283 int error, sql::Connection* connection, sql::Statement* stmt) { | 289 int error, sql::Connection* connection, sql::Statement* stmt) { |
284 if (wrapped_delegate_.get()) | 290 sql::LogAndRecordErrorInHistogram<HistogramUniquifier>(error, connection); |
285 error = wrapped_delegate_->OnError(error, connection, stmt); | |
286 | 291 |
287 bool delete_db = false; | 292 // Do not attempt to kill database more than once. If the first time failed, |
| 293 // it is unlikely that a second time will be successful. |
| 294 if (!attempted_to_kill_database_ && sql::IsErrorCatastrophic(error)) { |
| 295 attempted_to_kill_database_ = true; |
288 | 296 |
289 switch (error) { | |
290 case SQLITE_DONE: | |
291 case SQLITE_OK: | |
292 // Theoretically, the wrapped delegate might have resolved the error, and | |
293 // we would end up here. | |
294 break; | |
295 | |
296 case SQLITE_CORRUPT: | |
297 case SQLITE_NOTADB: | |
298 // Highly unlikely we would ever recover from these. | |
299 delete_db = true; | |
300 break; | |
301 | |
302 case SQLITE_CANTOPEN: | |
303 // TODO(erikwright): Figure out what this means. | |
304 break; | |
305 | |
306 case SQLITE_IOERR: | |
307 // This could be broken blocks, in which case deleting the DB would be a | |
308 // good idea. But it might also be transient. | |
309 // TODO(erikwright): Figure out if we can distinguish between the two, | |
310 // or determine through metrics analysis to what extent these failures are | |
311 // transient. | |
312 break; | |
313 | |
314 case SQLITE_BUSY: | |
315 // Presumably transient. | |
316 break; | |
317 | |
318 case SQLITE_TOOBIG: | |
319 case SQLITE_FULL: | |
320 case SQLITE_NOMEM: | |
321 // Not a problem with the database. | |
322 break; | |
323 | |
324 case SQLITE_READONLY: | |
325 // Presumably either transient or we don't have the privileges to | |
326 // move/delete the file anyway. | |
327 break; | |
328 | |
329 case SQLITE_CONSTRAINT: | |
330 case SQLITE_ERROR: | |
331 // These probably indicate a programming error or a migration failure that | |
332 // we prefer not to mask. | |
333 break; | |
334 | |
335 case SQLITE_LOCKED: | |
336 case SQLITE_INTERNAL: | |
337 case SQLITE_PERM: | |
338 case SQLITE_ABORT: | |
339 case SQLITE_INTERRUPT: | |
340 case SQLITE_NOTFOUND: | |
341 case SQLITE_PROTOCOL: | |
342 case SQLITE_EMPTY: | |
343 case SQLITE_SCHEMA: | |
344 case SQLITE_MISMATCH: | |
345 case SQLITE_MISUSE: | |
346 case SQLITE_NOLFS: | |
347 case SQLITE_AUTH: | |
348 case SQLITE_FORMAT: | |
349 case SQLITE_RANGE: | |
350 case SQLITE_ROW: | |
351 // None of these appear in error reports, so for now let's not try to | |
352 // guess at how to handle them. | |
353 break; | |
354 } | |
355 | |
356 if (delete_db && backend_) { | |
357 // Don't just do the close/delete here, as we are being called by |db| and | 297 // Don't just do the close/delete here, as we are being called by |db| and |
358 // that seems dangerous. | 298 // that seems dangerous. |
359 MessageLoop::current()->PostTask( | 299 MessageLoop::current()->PostTask( |
360 FROM_HERE, base::Bind(&Backend::KillDatabase, backend_)); | 300 FROM_HERE, base::Bind(&Backend::KillDatabase, backend_)); |
361 | |
362 // Avoid being called more than once. This will destroy the | |
363 // KillDatabaseErrorDelegate. Do not refer to any members from here forward. | |
364 connection->set_error_delegate(wrapped_delegate_.release()); | |
365 } | 301 } |
366 | 302 |
367 return error; | 303 return error; |
368 } | 304 } |
369 | 305 |
370 // Version number of the database. | 306 // Version number of the database. |
371 // | 307 // |
372 // Version 5 adds the columns has_expires and is_persistent, so that the | 308 // Version 5 adds the columns has_expires and is_persistent, so that the |
373 // database can store session cookies as well as persistent cookies. Databases | 309 // database can store session cookies as well as persistent cookies. Databases |
374 // of version 5 are incompatible with older versions of code. If a database of | 310 // of version 5 are incompatible with older versions of code. If a database of |
(...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
607 return false; | 543 return false; |
608 } | 544 } |
609 | 545 |
610 int64 db_size = 0; | 546 int64 db_size = 0; |
611 if (file_util::GetFileSize(path_, &db_size)) { | 547 if (file_util::GetFileSize(path_, &db_size)) { |
612 base::ThreadRestrictions::ScopedAllowIO allow_io; | 548 base::ThreadRestrictions::ScopedAllowIO allow_io; |
613 UMA_HISTOGRAM_COUNTS("Cookie.DBSizeInKB", db_size / 1024 ); | 549 UMA_HISTOGRAM_COUNTS("Cookie.DBSizeInKB", db_size / 1024 ); |
614 } | 550 } |
615 | 551 |
616 db_.reset(new sql::Connection); | 552 db_.reset(new sql::Connection); |
617 db_->set_error_delegate( | 553 db_->set_error_delegate(new KillDatabaseErrorDelegate(this)); |
618 new KillDatabaseErrorDelegate(this, GetErrorHandlerForCookieDb())); | |
619 | 554 |
620 if (!db_->Open(path_)) { | 555 if (!db_->Open(path_)) { |
621 NOTREACHED() << "Unable to open cookie DB."; | 556 NOTREACHED() << "Unable to open cookie DB."; |
622 db_.reset(); | 557 db_.reset(); |
623 return false; | 558 return false; |
624 } | 559 } |
625 | 560 |
626 if (!EnsureDatabaseVersion() || !InitTable(db_.get())) { | 561 if (!EnsureDatabaseVersion() || !InitTable(db_.get())) { |
627 NOTREACHED() << "Unable to open cookie DB."; | 562 NOTREACHED() << "Unable to open cookie DB."; |
628 db_.reset(); | 563 db_.reset(); |
(...skipping 531 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1160 } | 1095 } |
1161 | 1096 |
1162 SQLitePersistentCookieStore::~SQLitePersistentCookieStore() { | 1097 SQLitePersistentCookieStore::~SQLitePersistentCookieStore() { |
1163 if (backend_.get()) { | 1098 if (backend_.get()) { |
1164 backend_->Close(); | 1099 backend_->Close(); |
1165 // Release our reference, it will probably still have a reference if the | 1100 // Release our reference, it will probably still have a reference if the |
1166 // background thread has not run Close() yet. | 1101 // background thread has not run Close() yet. |
1167 backend_ = NULL; | 1102 backend_ = NULL; |
1168 } | 1103 } |
1169 } | 1104 } |
OLD | NEW |