Index: content/browser/net/sqlite_persistent_cookie_store.cc |
diff --git a/content/browser/net/sqlite_persistent_cookie_store.cc b/content/browser/net/sqlite_persistent_cookie_store.cc |
index d11bac36434e8390ca4760a91ac15773bb71bc3f..2822e40416214fe037d8352ede66ef8de00a259e 100644 |
--- a/content/browser/net/sqlite_persistent_cookie_store.cc |
+++ b/content/browser/net/sqlite_persistent_cookie_store.cc |
@@ -21,6 +21,7 @@ |
#include "base/metrics/histogram.h" |
#include "base/sequenced_task_runner.h" |
#include "base/string_util.h" |
+#include "base/stringprintf.h" |
#include "base/synchronization/lock.h" |
#include "base/threading/sequenced_worker_pool.h" |
#include "base/time.h" |
@@ -314,8 +315,13 @@ int SQLitePersistentCookieStore::Backend::KillDatabaseErrorDelegate::OnError( |
return error; |
} |
+namespace { |
+ |
// Version number of the database. |
// |
+// Version 6 adds cookie priorities. This allows developers to influence the |
+// order in which cookies are evicted in order to meet domain cookie limits. |
+// |
// Version 5 adds the columns has_expires and is_persistent, so that the |
// database can store session cookies as well as persistent cookies. Databases |
// of version 5 are incompatible with older versions of code. If a database of |
@@ -329,10 +335,43 @@ int SQLitePersistentCookieStore::Backend::KillDatabaseErrorDelegate::OnError( |
// Version 3 updated the database to include the last access time, so we can |
// expire them in decreasing order of use when we've reached the maximum |
// number of cookies. |
-static const int kCurrentVersionNumber = 5; |
-static const int kCompatibleVersionNumber = 5; |
+const int kCurrentVersionNumber = 6; |
+const int kCompatibleVersionNumber = 5; |
+ |
+// Possible values for the 'priority' column. |
+enum DBCookiePriority { |
+ kCookiePriorityLow = 0, |
+ kCookiePriorityMedium = 1, |
+ kCookiePriorityHigh = 2, |
+}; |
-namespace { |
+DBCookiePriority CookiePriorityToDBCookiePriority(net::CookiePriority value) { |
+ switch (value) { |
+ case net::COOKIE_PRIORITY_LOW: |
+ return kCookiePriorityLow; |
+ case net::COOKIE_PRIORITY_MEDIUM: |
+ return kCookiePriorityMedium; |
+ case net::COOKIE_PRIORITY_HIGH: |
+ return kCookiePriorityHigh; |
+ } |
+ |
+ NOTREACHED(); |
+ return kCookiePriorityMedium; |
+} |
+ |
+net::CookiePriority DBCookiePriorityToCookiePriority(DBCookiePriority value) { |
+ switch (value) { |
+ case kCookiePriorityLow: |
+ return net::COOKIE_PRIORITY_LOW; |
+ case kCookiePriorityMedium: |
+ return net::COOKIE_PRIORITY_MEDIUM; |
+ case kCookiePriorityHigh: |
+ return net::COOKIE_PRIORITY_HIGH; |
+ } |
+ |
+ NOTREACHED(); |
+ return net::COOKIE_PRIORITY_DEFAULT; |
+} |
// Increments a specified TimeDelta by the duration between this object's |
// constructor and destructor. Not thread safe. Multiple instances may be |
@@ -360,21 +399,23 @@ class IncrementTimeDelta { |
// Initializes the cookies table, returning true on success. |
bool InitTable(sql::Connection* db) { |
if (!db->DoesTableExist("cookies")) { |
- if (!db->Execute("CREATE TABLE cookies (" |
- "creation_utc INTEGER NOT NULL UNIQUE PRIMARY KEY," |
- "host_key TEXT NOT NULL," |
- "name TEXT NOT NULL," |
- "value TEXT NOT NULL," |
- "path TEXT NOT NULL," |
- "expires_utc INTEGER NOT NULL," |
- "secure INTEGER NOT NULL," |
- "httponly INTEGER NOT NULL," |
- "last_access_utc INTEGER NOT NULL, " |
- "has_expires INTEGER NOT NULL DEFAULT 1, " |
- "persistent INTEGER NOT NULL DEFAULT 1)")) { |
- // TODO(rogerm): Add priority. |
+ std::string stmt(base::StringPrintf( |
+ "CREATE TABLE cookies (" |
+ "creation_utc INTEGER NOT NULL UNIQUE PRIMARY KEY," |
+ "host_key TEXT NOT NULL," |
+ "name TEXT NOT NULL," |
+ "value TEXT NOT NULL," |
+ "path TEXT NOT NULL," |
+ "expires_utc INTEGER NOT NULL," |
+ "secure INTEGER NOT NULL," |
+ "httponly INTEGER NOT NULL," |
+ "last_access_utc INTEGER NOT NULL, " |
+ "has_expires INTEGER NOT NULL DEFAULT 1, " |
+ "persistent INTEGER NOT NULL DEFAULT 1," |
+ "priority INTEGER NOT NULL DEFAULT %d)", |
+ CookiePriorityToDBCookiePriority(net::COOKIE_PRIORITY_DEFAULT))); |
+ if (!db->Execute(stmt.c_str())) |
return false; |
- } |
} |
// Older code created an index on creation_utc, which is already |
@@ -660,18 +701,16 @@ bool SQLitePersistentCookieStore::Backend::LoadCookiesForDomains( |
sql::Statement smt; |
if (restore_old_session_cookies_) { |
smt.Assign(db_->GetCachedStatement( |
- SQL_FROM_HERE, |
- "SELECT creation_utc, host_key, name, value, path, expires_utc, " |
- "secure, httponly, last_access_utc, has_expires, persistent " |
- "FROM cookies WHERE host_key = ?")); |
- // TODO(rogerm): Add priority. |
+ SQL_FROM_HERE, |
+ "SELECT creation_utc, host_key, name, value, path, expires_utc, " |
+ "secure, httponly, last_access_utc, has_expires, persistent, priority " |
+ "FROM cookies WHERE host_key = ?")); |
} else { |
smt.Assign(db_->GetCachedStatement( |
- SQL_FROM_HERE, |
- "SELECT creation_utc, host_key, name, value, path, expires_utc, " |
- "secure, httponly, last_access_utc, has_expires, persistent " |
- "FROM cookies WHERE host_key = ? AND persistent = 1")); |
- // TODO(rogerm): Add priority. |
+ SQL_FROM_HERE, |
+ "SELECT creation_utc, host_key, name, value, path, expires_utc, " |
+ "secure, httponly, last_access_utc, has_expires, persistent, priority " |
+ "FROM cookies WHERE host_key = ? AND persistent = 1")); |
} |
if (!smt.is_valid()) { |
smt.Clear(); // Disconnect smt_ref from db_. |
@@ -685,22 +724,20 @@ bool SQLitePersistentCookieStore::Backend::LoadCookiesForDomains( |
for (; it != domains.end(); ++it) { |
smt.BindString(0, *it); |
while (smt.Step()) { |
- scoped_ptr<net::CanonicalCookie> cc( |
- new net::CanonicalCookie( |
- // The "source" URL is not used with persisted cookies. |
- GURL(), // Source |
- smt.ColumnString(2), // name |
- smt.ColumnString(3), // value |
- smt.ColumnString(1), // domain |
- smt.ColumnString(4), // path |
- Time::FromInternalValue(smt.ColumnInt64(0)), // creation_utc |
- Time::FromInternalValue(smt.ColumnInt64(5)), // expires_utc |
- Time::FromInternalValue(smt.ColumnInt64(8)), // last_access_utc |
- smt.ColumnInt(6) != 0, // secure |
- smt.ColumnInt(7) != 0, // httponly |
- net::COOKIE_PRIORITY_DEFAULT)); // priority |
- // TODO(rogerm): Change net::COOKIE_PRIORITY_DEFAULT above to |
- // net::StringToCookiePriority(smt.ColumnString(9))? |
+ scoped_ptr<net::CanonicalCookie> cc(new net::CanonicalCookie( |
+ // The "source" URL is not used with persisted cookies. |
+ GURL(), // Source |
+ smt.ColumnString(2), // name |
+ smt.ColumnString(3), // value |
+ smt.ColumnString(1), // domain |
+ smt.ColumnString(4), // path |
+ Time::FromInternalValue(smt.ColumnInt64(0)), // creation_utc |
+ Time::FromInternalValue(smt.ColumnInt64(5)), // expires_utc |
+ Time::FromInternalValue(smt.ColumnInt64(8)), // last_access_utc |
+ smt.ColumnInt(6) != 0, // secure |
+ smt.ColumnInt(7) != 0, // httponly |
+ DBCookiePriorityToCookiePriority( |
+ static_cast<DBCookiePriority>(smt.ColumnInt(11))))); // priority |
DLOG_IF(WARNING, |
cc->CreationDate() > Time::Now()) << L"CreationDate too recent"; |
cookies_per_origin_[CookieOrigin(cc->Domain(), cc->IsSecure())]++; |
@@ -801,6 +838,28 @@ bool SQLitePersistentCookieStore::Backend::EnsureDatabaseVersion() { |
base::TimeTicks::Now() - start_time); |
} |
+ if (cur_version == 5) { |
+ const base::TimeTicks start_time = base::TimeTicks::Now(); |
+ sql::Transaction transaction(db_.get()); |
+ if (!transaction.Begin()) |
+ return false; |
+ // Alter the table to add the priority column with a default value. |
+ std::string stmt(base::StringPrintf( |
+ "ALTER TABLE cookies ADD COLUMN priority INTEGER DEFAULT %d", |
+ CookiePriorityToDBCookiePriority(net::COOKIE_PRIORITY_DEFAULT))); |
+ if (!db_->Execute(stmt.c_str())) { |
+ LOG(WARNING) << "Unable to update cookie database to version 6."; |
+ return false; |
+ } |
+ ++cur_version; |
+ meta_table_.SetVersionNumber(cur_version); |
+ meta_table_.SetCompatibleVersionNumber( |
+ std::min(cur_version, kCompatibleVersionNumber)); |
+ transaction.Commit(); |
+ UMA_HISTOGRAM_TIMES("Cookie.TimeDatabaseMigrationToV6", |
+ base::TimeTicks::Now() - start_time); |
+ } |
+ |
// Put future migration cases here. |
if (cur_version < kCurrentVersionNumber) { |
@@ -884,12 +943,11 @@ void SQLitePersistentCookieStore::Backend::Commit() { |
if (!db_.get() || ops.empty()) |
return; |
- // TODO(rogerm): Add priority. |
sql::Statement add_smt(db_->GetCachedStatement(SQL_FROM_HERE, |
"INSERT INTO cookies (creation_utc, host_key, name, value, path, " |
"expires_utc, secure, httponly, last_access_utc, has_expires, " |
- "persistent) " |
- "VALUES (?,?,?,?,?,?,?,?,?,?,?)")); |
+ "persistent, priority) " |
+ "VALUES (?,?,?,?,?,?,?,?,?,?,?,?)")); |
if (!add_smt.is_valid()) |
return; |
@@ -927,7 +985,8 @@ void SQLitePersistentCookieStore::Backend::Commit() { |
add_smt.BindInt64(8, po->cc().LastAccessDate().ToInternalValue()); |
add_smt.BindInt(9, po->cc().IsPersistent()); |
add_smt.BindInt(10, po->cc().IsPersistent()); |
- // TODO(rogerm): Add priority. |
+ add_smt.BindInt( |
+ 11, CookiePriorityToDBCookiePriority(po->cc().Priority())); |
if (!add_smt.Run()) |
NOTREACHED() << "Could not add a cookie to the DB."; |
break; |