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

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

Issue 876973003: Implement the "first-party-only" cookie flag. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: FirstPartyOnly. Created 5 years, 10 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 293 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698