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 293 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
304 // Not owned. | 304 // Not owned. |
305 CookieCryptoDelegate* crypto_; | 305 CookieCryptoDelegate* crypto_; |
306 | 306 |
307 DISALLOW_COPY_AND_ASSIGN(Backend); | 307 DISALLOW_COPY_AND_ASSIGN(Backend); |
308 }; | 308 }; |
309 | 309 |
310 namespace { | 310 namespace { |
311 | 311 |
312 // Version number of the database. | 312 // Version number of the database. |
313 // | 313 // |
| 314 // Version 8 adds "first-party only" cookies. |
| 315 // |
314 // Version 7 adds encrypted values. Old values will continue to be used but | 316 // Version 7 adds encrypted values. Old values will continue to be used but |
315 // all new values written will be encrypted on selected operating systems. New | 317 // all new values written will be encrypted on selected operating systems. New |
316 // records read by old clients will simply get an empty cookie value while old | 318 // records read by old clients will simply get an empty cookie value while old |
317 // records read by new clients will continue to operate with the unencrypted | 319 // records read by new clients will continue to operate with the unencrypted |
318 // version. New and old clients alike will always write/update records with | 320 // version. New and old clients alike will always write/update records with |
319 // what they support. | 321 // what they support. |
320 // | 322 // |
321 // Version 6 adds cookie priorities. This allows developers to influence the | 323 // 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. | 324 // order in which cookies are evicted in order to meet domain cookie limits. |
323 // | 325 // |
324 // Version 5 adds the columns has_expires and is_persistent, so that the | 326 // Version 5 adds the columns has_expires and is_persistent, so that the |
325 // database can store session cookies as well as persistent cookies. Databases | 327 // database can store session cookies as well as persistent cookies. Databases |
326 // of version 5 are incompatible with older versions of code. If a database of | 328 // of version 5 are incompatible with older versions of code. If a database of |
327 // version 5 is read by older code, session cookies will be treated as normal | 329 // version 5 is read by older code, session cookies will be treated as normal |
328 // cookies. Currently, these fields are written, but not read anymore. | 330 // cookies. Currently, these fields are written, but not read anymore. |
329 // | 331 // |
330 // In version 4, we migrated the time epoch. If you open the DB with an older | 332 // In version 4, we migrated the time epoch. If you open the DB with an older |
331 // version on Mac or Linux, the times will look wonky, but the file will likely | 333 // version on Mac or Linux, the times will look wonky, but the file will likely |
332 // be usable. On Windows version 3 and 4 are the same. | 334 // be usable. On Windows version 3 and 4 are the same. |
333 // | 335 // |
334 // Version 3 updated the database to include the last access time, so we can | 336 // Version 3 updated the database to include the last access time, so we can |
335 // expire them in decreasing order of use when we've reached the maximum | 337 // expire them in decreasing order of use when we've reached the maximum |
336 // number of cookies. | 338 // number of cookies. |
337 const int kCurrentVersionNumber = 7; | 339 const int kCurrentVersionNumber = 8; |
338 const int kCompatibleVersionNumber = 5; | 340 const int kCompatibleVersionNumber = 5; |
339 | 341 |
340 // Possible values for the 'priority' column. | 342 // Possible values for the 'priority' column. |
341 enum DBCookiePriority { | 343 enum DBCookiePriority { |
342 kCookiePriorityLow = 0, | 344 kCookiePriorityLow = 0, |
343 kCookiePriorityMedium = 1, | 345 kCookiePriorityMedium = 1, |
344 kCookiePriorityHigh = 2, | 346 kCookiePriorityHigh = 2, |
345 }; | 347 }; |
346 | 348 |
347 DBCookiePriority CookiePriorityToDBCookiePriority(net::CookiePriority value) { | 349 DBCookiePriority CookiePriorityToDBCookiePriority(net::CookiePriority value) { |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
393 base::Time start_; | 395 base::Time start_; |
394 | 396 |
395 DISALLOW_COPY_AND_ASSIGN(IncrementTimeDelta); | 397 DISALLOW_COPY_AND_ASSIGN(IncrementTimeDelta); |
396 }; | 398 }; |
397 | 399 |
398 // Initializes the cookies table, returning true on success. | 400 // Initializes the cookies table, returning true on success. |
399 bool InitTable(sql::Connection* db) { | 401 bool InitTable(sql::Connection* db) { |
400 if (!db->DoesTableExist("cookies")) { | 402 if (!db->DoesTableExist("cookies")) { |
401 std::string stmt(base::StringPrintf( | 403 std::string stmt(base::StringPrintf( |
402 "CREATE TABLE cookies (" | 404 "CREATE TABLE cookies (" |
403 "creation_utc INTEGER NOT NULL UNIQUE PRIMARY KEY," | 405 "creation_utc INTEGER NOT NULL UNIQUE PRIMARY KEY," |
404 "host_key TEXT NOT NULL," | 406 "host_key TEXT NOT NULL," |
405 "name TEXT NOT NULL," | 407 "name TEXT NOT NULL," |
406 "value TEXT NOT NULL," | 408 "value TEXT NOT NULL," |
407 "path TEXT NOT NULL," | 409 "path TEXT NOT NULL," |
408 "expires_utc INTEGER NOT NULL," | 410 "expires_utc INTEGER NOT NULL," |
409 "secure INTEGER NOT NULL," | 411 "secure INTEGER NOT NULL," |
410 "httponly INTEGER NOT NULL," | 412 "httponly INTEGER NOT NULL," |
411 "last_access_utc INTEGER NOT NULL, " | 413 "last_access_utc INTEGER NOT NULL, " |
412 "has_expires INTEGER NOT NULL DEFAULT 1, " | 414 "has_expires INTEGER NOT NULL DEFAULT 1, " |
413 "persistent INTEGER NOT NULL DEFAULT 1," | 415 "persistent INTEGER NOT NULL DEFAULT 1," |
414 "priority INTEGER NOT NULL DEFAULT %d," | 416 "priority INTEGER NOT NULL DEFAULT %d," |
415 "encrypted_value BLOB DEFAULT '')", | 417 "encrypted_value BLOB DEFAULT ''," |
| 418 "firstpartyonly INTEGER NOT NULL DEFAULT 0)", |
416 CookiePriorityToDBCookiePriority(net::COOKIE_PRIORITY_DEFAULT))); | 419 CookiePriorityToDBCookiePriority(net::COOKIE_PRIORITY_DEFAULT))); |
417 if (!db->Execute(stmt.c_str())) | 420 if (!db->Execute(stmt.c_str())) |
418 return false; | 421 return false; |
419 } | 422 } |
420 | 423 |
421 // Older code created an index on creation_utc, which is already | 424 // Older code created an index on creation_utc, which is already |
422 // primary key for the table. | 425 // primary key for the table. |
423 if (!db->Execute("DROP INDEX IF EXISTS cookie_times")) | 426 if (!db->Execute("DROP INDEX IF EXISTS cookie_times")) |
424 return false; | 427 return false; |
425 | 428 |
(...skipping 300 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
726 | 729 |
727 bool SQLitePersistentCookieStore::Backend::LoadCookiesForDomains( | 730 bool SQLitePersistentCookieStore::Backend::LoadCookiesForDomains( |
728 const std::set<std::string>& domains) { | 731 const std::set<std::string>& domains) { |
729 DCHECK(background_task_runner_->RunsTasksOnCurrentThread()); | 732 DCHECK(background_task_runner_->RunsTasksOnCurrentThread()); |
730 | 733 |
731 sql::Statement smt; | 734 sql::Statement smt; |
732 if (restore_old_session_cookies_) { | 735 if (restore_old_session_cookies_) { |
733 smt.Assign(db_->GetCachedStatement( | 736 smt.Assign(db_->GetCachedStatement( |
734 SQL_FROM_HERE, | 737 SQL_FROM_HERE, |
735 "SELECT creation_utc, host_key, name, value, encrypted_value, path, " | 738 "SELECT creation_utc, host_key, name, value, encrypted_value, path, " |
736 "expires_utc, secure, httponly, last_access_utc, has_expires, " | 739 "expires_utc, secure, httponly, firstpartyonly, last_access_utc, " |
737 "persistent, priority FROM cookies WHERE host_key = ?")); | 740 "has_expires, persistent, priority FROM cookies WHERE host_key = ?")); |
738 } else { | 741 } else { |
739 smt.Assign(db_->GetCachedStatement( | 742 smt.Assign(db_->GetCachedStatement( |
740 SQL_FROM_HERE, | 743 SQL_FROM_HERE, |
741 "SELECT creation_utc, host_key, name, value, encrypted_value, path, " | 744 "SELECT creation_utc, host_key, name, value, encrypted_value, path, " |
742 "expires_utc, secure, httponly, last_access_utc, has_expires, " | 745 "expires_utc, secure, httponly, firstpartyonly, last_access_utc, " |
743 "persistent, priority FROM cookies WHERE host_key = ? " | 746 "has_expires, persistent, priority FROM cookies WHERE host_key = ? " |
744 "AND persistent = 1")); | 747 "AND persistent = 1")); |
745 } | 748 } |
746 if (!smt.is_valid()) { | 749 if (!smt.is_valid()) { |
747 smt.Clear(); // Disconnect smt_ref from db_. | 750 smt.Clear(); // Disconnect smt_ref from db_. |
748 meta_table_.Reset(); | 751 meta_table_.Reset(); |
749 db_.reset(); | 752 db_.reset(); |
750 return false; | 753 return false; |
751 } | 754 } |
752 | 755 |
753 std::vector<net::CanonicalCookie*> cookies; | 756 std::vector<net::CanonicalCookie*> cookies; |
(...skipping 18 matching lines...) Expand all Loading... |
772 std::string value; | 775 std::string value; |
773 std::string encrypted_value = smt.ColumnString(4); | 776 std::string encrypted_value = smt.ColumnString(4); |
774 if (!encrypted_value.empty() && crypto_) { | 777 if (!encrypted_value.empty() && crypto_) { |
775 crypto_->DecryptString(encrypted_value, &value); | 778 crypto_->DecryptString(encrypted_value, &value); |
776 } else { | 779 } else { |
777 DCHECK(encrypted_value.empty()); | 780 DCHECK(encrypted_value.empty()); |
778 value = smt.ColumnString(3); | 781 value = smt.ColumnString(3); |
779 } | 782 } |
780 scoped_ptr<net::CanonicalCookie> cc(new net::CanonicalCookie( | 783 scoped_ptr<net::CanonicalCookie> cc(new net::CanonicalCookie( |
781 // The "source" URL is not used with persisted cookies. | 784 // The "source" URL is not used with persisted cookies. |
782 GURL(), // Source | 785 GURL(), // Source |
783 smt.ColumnString(2), // name | 786 smt.ColumnString(2), // name |
784 value, // value | 787 value, // value |
785 smt.ColumnString(1), // domain | 788 smt.ColumnString(1), // domain |
786 smt.ColumnString(5), // path | 789 smt.ColumnString(5), // path |
787 Time::FromInternalValue(smt.ColumnInt64(0)), // creation_utc | 790 Time::FromInternalValue(smt.ColumnInt64(0)), // creation_utc |
788 Time::FromInternalValue(smt.ColumnInt64(6)), // expires_utc | 791 Time::FromInternalValue(smt.ColumnInt64(6)), // expires_utc |
789 Time::FromInternalValue(smt.ColumnInt64(9)), // last_access_utc | 792 Time::FromInternalValue(smt.ColumnInt64(10)), // last_access_utc |
790 smt.ColumnInt(7) != 0, // secure | 793 smt.ColumnInt(7) != 0, // secure |
791 smt.ColumnInt(8) != 0, // httponly | 794 smt.ColumnInt(8) != 0, // httponly |
| 795 smt.ColumnInt(9) != 0, // firstpartyonly |
792 DBCookiePriorityToCookiePriority( | 796 DBCookiePriorityToCookiePriority( |
793 static_cast<DBCookiePriority>(smt.ColumnInt(12))))); // priority | 797 static_cast<DBCookiePriority>(smt.ColumnInt(13))))); // priority |
794 DLOG_IF(WARNING, cc->CreationDate() > Time::Now()) | 798 DLOG_IF(WARNING, cc->CreationDate() > Time::Now()) |
795 << L"CreationDate too recent"; | 799 << L"CreationDate too recent"; |
796 cookies_per_origin_[CookieOrigin(cc->Domain(), cc->IsSecure())]++; | 800 cookies_per_origin_[CookieOrigin(cc->Domain(), cc->IsSecure())]++; |
797 cookies->push_back(cc.release()); | 801 cookies->push_back(cc.release()); |
798 ++num_cookies_read_; | 802 ++num_cookies_read_; |
799 } | 803 } |
800 } | 804 } |
801 | 805 |
802 bool SQLitePersistentCookieStore::Backend::EnsureDatabaseVersion() { | 806 bool SQLitePersistentCookieStore::Backend::EnsureDatabaseVersion() { |
803 // Version check. | 807 // Version check. |
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
919 } | 923 } |
920 ++cur_version; | 924 ++cur_version; |
921 meta_table_.SetVersionNumber(cur_version); | 925 meta_table_.SetVersionNumber(cur_version); |
922 meta_table_.SetCompatibleVersionNumber( | 926 meta_table_.SetCompatibleVersionNumber( |
923 std::min(cur_version, kCompatibleVersionNumber)); | 927 std::min(cur_version, kCompatibleVersionNumber)); |
924 transaction.Commit(); | 928 transaction.Commit(); |
925 UMA_HISTOGRAM_TIMES("Cookie.TimeDatabaseMigrationToV7", | 929 UMA_HISTOGRAM_TIMES("Cookie.TimeDatabaseMigrationToV7", |
926 base::TimeTicks::Now() - start_time); | 930 base::TimeTicks::Now() - start_time); |
927 } | 931 } |
928 | 932 |
| 933 if (cur_version == 7) { |
| 934 const base::TimeTicks start_time = base::TimeTicks::Now(); |
| 935 sql::Transaction transaction(db_.get()); |
| 936 if (!transaction.Begin()) |
| 937 return false; |
| 938 // Alter the table to add a 'firstpartyonly' column. |
| 939 if (!db_->Execute( |
| 940 "ALTER TABLE cookies " |
| 941 "ADD COLUMN firstpartyonly INTEGER DEFAULT 0")) { |
| 942 LOG(WARNING) << "Unable to update cookie database to version 8."; |
| 943 return false; |
| 944 } |
| 945 ++cur_version; |
| 946 meta_table_.SetVersionNumber(cur_version); |
| 947 meta_table_.SetCompatibleVersionNumber( |
| 948 std::min(cur_version, kCompatibleVersionNumber)); |
| 949 transaction.Commit(); |
| 950 UMA_HISTOGRAM_TIMES("Cookie.TimeDatabaseMigrationToV8", |
| 951 base::TimeTicks::Now() - start_time); |
| 952 } |
| 953 |
929 // Put future migration cases here. | 954 // Put future migration cases here. |
930 | 955 |
931 if (cur_version < kCurrentVersionNumber) { | 956 if (cur_version < kCurrentVersionNumber) { |
932 UMA_HISTOGRAM_COUNTS_100("Cookie.CorruptMetaTable", 1); | 957 UMA_HISTOGRAM_COUNTS_100("Cookie.CorruptMetaTable", 1); |
933 | 958 |
934 meta_table_.Reset(); | 959 meta_table_.Reset(); |
935 db_.reset(new sql::Connection); | 960 db_.reset(new sql::Connection); |
936 if (!base::DeleteFile(path_, false) || | 961 if (!base::DeleteFile(path_, false) || |
937 !db_->Open(path_) || | 962 !db_->Open(path_) || |
938 !meta_table_.Init( | 963 !meta_table_.Init( |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1002 { | 1027 { |
1003 base::AutoLock locked(lock_); | 1028 base::AutoLock locked(lock_); |
1004 pending_.swap(ops); | 1029 pending_.swap(ops); |
1005 num_pending_ = 0; | 1030 num_pending_ = 0; |
1006 } | 1031 } |
1007 | 1032 |
1008 // Maybe an old timer fired or we are already Close()'ed. | 1033 // Maybe an old timer fired or we are already Close()'ed. |
1009 if (!db_.get() || ops.empty()) | 1034 if (!db_.get() || ops.empty()) |
1010 return; | 1035 return; |
1011 | 1036 |
1012 sql::Statement add_smt(db_->GetCachedStatement(SQL_FROM_HERE, | 1037 sql::Statement add_smt(db_->GetCachedStatement( |
| 1038 SQL_FROM_HERE, |
1013 "INSERT INTO cookies (creation_utc, host_key, name, value, " | 1039 "INSERT INTO cookies (creation_utc, host_key, name, value, " |
1014 "encrypted_value, path, expires_utc, secure, httponly, last_access_utc, " | 1040 "encrypted_value, path, expires_utc, secure, httponly, firstpartyonly, " |
1015 "has_expires, persistent, priority) " | 1041 "last_access_utc, has_expires, persistent, priority) " |
1016 "VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?)")); | 1042 "VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?)")); |
1017 if (!add_smt.is_valid()) | 1043 if (!add_smt.is_valid()) |
1018 return; | 1044 return; |
1019 | 1045 |
1020 sql::Statement update_access_smt(db_->GetCachedStatement(SQL_FROM_HERE, | 1046 sql::Statement update_access_smt(db_->GetCachedStatement(SQL_FROM_HERE, |
1021 "UPDATE cookies SET last_access_utc=? WHERE creation_utc=?")); | 1047 "UPDATE cookies SET last_access_utc=? WHERE creation_utc=?")); |
1022 if (!update_access_smt.is_valid()) | 1048 if (!update_access_smt.is_valid()) |
1023 return; | 1049 return; |
1024 | 1050 |
1025 sql::Statement del_smt(db_->GetCachedStatement(SQL_FROM_HERE, | 1051 sql::Statement del_smt(db_->GetCachedStatement(SQL_FROM_HERE, |
1026 "DELETE FROM cookies WHERE creation_utc=?")); | 1052 "DELETE FROM cookies WHERE creation_utc=?")); |
(...skipping 24 matching lines...) Expand all Loading... |
1051 add_smt.BindBlob(4, encrypted_value.data(), | 1077 add_smt.BindBlob(4, encrypted_value.data(), |
1052 static_cast<int>(encrypted_value.length())); | 1078 static_cast<int>(encrypted_value.length())); |
1053 } else { | 1079 } else { |
1054 add_smt.BindString(3, po->cc().Value()); | 1080 add_smt.BindString(3, po->cc().Value()); |
1055 add_smt.BindBlob(4, "", 0); // encrypted_value | 1081 add_smt.BindBlob(4, "", 0); // encrypted_value |
1056 } | 1082 } |
1057 add_smt.BindString(5, po->cc().Path()); | 1083 add_smt.BindString(5, po->cc().Path()); |
1058 add_smt.BindInt64(6, po->cc().ExpiryDate().ToInternalValue()); | 1084 add_smt.BindInt64(6, po->cc().ExpiryDate().ToInternalValue()); |
1059 add_smt.BindInt(7, po->cc().IsSecure()); | 1085 add_smt.BindInt(7, po->cc().IsSecure()); |
1060 add_smt.BindInt(8, po->cc().IsHttpOnly()); | 1086 add_smt.BindInt(8, po->cc().IsHttpOnly()); |
1061 add_smt.BindInt64(9, po->cc().LastAccessDate().ToInternalValue()); | 1087 add_smt.BindInt(9, po->cc().IsFirstPartyOnly()); |
1062 add_smt.BindInt(10, po->cc().IsPersistent()); | 1088 add_smt.BindInt64(10, po->cc().LastAccessDate().ToInternalValue()); |
1063 add_smt.BindInt(11, po->cc().IsPersistent()); | 1089 add_smt.BindInt(11, po->cc().IsPersistent()); |
1064 add_smt.BindInt( | 1090 add_smt.BindInt(12, po->cc().IsPersistent()); |
1065 12, CookiePriorityToDBCookiePriority(po->cc().Priority())); | 1091 add_smt.BindInt(13, |
| 1092 CookiePriorityToDBCookiePriority(po->cc().Priority())); |
1066 if (!add_smt.Run()) | 1093 if (!add_smt.Run()) |
1067 NOTREACHED() << "Could not add a cookie to the DB."; | 1094 NOTREACHED() << "Could not add a cookie to the DB."; |
1068 break; | 1095 break; |
1069 | 1096 |
1070 case PendingOperation::COOKIE_UPDATEACCESS: | 1097 case PendingOperation::COOKIE_UPDATEACCESS: |
1071 update_access_smt.Reset(true); | 1098 update_access_smt.Reset(true); |
1072 update_access_smt.BindInt64(0, | 1099 update_access_smt.BindInt64(0, |
1073 po->cc().LastAccessDate().ToInternalValue()); | 1100 po->cc().LastAccessDate().ToInternalValue()); |
1074 update_access_smt.BindInt64(1, | 1101 update_access_smt.BindInt64(1, |
1075 po->cc().CreationDate().ToInternalValue()); | 1102 po->cc().CreationDate().ToInternalValue()); |
(...skipping 295 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1371 | 1398 |
1372 if (base::CommandLine::ForCurrentProcess()->HasSwitch( | 1399 if (base::CommandLine::ForCurrentProcess()->HasSwitch( |
1373 switches::kEnableFileCookies)) { | 1400 switches::kEnableFileCookies)) { |
1374 cookie_monster->SetEnableFileScheme(true); | 1401 cookie_monster->SetEnableFileScheme(true); |
1375 } | 1402 } |
1376 | 1403 |
1377 return cookie_monster; | 1404 return cookie_monster; |
1378 } | 1405 } |
1379 | 1406 |
1380 } // namespace content | 1407 } // namespace content |
OLD | NEW |