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 "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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |