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

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

Issue 11141012: Move ErrorDelegate to its own file and add static utility functions to ErrorDelegate (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fix win build Created 8 years, 2 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
« no previous file with comments | « chrome/browser/diagnostics/sqlite_diagnostics.cc ('k') | sql/connection.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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 }
OLDNEW
« no previous file with comments | « chrome/browser/diagnostics/sqlite_diagnostics.cc ('k') | sql/connection.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698