summaryrefslogtreecommitdiff
path: root/chromium/net/extras/sqlite/sqlite_persistent_cookie_store.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/net/extras/sqlite/sqlite_persistent_cookie_store.cc')
-rw-r--r--chromium/net/extras/sqlite/sqlite_persistent_cookie_store.cc141
1 files changed, 125 insertions, 16 deletions
diff --git a/chromium/net/extras/sqlite/sqlite_persistent_cookie_store.cc b/chromium/net/extras/sqlite/sqlite_persistent_cookie_store.cc
index c47ccefb164..90afe861f9b 100644
--- a/chromium/net/extras/sqlite/sqlite_persistent_cookie_store.cc
+++ b/chromium/net/extras/sqlite/sqlite_persistent_cookie_store.cc
@@ -21,6 +21,7 @@
#include "base/sequenced_task_runner.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
+#include "base/synchronization/atomic_flag.h"
#include "base/synchronization/lock.h"
#include "base/time/time.h"
#include "net/cookies/canonical_cookie.h"
@@ -37,6 +38,51 @@ using base::Time;
namespace {
+// Used to populate a histogram for problems when loading cookies.
+//
+// Please do not reorder or remove entries. New entries must be added to the
+// end of the list, just before COOKIE_LOAD_PROBLEM_LAST_ENTRY.
+enum CookieLoadProblem {
+ COOKIE_LOAD_PROBLEM_DECRYPT_FAILED = 0,
+ COOKIE_LOAD_PROBLEM_DECRYPT_TIMEOUT = 1,
+ COOKIE_LOAD_PROBLEM_NON_CANONICAL = 2,
+ COOKIE_LOAD_PROBLEM_OPEN_DB = 3,
+ COOKIE_LOAD_PROBLEM_LAST_ENTRY
+};
+
+// Used to populate a histogram for problems when committing cookies.
+//
+// Please do not reorder or remove entries. New entries must be added to the
+// end of the list, just before COOKIE_COMMIT_PROBLEM_LAST_ENTRY.
+enum CookieCommitProblem {
+ COOKIE_COMMIT_PROBLEM_ENCRYPT_FAILED = 0,
+ COOKIE_COMMIT_PROBLEM_ADD = 1,
+ COOKIE_COMMIT_PROBLEM_UPDATE_ACCESS = 2,
+ COOKIE_COMMIT_PROBLEM_DELETE = 3,
+ COOKIE_COMMIT_PROBLEM_LAST_ENTRY
+};
+
+// Used to report a histogram on status of cookie commit to disk.
+//
+// Please do not reorder or remove entries. New entries must be added to the
+// end of the list, just before BACKING_STORE_RESULTS_LAST_ENTRY.
+enum BackingStoreResults {
+ BACKING_STORE_RESULTS_SUCCESS = 0,
+ BACKING_STORE_RESULTS_FAILURE = 1,
+ BACKING_STORE_RESULTS_MIXED = 2,
+ BACKING_STORE_RESULTS_LAST_ENTRY
+};
+
+void RecordCookieLoadProblem(CookieLoadProblem event) {
+ UMA_HISTOGRAM_ENUMERATION("Cookie.LoadProblem", event,
+ COOKIE_LOAD_PROBLEM_LAST_ENTRY);
+}
+
+void RecordCookieCommitProblem(CookieCommitProblem event) {
+ UMA_HISTOGRAM_ENUMERATION("Cookie.CommitProblem", event,
+ COOKIE_COMMIT_PROBLEM_LAST_ENTRY);
+}
+
// The persistent cookie store is loaded into memory on eTLD at a time. This
// variable controls the delay between loading eTLDs, so as to not overload the
// CPU or I/O with these low priority requests immediately after start up.
@@ -50,6 +96,38 @@ const int kLoadDelayMilliseconds = 0;
const int kLoadDelayMilliseconds = 0;
#endif
+// A little helper to help us log (on client thread) if the background runner
+// gets stuck.
+class TimeoutTracker : public base::RefCountedThreadSafe<TimeoutTracker> {
+ public:
+ // Runs on background runner.
+ static scoped_refptr<TimeoutTracker> Begin(
+ const scoped_refptr<base::SequencedTaskRunner>& client_task_runner) {
+ scoped_refptr<TimeoutTracker> tracker = new TimeoutTracker;
+ client_task_runner->PostDelayedTask(
+ FROM_HERE, base::BindOnce(&TimeoutTracker::TimerElapsed, tracker),
+ base::TimeDelta::FromSeconds(60));
+ return tracker;
+ }
+
+ // Runs on background runner.
+ void End() { done_.Set(); }
+
+ private:
+ friend class base::RefCountedThreadSafe<TimeoutTracker>;
+ TimeoutTracker() {}
+ ~TimeoutTracker() { DCHECK(done_.IsSet()); }
+
+ // Run on client runner.
+ void TimerElapsed() {
+ if (!done_.IsSet())
+ RecordCookieLoadProblem(COOKIE_LOAD_PROBLEM_DECRYPT_TIMEOUT);
+ }
+
+ base::AtomicFlag done_;
+ DISALLOW_COPY_AND_ASSIGN(TimeoutTracker);
+};
+
} // namespace
namespace net {
@@ -241,7 +319,7 @@ class SQLitePersistentCookieStore::Backend
std::unique_ptr<sql::Connection> db_;
sql::MetaTable meta_table_;
- typedef std::list<PendingOperation*> PendingOperationsList;
+ typedef std::list<std::unique_ptr<PendingOperation>> PendingOperationsList;
PendingOperationsList pending_;
PendingOperationsList::size_type num_pending_;
// Guard |cookies_|, |pending_|, |num_pending_|.
@@ -352,7 +430,7 @@ namespace {
// expire them in decreasing order of use when we've reached the maximum
// number of cookies.
const int kCurrentVersionNumber = 10;
-const int kCompatibleVersionNumber = 5;
+const int kCompatibleVersionNumber = 10;
// Possible values for the 'priority' column.
enum DBCookiePriority {
@@ -667,7 +745,8 @@ bool SQLitePersistentCookieStore::Backend::InitializeDatabase() {
base::Unretained(this)));
if (!db_->Open(path_)) {
- NOTREACHED() << "Unable to open cookie DB.";
+ DLOG(ERROR) << "Unable to open cookie DB.";
+ RecordCookieLoadProblem(COOKIE_LOAD_PROBLEM_OPEN_DB);
if (corruption_detected_)
db_->Raze();
meta_table_.Reset();
@@ -676,7 +755,8 @@ bool SQLitePersistentCookieStore::Backend::InitializeDatabase() {
}
if (!EnsureDatabaseVersion() || !InitTable(db_.get())) {
- NOTREACHED() << "Unable to open cookie DB.";
+ DLOG(ERROR) << "Unable to open cookie DB.";
+ RecordCookieLoadProblem(COOKIE_LOAD_PROBLEM_OPEN_DB);
if (corruption_detected_)
db_->Raze();
meta_table_.Reset();
@@ -817,13 +897,20 @@ bool SQLitePersistentCookieStore::Backend::LoadCookiesForDomains(
void SQLitePersistentCookieStore::Backend::MakeCookiesFromSQLStatement(
std::vector<std::unique_ptr<CanonicalCookie>>* cookies,
sql::Statement* statement) {
+ DCHECK(background_task_runner_->RunsTasksInCurrentSequence());
sql::Statement& smt = *statement;
while (smt.Step()) {
std::string value;
std::string encrypted_value = smt.ColumnString(4);
if (!encrypted_value.empty() && crypto_) {
- if (!crypto_->DecryptString(encrypted_value, &value))
+ scoped_refptr<TimeoutTracker> timeout_tracker =
+ TimeoutTracker::Begin(client_task_runner_);
+ bool decrypt_ok = crypto_->DecryptString(encrypted_value, &value);
+ timeout_tracker->End();
+ if (!decrypt_ok) {
+ RecordCookieLoadProblem(COOKIE_LOAD_PROBLEM_DECRYPT_FAILED);
continue;
+ }
} else {
value = smt.ColumnString(3);
}
@@ -843,8 +930,11 @@ void SQLitePersistentCookieStore::Backend::MakeCookiesFromSQLStatement(
static_cast<DBCookiePriority>(smt.ColumnInt(13))))); // priority
DLOG_IF(WARNING, cc->CreationDate() > Time::Now())
<< L"CreationDate too recent";
- if (cc->IsCanonical())
+ if (cc->IsCanonical()) {
cookies->push_back(std::move(cc));
+ } else {
+ RecordCookieLoadProblem(COOKIE_LOAD_PROBLEM_NON_CANONICAL);
+ }
++num_cookies_read_;
}
}
@@ -1141,7 +1231,7 @@ void SQLitePersistentCookieStore::Backend::BatchOperation(
PendingOperationsList::size_type num_pending;
{
base::AutoLock locked(lock_);
- pending_.push_back(po.release());
+ pending_.push_back(std::move(po));
num_pending = ++num_pending_;
}
@@ -1205,10 +1295,11 @@ void SQLitePersistentCookieStore::Backend::Commit() {
if (!transaction.Begin())
return;
+ bool trouble = false;
for (PendingOperationsList::iterator it = ops.begin(); it != ops.end();
++it) {
// Free the cookies as we commit them to the database.
- std::unique_ptr<PendingOperation> po(*it);
+ std::unique_ptr<PendingOperation> po(std::move(*it));
switch (po->op()) {
case PendingOperation::COOKIE_ADD:
add_smt.Reset(true);
@@ -1217,8 +1308,12 @@ void SQLitePersistentCookieStore::Backend::Commit() {
add_smt.BindString(2, po->cc().Name());
if (crypto_ && crypto_->ShouldEncrypt()) {
std::string encrypted_value;
- if (!crypto_->EncryptString(po->cc().Value(), &encrypted_value))
+ if (!crypto_->EncryptString(po->cc().Value(), &encrypted_value)) {
+ DLOG(WARNING) << "Could not encrypt a cookie, skipping add.";
+ RecordCookieCommitProblem(COOKIE_COMMIT_PROBLEM_ENCRYPT_FAILED);
+ trouble = true;
continue;
+ }
add_smt.BindCString(3, ""); // value
// BindBlob() immediately makes an internal copy of the data.
add_smt.BindBlob(4, encrypted_value.data(),
@@ -1238,8 +1333,11 @@ void SQLitePersistentCookieStore::Backend::Commit() {
add_smt.BindInt(12, po->cc().IsPersistent());
add_smt.BindInt(13,
CookiePriorityToDBCookiePriority(po->cc().Priority()));
- if (!add_smt.Run())
- NOTREACHED() << "Could not add a cookie to the DB.";
+ if (!add_smt.Run()) {
+ DLOG(WARNING) << "Could not add a cookie to the DB.";
+ RecordCookieCommitProblem(COOKIE_COMMIT_PROBLEM_ADD);
+ trouble = true;
+ }
break;
case PendingOperation::COOKIE_UPDATEACCESS:
@@ -1249,8 +1347,12 @@ void SQLitePersistentCookieStore::Backend::Commit() {
update_access_smt.BindString(1, po->cc().Name());
update_access_smt.BindString(2, po->cc().Domain());
update_access_smt.BindString(3, po->cc().Path());
- if (!update_access_smt.Run())
- NOTREACHED() << "Could not update cookie last access time in the DB.";
+ if (!update_access_smt.Run()) {
+ DLOG(WARNING)
+ << "Could not update cookie last access time in the DB.";
+ RecordCookieCommitProblem(COOKIE_COMMIT_PROBLEM_UPDATE_ACCESS);
+ trouble = true;
+ }
break;
case PendingOperation::COOKIE_DELETE:
@@ -1258,8 +1360,11 @@ void SQLitePersistentCookieStore::Backend::Commit() {
del_smt.BindString(0, po->cc().Name());
del_smt.BindString(1, po->cc().Domain());
del_smt.BindString(2, po->cc().Path());
- if (!del_smt.Run())
- NOTREACHED() << "Could not delete a cookie from the DB.";
+ if (!del_smt.Run()) {
+ DLOG(WARNING) << "Could not delete a cookie from the DB.";
+ RecordCookieCommitProblem(COOKIE_COMMIT_PROBLEM_DELETE);
+ trouble = true;
+ }
break;
default:
@@ -1269,7 +1374,11 @@ void SQLitePersistentCookieStore::Backend::Commit() {
}
bool succeeded = transaction.Commit();
UMA_HISTOGRAM_ENUMERATION("Cookie.BackingStoreUpdateResults",
- succeeded ? 0 : 1, 2);
+ succeeded
+ ? (trouble ? BACKING_STORE_RESULTS_MIXED
+ : BACKING_STORE_RESULTS_SUCCESS)
+ : BACKING_STORE_RESULTS_FAILURE,
+ BACKING_STORE_RESULTS_LAST_ENTRY);
}
void SQLitePersistentCookieStore::Backend::SetBeforeFlushCallback(