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

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

Issue 14208017: Add cookie priority to the cookie database. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Add unittests and rebase onto Sam's change. Created 7 years, 8 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
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 "content/browser/net/sqlite_persistent_cookie_store.h" 5 #include "content/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 296 matching lines...) Expand 10 before | Expand all | Expand 10 after
307 // it is unlikely that a second time will be successful. 307 // it is unlikely that a second time will be successful.
308 if (!attempted_to_kill_database_ && sql::IsErrorCatastrophic(error)) { 308 if (!attempted_to_kill_database_ && sql::IsErrorCatastrophic(error)) {
309 attempted_to_kill_database_ = true; 309 attempted_to_kill_database_ = true;
310 310
311 backend_->ScheduleKillDatabase(); 311 backend_->ScheduleKillDatabase();
312 } 312 }
313 313
314 return error; 314 return error;
315 } 315 }
316 316
317 namespace {
318
317 // Version number of the database. 319 // Version number of the database.
318 // 320 //
321 // Version 6 adds cookie priorities. This allows developers to influence the
322 // order in which cookies are evicted in order to meet domain cookie limits.
323 //
319 // Version 5 adds the columns has_expires and is_persistent, so that the 324 // Version 5 adds the columns has_expires and is_persistent, so that the
320 // database can store session cookies as well as persistent cookies. Databases 325 // database can store session cookies as well as persistent cookies. Databases
321 // of version 5 are incompatible with older versions of code. If a database of 326 // of version 5 are incompatible with older versions of code. If a database of
322 // version 5 is read by older code, session cookies will be treated as normal 327 // version 5 is read by older code, session cookies will be treated as normal
323 // cookies. Currently, these fields are written, but not read anymore. 328 // cookies. Currently, these fields are written, but not read anymore.
324 // 329 //
325 // In version 4, we migrated the time epoch. If you open the DB with an older 330 // In version 4, we migrated the time epoch. If you open the DB with an older
326 // version on Mac or Linux, the times will look wonky, but the file will likely 331 // version on Mac or Linux, the times will look wonky, but the file will likely
327 // be usable. On Windows version 3 and 4 are the same. 332 // be usable. On Windows version 3 and 4 are the same.
328 // 333 //
329 // Version 3 updated the database to include the last access time, so we can 334 // Version 3 updated the database to include the last access time, so we can
330 // expire them in decreasing order of use when we've reached the maximum 335 // expire them in decreasing order of use when we've reached the maximum
331 // number of cookies. 336 // number of cookies.
332 static const int kCurrentVersionNumber = 5; 337 const int kCurrentVersionNumber = 6;
333 static const int kCompatibleVersionNumber = 5; 338 const int kCompatibleVersionNumber = 5;
334 339
335 namespace { 340 // This anonymous enum defines the valid integer CookiePriority values.
erikwright (departed) 2013/04/18 19:34:05 Just say: // Possible values for the 'priority' c
Roger McFarlane (Chromium) 2013/04/19 20:53:03 Done.
341 enum {
342 kCookiePriorityLow = 0,
343 kCookiePriorityMedium = 1,
344 kCookiePriorityHigh = 2,
345
346 kCookiePriorityDefault = kCookiePriorityMedium
erikwright (departed) 2013/04/18 19:34:05 Not used.
Roger McFarlane (Chromium) 2013/04/19 20:53:03 Removed.
347 };
erikwright (departed) 2013/04/18 19:34:05 Maybe name this enum "DBCookiePriority" and use th
Roger McFarlane (Chromium) 2013/04/19 20:53:03 Done. While I don't feel all that strongly about
348
349 // Maps from the cookie priority values used elsewhere in the code to those
350 // actually persisted in the cookie database. This decouples changes made in
351 // the two value sets.
352 int CookiePriorityToInt(net::CookiePriority priority) {
erikwright (departed) 2013/04/18 19:34:05 CookiePriorityToDBCookiePriority and the reverse b
Roger McFarlane (Chromium) 2013/04/19 20:53:03 Done.
353 switch (priority) {
354 case net::PRIORITY_LOW:
355 return kCookiePriorityLow;
356 case net::PRIORITY_MEDIUM:
357 return kCookiePriorityMedium;
358 case net::PRIORITY_HIGH:
359 return kCookiePriorityHigh;
360 }
361
362 NOTREACHED();
363 return kCookiePriorityMedium;
364 }
365
366 // Maps from the cookie priority values persisted in the cookie database to
367 // those use elsewhere in the code. This decouples changes made in the two
368 // value sets.
369 net::CookiePriority IntToCookiePriority(int value) {
370 switch (value) {
371 case kCookiePriorityLow:
372 return net::PRIORITY_LOW;
373 case kCookiePriorityMedium:
374 return net::PRIORITY_MEDIUM;
375 case kCookiePriorityHigh:
376 return net::PRIORITY_HIGH;
377 }
378
379 NOTREACHED();
380 return net::PRIORITY_MEDIUM;
381 }
336 382
337 // Increments a specified TimeDelta by the duration between this object's 383 // Increments a specified TimeDelta by the duration between this object's
338 // constructor and destructor. Not thread safe. Multiple instances may be 384 // constructor and destructor. Not thread safe. Multiple instances may be
339 // created with the same delta instance as long as their lifetimes are nested. 385 // created with the same delta instance as long as their lifetimes are nested.
340 // The shortest lived instances have no impact. 386 // The shortest lived instances have no impact.
341 class IncrementTimeDelta { 387 class IncrementTimeDelta {
342 public: 388 public:
343 explicit IncrementTimeDelta(base::TimeDelta* delta) : 389 explicit IncrementTimeDelta(base::TimeDelta* delta) :
344 delta_(delta), 390 delta_(delta),
345 original_value_(*delta), 391 original_value_(*delta),
346 start_(base::Time::Now()) {} 392 start_(base::Time::Now()) {}
347 393
348 ~IncrementTimeDelta() { 394 ~IncrementTimeDelta() {
349 *delta_ = original_value_ + base::Time::Now() - start_; 395 *delta_ = original_value_ + base::Time::Now() - start_;
350 } 396 }
351 397
352 private: 398 private:
353 base::TimeDelta* delta_; 399 base::TimeDelta* delta_;
354 base::TimeDelta original_value_; 400 base::TimeDelta original_value_;
355 base::Time start_; 401 base::Time start_;
356 402
357 DISALLOW_COPY_AND_ASSIGN(IncrementTimeDelta); 403 DISALLOW_COPY_AND_ASSIGN(IncrementTimeDelta);
358 }; 404 };
359 405
360 // Initializes the cookies table, returning true on success. 406 // Initializes the cookies table, returning true on success.
361 bool InitTable(sql::Connection* db) { 407 bool InitTable(sql::Connection* db) {
362 if (!db->DoesTableExist("cookies")) { 408 if (!db->DoesTableExist("cookies")) {
363 if (!db->Execute("CREATE TABLE cookies (" 409 if (!db->Execute(
364 "creation_utc INTEGER NOT NULL UNIQUE PRIMARY KEY," 410 "CREATE TABLE cookies ("
365 "host_key TEXT NOT NULL," 411 "creation_utc INTEGER NOT NULL UNIQUE PRIMARY KEY,"
366 "name TEXT NOT NULL," 412 "host_key TEXT NOT NULL,"
367 "value TEXT NOT NULL," 413 "name TEXT NOT NULL,"
368 "path TEXT NOT NULL," 414 "value TEXT NOT NULL,"
369 "expires_utc INTEGER NOT NULL," 415 "path TEXT NOT NULL,"
370 "secure INTEGER NOT NULL," 416 "expires_utc INTEGER NOT NULL,"
371 "httponly INTEGER NOT NULL," 417 "secure INTEGER NOT NULL,"
372 "last_access_utc INTEGER NOT NULL, " 418 "httponly INTEGER NOT NULL,"
373 "has_expires INTEGER NOT NULL DEFAULT 1, " 419 "last_access_utc INTEGER NOT NULL, "
374 "persistent INTEGER NOT NULL DEFAULT 1)")) 420 "has_expires INTEGER NOT NULL DEFAULT 1, "
375 // TODO(rogerm): Add priority. 421 "persistent INTEGER NOT NULL DEFAULT 1,"
422 "priority INTEGER NOT NULL DEFAULT 1)")) { // Medium priority.
erikwright (departed) 2013/04/18 19:34:05 Would this compile if you replace -- 1)" -- wi
Roger McFarlane (Chromium) 2013/04/19 20:53:03 Done. Switched to using base::StringPrintf to get
376 return false; 423 return false;
424 }
377 } 425 }
378 426
379 // Older code created an index on creation_utc, which is already 427 // Older code created an index on creation_utc, which is already
380 // primary key for the table. 428 // primary key for the table.
381 if (!db->Execute("DROP INDEX IF EXISTS cookie_times")) 429 if (!db->Execute("DROP INDEX IF EXISTS cookie_times"))
382 return false; 430 return false;
383 431
384 if (!db->Execute("CREATE INDEX IF NOT EXISTS domain ON cookies(host_key)")) 432 if (!db->Execute("CREATE INDEX IF NOT EXISTS domain ON cookies(host_key)"))
385 return false; 433 return false;
386 434
(...skipping 265 matching lines...) Expand 10 before | Expand all | Expand 10 after
652 } 700 }
653 } 701 }
654 702
655 bool SQLitePersistentCookieStore::Backend::LoadCookiesForDomains( 703 bool SQLitePersistentCookieStore::Backend::LoadCookiesForDomains(
656 const std::set<std::string>& domains) { 704 const std::set<std::string>& domains) {
657 DCHECK(background_task_runner_->RunsTasksOnCurrentThread()); 705 DCHECK(background_task_runner_->RunsTasksOnCurrentThread());
658 706
659 sql::Statement smt; 707 sql::Statement smt;
660 if (restore_old_session_cookies_) { 708 if (restore_old_session_cookies_) {
661 smt.Assign(db_->GetCachedStatement( 709 smt.Assign(db_->GetCachedStatement(
662 SQL_FROM_HERE, 710 SQL_FROM_HERE,
663 "SELECT creation_utc, host_key, name, value, path, expires_utc, " 711 "SELECT creation_utc, host_key, name, value, path, expires_utc, "
664 "secure, httponly, last_access_utc, has_expires, persistent " 712 "secure, httponly, last_access_utc, has_expires, persistent, priority "
665 "FROM cookies WHERE host_key = ?")); 713 "FROM cookies WHERE host_key = ?"));
666 // TODO(rogerm): Add priority.
667 } else { 714 } else {
668 smt.Assign(db_->GetCachedStatement( 715 smt.Assign(db_->GetCachedStatement(
669 SQL_FROM_HERE, 716 SQL_FROM_HERE,
670 "SELECT creation_utc, host_key, name, value, path, expires_utc, " 717 "SELECT creation_utc, host_key, name, value, path, expires_utc, "
671 "secure, httponly, last_access_utc, has_expires, persistent " 718 "secure, httponly, last_access_utc, has_expires, persistent, priority "
672 "FROM cookies WHERE host_key = ? AND persistent = 1")); 719 "FROM cookies WHERE host_key = ? AND persistent = 1"));
673 // TODO(rogerm): Add priority.
674 } 720 }
675 if (!smt.is_valid()) { 721 if (!smt.is_valid()) {
676 smt.Clear(); // Disconnect smt_ref from db_. 722 smt.Clear(); // Disconnect smt_ref from db_.
677 meta_table_.Reset(); 723 meta_table_.Reset();
678 db_.reset(); 724 db_.reset();
679 return false; 725 return false;
680 } 726 }
681 727
682 std::vector<net::CanonicalCookie*> cookies; 728 std::vector<net::CanonicalCookie*> cookies;
683 std::set<std::string>::const_iterator it = domains.begin(); 729 std::set<std::string>::const_iterator it = domains.begin();
684 for (; it != domains.end(); ++it) { 730 for (; it != domains.end(); ++it) {
685 smt.BindString(0, *it); 731 smt.BindString(0, *it);
686 while (smt.Step()) { 732 while (smt.Step()) {
687 scoped_ptr<net::CanonicalCookie> cc( 733 scoped_ptr<net::CanonicalCookie> cc(
688 new net::CanonicalCookie( 734 new net::CanonicalCookie(
689 // The "source" URL is not used with persisted cookies. 735 // The "source" URL is not used with persisted cookies.
690 GURL(), // Source 736 GURL(), // Source
691 smt.ColumnString(2), // name 737 smt.ColumnString(2), // name
692 smt.ColumnString(3), // value 738 smt.ColumnString(3), // value
693 smt.ColumnString(1), // domain 739 smt.ColumnString(1), // domain
694 smt.ColumnString(4), // path 740 smt.ColumnString(4), // path
695 Time::FromInternalValue(smt.ColumnInt64(0)), // creation_utc 741 Time::FromInternalValue(smt.ColumnInt64(0)), // creation_utc
696 Time::FromInternalValue(smt.ColumnInt64(5)), // expires_utc 742 Time::FromInternalValue(smt.ColumnInt64(5)), // expires_utc
697 Time::FromInternalValue(smt.ColumnInt64(8)), // last_access_utc 743 Time::FromInternalValue(smt.ColumnInt64(8)), // last_access_utc
698 smt.ColumnInt(6) != 0, // secure 744 smt.ColumnInt(6) != 0, // secure
699 smt.ColumnInt(7) != 0, // httponly 745 smt.ColumnInt(7) != 0, // httponly
700 net::PRIORITY_DEFAULT)); // priority 746 IntToCookiePriority(smt.ColumnInt(11)))); // priority
701 // TODO(rogerm): Change net::PRIORITY_DEFAULT above to
702 // net::StringToCookiePriority(smt.ColumnString(9))?
703 DLOG_IF(WARNING, 747 DLOG_IF(WARNING,
704 cc->CreationDate() > Time::Now()) << L"CreationDate too recent"; 748 cc->CreationDate() > Time::Now()) << L"CreationDate too recent";
705 cookies_per_origin_[CookieOrigin(cc->Domain(), cc->IsSecure())]++; 749 cookies_per_origin_[CookieOrigin(cc->Domain(), cc->IsSecure())]++;
706 cookies.push_back(cc.release()); 750 cookies.push_back(cc.release());
707 ++num_cookies_read_; 751 ++num_cookies_read_;
708 } 752 }
709 smt.Reset(true); 753 smt.Reset(true);
710 } 754 }
711 { 755 {
712 base::AutoLock locked(lock_); 756 base::AutoLock locked(lock_);
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
793 } 837 }
794 ++cur_version; 838 ++cur_version;
795 meta_table_.SetVersionNumber(cur_version); 839 meta_table_.SetVersionNumber(cur_version);
796 meta_table_.SetCompatibleVersionNumber( 840 meta_table_.SetCompatibleVersionNumber(
797 std::min(cur_version, kCompatibleVersionNumber)); 841 std::min(cur_version, kCompatibleVersionNumber));
798 transaction.Commit(); 842 transaction.Commit();
799 UMA_HISTOGRAM_TIMES("Cookie.TimeDatabaseMigrationToV5", 843 UMA_HISTOGRAM_TIMES("Cookie.TimeDatabaseMigrationToV5",
800 base::TimeTicks::Now() - start_time); 844 base::TimeTicks::Now() - start_time);
801 } 845 }
802 846
847 if (cur_version == 5) {
848 const base::TimeTicks start_time = base::TimeTicks::Now();
849 sql::Transaction transaction(db_.get());
850 if (!transaction.Begin())
851 return false;
852 // Alter the table to add the priority column with a default value of
853 // 1 (Medium) for the value.
854 if (!db_->Execute("ALTER TABLE cookies "
855 "ADD COLUMN priority INTEGER DEFAULT 1")) {
856 LOG(WARNING) << "Unable to update cookie database to version 6.";
857 return false;
858 }
859 ++cur_version;
860 meta_table_.SetVersionNumber(cur_version);
861 meta_table_.SetCompatibleVersionNumber(
862 std::min(cur_version, kCompatibleVersionNumber));
863 transaction.Commit();
864 UMA_HISTOGRAM_TIMES("Cookie.TimeDatabaseMigrationToV6",
865 base::TimeTicks::Now() - start_time);
866 }
867
803 // Put future migration cases here. 868 // Put future migration cases here.
804 869
805 if (cur_version < kCurrentVersionNumber) { 870 if (cur_version < kCurrentVersionNumber) {
806 UMA_HISTOGRAM_COUNTS_100("Cookie.CorruptMetaTable", 1); 871 UMA_HISTOGRAM_COUNTS_100("Cookie.CorruptMetaTable", 1);
807 872
808 meta_table_.Reset(); 873 meta_table_.Reset();
809 db_.reset(new sql::Connection); 874 db_.reset(new sql::Connection);
810 if (!file_util::Delete(path_, false) || 875 if (!file_util::Delete(path_, false) ||
811 !db_->Open(path_) || 876 !db_->Open(path_) ||
812 !meta_table_.Init( 877 !meta_table_.Init(
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
876 { 941 {
877 base::AutoLock locked(lock_); 942 base::AutoLock locked(lock_);
878 pending_.swap(ops); 943 pending_.swap(ops);
879 num_pending_ = 0; 944 num_pending_ = 0;
880 } 945 }
881 946
882 // Maybe an old timer fired or we are already Close()'ed. 947 // Maybe an old timer fired or we are already Close()'ed.
883 if (!db_.get() || ops.empty()) 948 if (!db_.get() || ops.empty())
884 return; 949 return;
885 950
886 // TODO(rogerm): Add priority.
887 sql::Statement add_smt(db_->GetCachedStatement(SQL_FROM_HERE, 951 sql::Statement add_smt(db_->GetCachedStatement(SQL_FROM_HERE,
888 "INSERT INTO cookies (creation_utc, host_key, name, value, path, " 952 "INSERT INTO cookies (creation_utc, host_key, name, value, path, "
889 "expires_utc, secure, httponly, last_access_utc, has_expires, " 953 "expires_utc, secure, httponly, last_access_utc, has_expires, "
890 "persistent) " 954 "persistent, priority) "
891 "VALUES (?,?,?,?,?,?,?,?,?,?,?)")); 955 "VALUES (?,?,?,?,?,?,?,?,?,?,?,?)"));
892 if (!add_smt.is_valid()) 956 if (!add_smt.is_valid())
893 return; 957 return;
894 958
895 sql::Statement update_access_smt(db_->GetCachedStatement(SQL_FROM_HERE, 959 sql::Statement update_access_smt(db_->GetCachedStatement(SQL_FROM_HERE,
896 "UPDATE cookies SET last_access_utc=? WHERE creation_utc=?")); 960 "UPDATE cookies SET last_access_utc=? WHERE creation_utc=?"));
897 if (!update_access_smt.is_valid()) 961 if (!update_access_smt.is_valid())
898 return; 962 return;
899 963
900 sql::Statement del_smt(db_->GetCachedStatement(SQL_FROM_HERE, 964 sql::Statement del_smt(db_->GetCachedStatement(SQL_FROM_HERE,
901 "DELETE FROM cookies WHERE creation_utc=?")); 965 "DELETE FROM cookies WHERE creation_utc=?"));
(...skipping 17 matching lines...) Expand all
919 add_smt.BindString(1, po->cc().Domain()); 983 add_smt.BindString(1, po->cc().Domain());
920 add_smt.BindString(2, po->cc().Name()); 984 add_smt.BindString(2, po->cc().Name());
921 add_smt.BindString(3, po->cc().Value()); 985 add_smt.BindString(3, po->cc().Value());
922 add_smt.BindString(4, po->cc().Path()); 986 add_smt.BindString(4, po->cc().Path());
923 add_smt.BindInt64(5, po->cc().ExpiryDate().ToInternalValue()); 987 add_smt.BindInt64(5, po->cc().ExpiryDate().ToInternalValue());
924 add_smt.BindInt(6, po->cc().IsSecure()); 988 add_smt.BindInt(6, po->cc().IsSecure());
925 add_smt.BindInt(7, po->cc().IsHttpOnly()); 989 add_smt.BindInt(7, po->cc().IsHttpOnly());
926 add_smt.BindInt64(8, po->cc().LastAccessDate().ToInternalValue()); 990 add_smt.BindInt64(8, po->cc().LastAccessDate().ToInternalValue());
927 add_smt.BindInt(9, po->cc().IsPersistent()); 991 add_smt.BindInt(9, po->cc().IsPersistent());
928 add_smt.BindInt(10, po->cc().IsPersistent()); 992 add_smt.BindInt(10, po->cc().IsPersistent());
929 // TODO(rogerm): Add priority. 993 add_smt.BindInt(11, CookiePriorityToInt(po->cc().Priority()));
930 if (!add_smt.Run()) 994 if (!add_smt.Run())
931 NOTREACHED() << "Could not add a cookie to the DB."; 995 NOTREACHED() << "Could not add a cookie to the DB.";
932 break; 996 break;
933 997
934 case PendingOperation::COOKIE_UPDATEACCESS: 998 case PendingOperation::COOKIE_UPDATEACCESS:
935 update_access_smt.Reset(true); 999 update_access_smt.Reset(true);
936 update_access_smt.BindInt64(0, 1000 update_access_smt.BindInt64(0,
937 po->cc().LastAccessDate().ToInternalValue()); 1001 po->cc().LastAccessDate().ToInternalValue());
938 update_access_smt.BindInt64(1, 1002 update_access_smt.BindInt64(1,
939 po->cc().CreationDate().ToInternalValue()); 1003 po->cc().CreationDate().ToInternalValue());
(...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after
1154 path, 1218 path,
1155 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO), 1219 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO),
1156 BrowserThread::GetBlockingPool()->GetSequencedTaskRunner( 1220 BrowserThread::GetBlockingPool()->GetSequencedTaskRunner(
1157 BrowserThread::GetBlockingPool()->GetSequenceToken()), 1221 BrowserThread::GetBlockingPool()->GetSequenceToken()),
1158 restore_old_session_cookies, 1222 restore_old_session_cookies,
1159 storage_policy); 1223 storage_policy);
1160 return new net::CookieMonster(persistent_store, cookie_monster_delegate); 1224 return new net::CookieMonster(persistent_store, cookie_monster_delegate);
1161 } 1225 }
1162 1226
1163 } // namespace content 1227 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698