Chromium Code Reviews| 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 // Portions of this code based on Mozilla: | 5 // Portions of this code based on Mozilla: |
| 6 // (netwerk/cookie/src/nsCookieService.cpp) | 6 // (netwerk/cookie/src/nsCookieService.cpp) |
| 7 /* ***** BEGIN LICENSE BLOCK ***** | 7 /* ***** BEGIN LICENSE BLOCK ***** |
| 8 * Version: MPL 1.1/GPL 2.0/LGPL 2.1 | 8 * Version: MPL 1.1/GPL 2.0/LGPL 2.1 |
| 9 * | 9 * |
| 10 * The contents of this file are subject to the Mozilla Public License Version | 10 * The contents of this file are subject to the Mozilla Public License Version |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 55 #include "base/logging.h" | 55 #include "base/logging.h" |
| 56 #include "base/macros.h" | 56 #include "base/macros.h" |
| 57 #include "base/memory/ptr_util.h" | 57 #include "base/memory/ptr_util.h" |
| 58 #include "base/metrics/field_trial.h" | 58 #include "base/metrics/field_trial.h" |
| 59 #include "base/metrics/histogram.h" | 59 #include "base/metrics/histogram.h" |
| 60 #include "base/profiler/scoped_tracker.h" | 60 #include "base/profiler/scoped_tracker.h" |
| 61 #include "base/single_thread_task_runner.h" | 61 #include "base/single_thread_task_runner.h" |
| 62 #include "base/strings/string_util.h" | 62 #include "base/strings/string_util.h" |
| 63 #include "base/strings/stringprintf.h" | 63 #include "base/strings/stringprintf.h" |
| 64 #include "base/threading/thread_task_runner_handle.h" | 64 #include "base/threading/thread_task_runner_handle.h" |
| 65 #include "base/time/time.h" | |
| 65 #include "net/base/registry_controlled_domains/registry_controlled_domain.h" | 66 #include "net/base/registry_controlled_domains/registry_controlled_domain.h" |
| 66 #include "net/cookies/canonical_cookie.h" | 67 #include "net/cookies/canonical_cookie.h" |
| 67 #include "net/cookies/cookie_util.h" | 68 #include "net/cookies/cookie_util.h" |
| 68 #include "net/cookies/parsed_cookie.h" | 69 #include "net/cookies/parsed_cookie.h" |
| 69 #include "url/origin.h" | 70 #include "url/origin.h" |
| 70 | 71 |
| 71 using base::Time; | 72 using base::Time; |
| 72 using base::TimeDelta; | 73 using base::TimeDelta; |
| 73 using base::TimeTicks; | 74 using base::TimeTicks; |
| 74 | 75 |
| (...skipping 596 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 671 private: | 672 private: |
| 672 CanonicalCookie cookie_; | 673 CanonicalCookie cookie_; |
| 673 | 674 |
| 674 DISALLOW_COPY_AND_ASSIGN(DeleteCanonicalCookieTask); | 675 DISALLOW_COPY_AND_ASSIGN(DeleteCanonicalCookieTask); |
| 675 }; | 676 }; |
| 676 | 677 |
| 677 int CookieMonster::DeleteCanonicalCookieTask::RunDeleteTask() { | 678 int CookieMonster::DeleteCanonicalCookieTask::RunDeleteTask() { |
| 678 return this->cookie_monster()->DeleteCanonicalCookie(cookie_); | 679 return this->cookie_monster()->DeleteCanonicalCookie(cookie_); |
| 679 } | 680 } |
| 680 | 681 |
| 682 // Task class for SetCanonicalCookie call. | |
| 683 class CookieMonster::SetCanonicalCookieTask : public CookieMonsterTask { | |
| 684 public: | |
| 685 SetCanonicalCookieTask(CookieMonster* cookie_monster, | |
| 686 std::unique_ptr<CanonicalCookie> cookie, | |
| 687 bool secure_source, | |
| 688 bool modify_http_only, | |
| 689 const SetCookiesCallback& callback) | |
| 690 : CookieMonsterTask(cookie_monster), | |
| 691 cookie_(std::move(cookie)), | |
| 692 secure_source_(secure_source), | |
| 693 modify_http_only_(modify_http_only), | |
| 694 callback_(callback) {} | |
| 695 | |
| 696 // CookieMonsterTask: | |
| 697 void Run() override; | |
| 698 | |
| 699 protected: | |
| 700 ~SetCanonicalCookieTask() override {} | |
| 701 | |
| 702 private: | |
| 703 std::unique_ptr<CanonicalCookie> cookie_; | |
| 704 bool secure_source_; | |
| 705 bool modify_http_only_; | |
| 706 SetCookiesCallback callback_; | |
| 707 | |
| 708 DISALLOW_COPY_AND_ASSIGN(SetCanonicalCookieTask); | |
| 709 }; | |
| 710 | |
| 711 void CookieMonster::SetCanonicalCookieTask::Run() { | |
| 712 bool result = this->cookie_monster()->SetCanonicalCookie( | |
| 713 std::move(cookie_), secure_source_, modify_http_only_); | |
| 714 if (!callback_.is_null()) | |
| 715 callback_.Run(result); | |
| 716 } | |
| 717 | |
| 681 // Task class for SetCookieWithOptions call. | 718 // Task class for SetCookieWithOptions call. |
| 682 class CookieMonster::SetCookieWithOptionsTask : public CookieMonsterTask { | 719 class CookieMonster::SetCookieWithOptionsTask : public CookieMonsterTask { |
| 683 public: | 720 public: |
| 684 SetCookieWithOptionsTask(CookieMonster* cookie_monster, | 721 SetCookieWithOptionsTask(CookieMonster* cookie_monster, |
| 685 const GURL& url, | 722 const GURL& url, |
| 686 const std::string& cookie_line, | 723 const std::string& cookie_line, |
| 687 const CookieOptions& options, | 724 const CookieOptions& options, |
| 688 const SetCookiesCallback& callback) | 725 const SetCookiesCallback& callback) |
| 689 : CookieMonsterTask(cookie_monster), | 726 : CookieMonsterTask(cookie_monster), |
| 690 url_(url), | 727 url_(url), |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 742 this->cookie_monster()->ComputeCookieDiff(&old_cookies, &list_, | 779 this->cookie_monster()->ComputeCookieDiff(&old_cookies, &list_, |
| 743 &positive_diff, &negative_diff); | 780 &positive_diff, &negative_diff); |
| 744 | 781 |
| 745 for (CookieList::const_iterator it = negative_diff.begin(); | 782 for (CookieList::const_iterator it = negative_diff.begin(); |
| 746 it != negative_diff.end(); ++it) { | 783 it != negative_diff.end(); ++it) { |
| 747 this->cookie_monster()->DeleteCanonicalCookie(*it); | 784 this->cookie_monster()->DeleteCanonicalCookie(*it); |
| 748 } | 785 } |
| 749 | 786 |
| 750 bool result = true; | 787 bool result = true; |
| 751 if (positive_diff.size() > 0) | 788 if (positive_diff.size() > 0) |
| 752 result = this->cookie_monster()->SetCanonicalCookies(list_); | 789 result = this->cookie_monster()->SetCanonicalCookiesInternal(list_); |
| 753 | 790 |
| 754 if (!callback_.is_null()) | 791 if (!callback_.is_null()) |
| 755 callback_.Run(result); | 792 callback_.Run(result); |
| 756 } | 793 } |
| 757 | 794 |
| 758 // Task class for GetCookiesWithOptions call. | 795 // Task class for GetCookiesWithOptions call. |
| 759 class CookieMonster::GetCookiesWithOptionsTask : public CookieMonsterTask { | 796 class CookieMonster::GetCookiesWithOptionsTask : public CookieMonsterTask { |
| 760 public: | 797 public: |
| 761 GetCookiesWithOptionsTask(CookieMonster* cookie_monster, | 798 GetCookiesWithOptionsTask(CookieMonster* cookie_monster, |
| 762 const GURL& url, | 799 const GURL& url, |
| (...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 875 store_->SetForceKeepSessionState(); | 912 store_->SetForceKeepSessionState(); |
| 876 } | 913 } |
| 877 | 914 |
| 878 void CookieMonster::SetAllCookiesAsync(const CookieList& list, | 915 void CookieMonster::SetAllCookiesAsync(const CookieList& list, |
| 879 const SetCookiesCallback& callback) { | 916 const SetCookiesCallback& callback) { |
| 880 scoped_refptr<SetAllCookiesTask> task = | 917 scoped_refptr<SetAllCookiesTask> task = |
| 881 new SetAllCookiesTask(this, list, callback); | 918 new SetAllCookiesTask(this, list, callback); |
| 882 DoCookieTask(task); | 919 DoCookieTask(task); |
| 883 } | 920 } |
| 884 | 921 |
| 922 void CookieMonster::SetCanonicalCookieAsync( | |
| 923 const CanonicalCookie& cookie, | |
| 924 bool secure_source, | |
| 925 bool modify_http_only, | |
| 926 const SetCookiesCallback& callback) { | |
| 927 DCHECK(cookie.IsCanonical()); | |
| 928 scoped_refptr<SetCanonicalCookieTask> task = new SetCanonicalCookieTask( | |
| 929 this, base::MakeUnique<CanonicalCookie>(cookie), secure_source, | |
| 930 modify_http_only, callback); | |
| 931 | |
| 932 // TODO(rdsmith): Switch to DoCookieTaskForURL (or the equivalent). | |
| 933 // This is tricky because we don't have the scheme in this routine | |
| 934 // and DoCookieTaskForURL uses cookie_util::GetEffectiveDomain(scheme, host) | |
| 935 // to generate the database key to block behind. | |
| 936 DoCookieTask(task); | |
| 937 } | |
| 938 | |
| 885 void CookieMonster::SetCookieWithOptionsAsync( | 939 void CookieMonster::SetCookieWithOptionsAsync( |
| 886 const GURL& url, | 940 const GURL& url, |
| 887 const std::string& cookie_line, | 941 const std::string& cookie_line, |
| 888 const CookieOptions& options, | 942 const CookieOptions& options, |
| 889 const SetCookiesCallback& callback) { | 943 const SetCookiesCallback& callback) { |
| 890 scoped_refptr<SetCookieWithOptionsTask> task = | 944 scoped_refptr<SetCookieWithOptionsTask> task = |
| 891 new SetCookieWithOptionsTask(this, url, cookie_line, options, callback); | 945 new SetCookieWithOptionsTask(this, url, cookie_line, options, callback); |
| 892 | 946 |
| 893 DoCookieTaskForURL(task, url); | 947 DoCookieTaskForURL(task, url); |
| 894 } | 948 } |
| (...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1041 base::Time last_access_time, | 1095 base::Time last_access_time, |
| 1042 bool secure, | 1096 bool secure, |
| 1043 bool http_only, | 1097 bool http_only, |
| 1044 CookieSameSite same_site, | 1098 CookieSameSite same_site, |
| 1045 CookiePriority priority) { | 1099 CookiePriority priority) { |
| 1046 DCHECK(thread_checker_.CalledOnValidThread()); | 1100 DCHECK(thread_checker_.CalledOnValidThread()); |
| 1047 | 1101 |
| 1048 if (!HasCookieableScheme(url)) | 1102 if (!HasCookieableScheme(url)) |
| 1049 return false; | 1103 return false; |
| 1050 | 1104 |
| 1051 // TODO(mmenke): This class assumes each cookie to have a unique creation | |
| 1052 // time. Allowing the caller to set the creation time violates that | |
| 1053 // assumption. Worth fixing? Worth noting that time changes between browser | |
| 1054 // restarts can cause the same issue. | |
| 1055 base::Time actual_creation_time = creation_time; | |
| 1056 if (creation_time.is_null()) { | |
| 1057 actual_creation_time = CurrentTime(); | |
| 1058 last_time_seen_ = actual_creation_time; | |
| 1059 } | |
| 1060 | |
| 1061 // Validate consistency of passed arguments. | 1105 // Validate consistency of passed arguments. |
| 1062 if (ParsedCookie::ParseTokenString(name) != name || | 1106 if (ParsedCookie::ParseTokenString(name) != name || |
| 1063 ParsedCookie::ParseValueString(value) != value || | 1107 ParsedCookie::ParseValueString(value) != value || |
| 1064 ParsedCookie::ParseValueString(domain) != domain || | 1108 ParsedCookie::ParseValueString(domain) != domain || |
| 1065 ParsedCookie::ParseValueString(path) != path) { | 1109 ParsedCookie::ParseValueString(path) != path) { |
| 1066 return false; | 1110 return false; |
| 1067 } | 1111 } |
| 1068 | 1112 |
| 1069 // Validate passed arguments against URL. | |
| 1070 if (secure && !url.SchemeIsCryptographic()) | |
| 1071 return false; | |
| 1072 | |
| 1073 std::string cookie_domain; | 1113 std::string cookie_domain; |
| 1074 if (!cookie_util::GetCookieDomainWithString(url, domain, &cookie_domain)) | 1114 if (!cookie_util::GetCookieDomainWithString(url, domain, &cookie_domain)) |
| 1075 return false; | 1115 return false; |
| 1076 | 1116 |
| 1077 std::string cookie_path = CanonicalCookie::CanonPathWithString(url, path); | 1117 std::string cookie_path = CanonicalCookie::CanonPathWithString(url, path); |
| 1078 if (!path.empty() && cookie_path != path) | 1118 if (!path.empty() && cookie_path != path) |
| 1079 return false; | 1119 return false; |
| 1080 | 1120 |
| 1081 // Canonicalize path again to make sure it escapes characters as needed. | 1121 // Canonicalize path again to make sure it escapes characters as needed. |
| 1082 url::Component path_component(0, cookie_path.length()); | 1122 url::Component path_component(0, cookie_path.length()); |
| 1083 url::RawCanonOutputT<char> canon_path; | 1123 url::RawCanonOutputT<char> canon_path; |
| 1084 url::Component canon_path_component; | 1124 url::Component canon_path_component; |
| 1085 url::CanonicalizePath(cookie_path.data(), path_component, &canon_path, | 1125 url::CanonicalizePath(cookie_path.data(), path_component, &canon_path, |
| 1086 &canon_path_component); | 1126 &canon_path_component); |
| 1087 cookie_path = std::string(canon_path.data() + canon_path_component.begin, | 1127 cookie_path = std::string(canon_path.data() + canon_path_component.begin, |
| 1088 canon_path_component.len); | 1128 canon_path_component.len); |
| 1089 | 1129 |
| 1090 std::unique_ptr<CanonicalCookie> cc(base::MakeUnique<CanonicalCookie>( | 1130 std::unique_ptr<CanonicalCookie> cc(base::MakeUnique<CanonicalCookie>( |
| 1091 name, value, cookie_domain, cookie_path, actual_creation_time, | 1131 name, value, cookie_domain, cookie_path, creation_time, expiration_time, |
| 1092 expiration_time, last_access_time, secure, http_only, same_site, | 1132 last_access_time, secure, http_only, same_site, priority)); |
| 1093 priority)); | |
| 1094 | 1133 |
| 1095 CookieOptions options; | 1134 return SetCanonicalCookie(std::move(cc), url.SchemeIsCryptographic(), true); |
| 1096 options.set_include_httponly(); | |
| 1097 options.set_same_site_cookie_mode( | |
| 1098 CookieOptions::SameSiteCookieMode::INCLUDE_STRICT_AND_LAX); | |
| 1099 return SetCanonicalCookie(std::move(cc), url, options); | |
| 1100 } | 1135 } |
| 1101 | 1136 |
| 1102 CookieList CookieMonster::GetAllCookies() { | 1137 CookieList CookieMonster::GetAllCookies() { |
| 1103 DCHECK(thread_checker_.CalledOnValidThread()); | 1138 DCHECK(thread_checker_.CalledOnValidThread()); |
| 1104 | 1139 |
| 1105 // This function is being called to scrape the cookie list for management UI | 1140 // This function is being called to scrape the cookie list for management UI |
| 1106 // or similar. We shouldn't show expired cookies in this list since it will | 1141 // or similar. We shouldn't show expired cookies in this list since it will |
| 1107 // just be confusing to users, and this function is called rarely enough (and | 1142 // just be confusing to users, and this function is called rarely enough (and |
| 1108 // is already slow enough) that it's OK to take the time to garbage collect | 1143 // is already slow enough) that it's OK to take the time to garbage collect |
| 1109 // the expired cookies now. | 1144 // the expired cookies now. |
| (...skipping 298 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1408 // Even if a key is expired, insert it so it can be garbage collected, | 1443 // Even if a key is expired, insert it so it can be garbage collected, |
| 1409 // removed, and sync'd. | 1444 // removed, and sync'd. |
| 1410 CookieItVector cookies_with_control_chars; | 1445 CookieItVector cookies_with_control_chars; |
| 1411 | 1446 |
| 1412 for (auto& cookie : cookies) { | 1447 for (auto& cookie : cookies) { |
| 1413 int64_t cookie_creation_time = cookie->CreationDate().ToInternalValue(); | 1448 int64_t cookie_creation_time = cookie->CreationDate().ToInternalValue(); |
| 1414 | 1449 |
| 1415 if (creation_times_.insert(cookie_creation_time).second) { | 1450 if (creation_times_.insert(cookie_creation_time).second) { |
| 1416 CanonicalCookie* cookie_ptr = cookie.get(); | 1451 CanonicalCookie* cookie_ptr = cookie.get(); |
| 1417 CookieMap::iterator inserted = InternalInsertCookie( | 1452 CookieMap::iterator inserted = InternalInsertCookie( |
| 1418 GetKey(cookie_ptr->Domain()), std::move(cookie), GURL(), false); | 1453 GetKey(cookie_ptr->Domain()), std::move(cookie), false, false); |
| 1419 const Time cookie_access_time(cookie_ptr->LastAccessDate()); | 1454 const Time cookie_access_time(cookie_ptr->LastAccessDate()); |
| 1420 if (earliest_access_time_.is_null() || | 1455 if (earliest_access_time_.is_null() || |
| 1421 cookie_access_time < earliest_access_time_) | 1456 cookie_access_time < earliest_access_time_) |
| 1422 earliest_access_time_ = cookie_access_time; | 1457 earliest_access_time_ = cookie_access_time; |
| 1423 | 1458 |
| 1424 if (ContainsControlCharacter(cookie_ptr->Name()) || | 1459 if (ContainsControlCharacter(cookie_ptr->Name()) || |
| 1425 ContainsControlCharacter(cookie_ptr->Value())) { | 1460 ContainsControlCharacter(cookie_ptr->Value())) { |
| 1426 cookies_with_control_chars.push_back(inserted); | 1461 cookies_with_control_chars.push_back(inserted); |
| 1427 } | 1462 } |
| 1428 } else { | 1463 } else { |
| (...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1622 // time if we've been requested to do so. | 1657 // time if we've been requested to do so. |
| 1623 if (options.update_access_time()) { | 1658 if (options.update_access_time()) { |
| 1624 InternalUpdateCookieAccessTime(cc, current); | 1659 InternalUpdateCookieAccessTime(cc, current); |
| 1625 } | 1660 } |
| 1626 cookies->push_back(cc); | 1661 cookies->push_back(cc); |
| 1627 } | 1662 } |
| 1628 } | 1663 } |
| 1629 | 1664 |
| 1630 bool CookieMonster::DeleteAnyEquivalentCookie(const std::string& key, | 1665 bool CookieMonster::DeleteAnyEquivalentCookie(const std::string& key, |
| 1631 const CanonicalCookie& ecc, | 1666 const CanonicalCookie& ecc, |
| 1632 const GURL& source_url, | 1667 bool source_secure, |
| 1633 bool skip_httponly, | 1668 bool skip_httponly, |
| 1634 bool already_expired) { | 1669 bool already_expired) { |
| 1635 DCHECK(thread_checker_.CalledOnValidThread()); | 1670 DCHECK(thread_checker_.CalledOnValidThread()); |
| 1636 | 1671 |
| 1637 bool found_equivalent_cookie = false; | 1672 bool found_equivalent_cookie = false; |
| 1638 bool skipped_httponly = false; | 1673 bool skipped_httponly = false; |
| 1639 bool skipped_secure_cookie = false; | 1674 bool skipped_secure_cookie = false; |
| 1640 | 1675 |
| 1641 histogram_cookie_delete_equivalent_->Add(COOKIE_DELETE_EQUIVALENT_ATTEMPT); | 1676 histogram_cookie_delete_equivalent_->Add(COOKIE_DELETE_EQUIVALENT_ATTEMPT); |
| 1642 | 1677 |
| 1643 for (CookieMapItPair its = cookies_.equal_range(key); | 1678 for (CookieMapItPair its = cookies_.equal_range(key); |
| 1644 its.first != its.second;) { | 1679 its.first != its.second;) { |
| 1645 CookieMap::iterator curit = its.first; | 1680 CookieMap::iterator curit = its.first; |
| 1646 CanonicalCookie* cc = curit->second.get(); | 1681 CanonicalCookie* cc = curit->second.get(); |
| 1647 ++its.first; | 1682 ++its.first; |
| 1648 | 1683 |
| 1649 // If the cookie is being set from an insecure scheme, then if a cookie | 1684 // If the cookie is being set from an insecure scheme, then if a cookie |
| 1650 // already exists with the same name and it is Secure, then the cookie | 1685 // already exists with the same name and it is Secure, then the cookie |
| 1651 // should *not* be updated if they domain-match and ignoring the path | 1686 // should *not* be updated if they domain-match and ignoring the path |
| 1652 // attribute. | 1687 // attribute. |
| 1653 // | 1688 // |
| 1654 // See: https://tools.ietf.org/html/draft-ietf-httpbis-cookie-alone | 1689 // See: https://tools.ietf.org/html/draft-ietf-httpbis-cookie-alone |
| 1655 if (cc->IsSecure() && !source_url.SchemeIsCryptographic() && | 1690 if (cc->IsSecure() && !source_secure && |
| 1656 ecc.IsEquivalentForSecureCookieMatching(*cc)) { | 1691 ecc.IsEquivalentForSecureCookieMatching(*cc)) { |
| 1657 skipped_secure_cookie = true; | 1692 skipped_secure_cookie = true; |
| 1658 histogram_cookie_delete_equivalent_->Add( | 1693 histogram_cookie_delete_equivalent_->Add( |
| 1659 COOKIE_DELETE_EQUIVALENT_SKIPPING_SECURE); | 1694 COOKIE_DELETE_EQUIVALENT_SKIPPING_SECURE); |
| 1660 // If the cookie is equivalent to the new cookie and wouldn't have been | 1695 // If the cookie is equivalent to the new cookie and wouldn't have been |
| 1661 // skipped for being HTTP-only, record that it is a skipped secure cookie | 1696 // skipped for being HTTP-only, record that it is a skipped secure cookie |
| 1662 // that would have been deleted otherwise. | 1697 // that would have been deleted otherwise. |
| 1663 if (ecc.IsEquivalent(*cc)) { | 1698 if (ecc.IsEquivalent(*cc)) { |
| 1664 found_equivalent_cookie = true; | 1699 found_equivalent_cookie = true; |
| 1665 | 1700 |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 1686 } | 1721 } |
| 1687 found_equivalent_cookie = true; | 1722 found_equivalent_cookie = true; |
| 1688 } | 1723 } |
| 1689 } | 1724 } |
| 1690 return skipped_httponly || skipped_secure_cookie; | 1725 return skipped_httponly || skipped_secure_cookie; |
| 1691 } | 1726 } |
| 1692 | 1727 |
| 1693 CookieMonster::CookieMap::iterator CookieMonster::InternalInsertCookie( | 1728 CookieMonster::CookieMap::iterator CookieMonster::InternalInsertCookie( |
| 1694 const std::string& key, | 1729 const std::string& key, |
| 1695 std::unique_ptr<CanonicalCookie> cc, | 1730 std::unique_ptr<CanonicalCookie> cc, |
| 1696 const GURL& source_url, | 1731 bool source_secure, |
| 1697 bool sync_to_store) { | 1732 bool sync_to_store) { |
| 1698 DCHECK(thread_checker_.CalledOnValidThread()); | 1733 DCHECK(thread_checker_.CalledOnValidThread()); |
| 1699 CanonicalCookie* cc_ptr = cc.get(); | 1734 CanonicalCookie* cc_ptr = cc.get(); |
| 1700 | 1735 |
| 1701 if ((cc_ptr->IsPersistent() || persist_session_cookies_) && store_.get() && | 1736 if ((cc_ptr->IsPersistent() || persist_session_cookies_) && store_.get() && |
| 1702 sync_to_store) | 1737 sync_to_store) |
| 1703 store_->AddCookie(*cc_ptr); | 1738 store_->AddCookie(*cc_ptr); |
| 1704 CookieMap::iterator inserted = | 1739 CookieMap::iterator inserted = |
| 1705 cookies_.insert(CookieMap::value_type(key, std::move(cc))); | 1740 cookies_.insert(CookieMap::value_type(key, std::move(cc))); |
| 1706 if (delegate_.get()) { | 1741 if (delegate_.get()) { |
| 1707 delegate_->OnCookieChanged(*cc_ptr, false, | 1742 delegate_->OnCookieChanged(*cc_ptr, false, |
| 1708 CookieStore::ChangeCause::INSERTED); | 1743 CookieStore::ChangeCause::INSERTED); |
| 1709 } | 1744 } |
| 1710 | 1745 |
| 1711 // See InitializeHistograms() for details. | 1746 // See InitializeHistograms() for details. |
| 1712 int32_t type_sample = cc_ptr->SameSite() != CookieSameSite::NO_RESTRICTION | 1747 int32_t type_sample = cc_ptr->SameSite() != CookieSameSite::NO_RESTRICTION |
| 1713 ? 1 << COOKIE_TYPE_SAME_SITE | 1748 ? 1 << COOKIE_TYPE_SAME_SITE |
| 1714 : 0; | 1749 : 0; |
| 1715 type_sample |= cc_ptr->IsHttpOnly() ? 1 << COOKIE_TYPE_HTTPONLY : 0; | 1750 type_sample |= cc_ptr->IsHttpOnly() ? 1 << COOKIE_TYPE_HTTPONLY : 0; |
| 1716 type_sample |= cc_ptr->IsSecure() ? 1 << COOKIE_TYPE_SECURE : 0; | 1751 type_sample |= cc_ptr->IsSecure() ? 1 << COOKIE_TYPE_SECURE : 0; |
| 1717 histogram_cookie_type_->Add(type_sample); | 1752 histogram_cookie_type_->Add(type_sample); |
| 1718 | 1753 |
| 1719 // Histogram the type of scheme used on URLs that set cookies. This | 1754 // Histogram the type of scheme used on URLs that set cookies. This |
| 1720 // intentionally includes cookies that are set or overwritten by | 1755 // intentionally includes cookies that are set or overwritten by |
| 1721 // http:// URLs, but not cookies that are cleared by http:// URLs, to | 1756 // http:// URLs, but not cookies that are cleared by http:// URLs, to |
| 1722 // understand if the former behavior can be deprecated for Secure | 1757 // understand if the former behavior can be deprecated for Secure |
| 1723 // cookies. | 1758 // cookies. |
| 1724 if (!source_url.is_empty()) { | 1759 CookieSource cookie_source_sample = |
| 1725 CookieSource cookie_source_sample; | 1760 (source_secure |
| 1726 if (source_url.SchemeIsCryptographic()) { | 1761 ? (cc_ptr->IsSecure() |
| 1727 cookie_source_sample = | 1762 ? COOKIE_SOURCE_SECURE_COOKIE_CRYPTOGRAPHIC_SCHEME |
| 1728 cc_ptr->IsSecure() | 1763 : COOKIE_SOURCE_NONSECURE_COOKIE_CRYPTOGRAPHIC_SCHEME) |
| 1729 ? COOKIE_SOURCE_SECURE_COOKIE_CRYPTOGRAPHIC_SCHEME | 1764 : (cc_ptr->IsSecure() |
| 1730 : COOKIE_SOURCE_NONSECURE_COOKIE_CRYPTOGRAPHIC_SCHEME; | 1765 ? COOKIE_SOURCE_SECURE_COOKIE_NONCRYPTOGRAPHIC_SCHEME |
| 1731 } else { | 1766 : COOKIE_SOURCE_NONSECURE_COOKIE_NONCRYPTOGRAPHIC_SCHEME)); |
| 1732 cookie_source_sample = | 1767 histogram_cookie_source_scheme_->Add(cookie_source_sample); |
| 1733 cc_ptr->IsSecure() | |
| 1734 ? COOKIE_SOURCE_SECURE_COOKIE_NONCRYPTOGRAPHIC_SCHEME | |
| 1735 : COOKIE_SOURCE_NONSECURE_COOKIE_NONCRYPTOGRAPHIC_SCHEME; | |
| 1736 } | |
| 1737 histogram_cookie_source_scheme_->Add(cookie_source_sample); | |
| 1738 } | |
| 1739 | 1768 |
| 1740 RunCookieChangedCallbacks(*cc_ptr, CookieStore::ChangeCause::INSERTED); | 1769 RunCookieChangedCallbacks(*cc_ptr, CookieStore::ChangeCause::INSERTED); |
| 1741 | 1770 |
| 1742 return inserted; | 1771 return inserted; |
| 1743 } | 1772 } |
| 1744 | 1773 |
| 1745 bool CookieMonster::SetCookieWithCreationTimeAndOptions( | 1774 bool CookieMonster::SetCookieWithCreationTimeAndOptions( |
| 1746 const GURL& url, | 1775 const GURL& url, |
| 1747 const std::string& cookie_line, | 1776 const std::string& cookie_line, |
| 1748 const Time& creation_time_or_null, | 1777 const Time& creation_time_or_null, |
| 1749 const CookieOptions& options) { | 1778 const CookieOptions& options) { |
| 1750 DCHECK(thread_checker_.CalledOnValidThread()); | 1779 DCHECK(thread_checker_.CalledOnValidThread()); |
| 1751 | 1780 |
| 1752 VLOG(kVlogSetCookies) << "SetCookie() line: " << cookie_line; | 1781 VLOG(kVlogSetCookies) << "SetCookie() line: " << cookie_line; |
| 1753 | 1782 |
| 1754 Time creation_time = creation_time_or_null; | 1783 Time creation_time = creation_time_or_null; |
| 1755 if (creation_time.is_null()) { | 1784 if (creation_time.is_null()) { |
| 1756 creation_time = CurrentTime(); | 1785 creation_time = CurrentTime(); |
| 1757 last_time_seen_ = creation_time; | 1786 last_time_seen_ = creation_time; |
| 1758 } | 1787 } |
| 1759 | 1788 |
| 1760 std::unique_ptr<CanonicalCookie> cc( | 1789 std::unique_ptr<CanonicalCookie> cc( |
| 1761 CanonicalCookie::Create(url, cookie_line, creation_time, options)); | 1790 CanonicalCookie::Create(url, cookie_line, creation_time, options)); |
| 1762 | 1791 |
| 1763 if (!cc.get()) { | 1792 if (!cc.get()) { |
| 1764 VLOG(kVlogSetCookies) << "WARNING: Failed to allocate CanonicalCookie"; | 1793 VLOG(kVlogSetCookies) << "WARNING: Failed to allocate CanonicalCookie"; |
| 1765 return false; | 1794 return false; |
| 1766 } | 1795 } |
| 1767 return SetCanonicalCookie(std::move(cc), url, options); | 1796 return SetCanonicalCookie(std::move(cc), url.SchemeIsCryptographic(), |
| 1797 !options.exclude_httponly()); | |
|
mmenke
2017/05/22 18:51:27
This is a web-visible behavior change, right? Thi
mmenke
2017/05/22 19:07:04
If this is a web-visible behavior change, this sho
Randy Smith (Not in Mondays)
2017/05/22 21:54:03
Aw, drat, it looks like I refactored a check from
Randy Smith (Not in Mondays)
2017/05/25 20:45:35
Matt: I was digging into this issue more closely
Randy Smith (Not in Mondays)
2017/05/25 20:59:25
Followup: The only place where this might be a beh
| |
| 1768 } | 1798 } |
| 1769 | 1799 |
| 1770 bool CookieMonster::SetCanonicalCookie(std::unique_ptr<CanonicalCookie> cc, | 1800 bool CookieMonster::SetCanonicalCookie(std::unique_ptr<CanonicalCookie> cc, |
| 1771 const GURL& source_url, | 1801 bool secure_source, |
| 1772 const CookieOptions& options) { | 1802 bool modify_http_only) { |
| 1773 DCHECK(thread_checker_.CalledOnValidThread()); | 1803 DCHECK(thread_checker_.CalledOnValidThread()); |
| 1774 | 1804 |
| 1775 Time creation_time = cc->CreationDate(); | 1805 // TODO(mmenke): This class assumes each cookie to have a unique creation |
| 1806 // time. Allowing the caller to set the creation time violates that | |
| 1807 // assumption. Worth fixing? Worth noting that time changes between browser | |
| 1808 // restarts can cause the same issue. | |
| 1809 base::Time creation_date = cc->CreationDate(); | |
| 1810 if (cc->CreationDate().is_null()) { | |
| 1811 creation_date = CurrentTime(); | |
| 1812 cc->SetCreationDate(creation_date); | |
| 1813 last_time_seen_ = creation_date; | |
| 1814 } | |
| 1815 | |
| 1776 const std::string key(GetKey(cc->Domain())); | 1816 const std::string key(GetKey(cc->Domain())); |
| 1777 bool already_expired = cc->IsExpired(creation_time); | 1817 bool already_expired = cc->IsExpired(creation_date); |
| 1778 | 1818 |
| 1779 if (DeleteAnyEquivalentCookie(key, *cc, source_url, | 1819 if (!secure_source && cc->IsSecure()) |
| 1780 options.exclude_httponly(), already_expired)) { | 1820 return false; |
| 1821 | |
| 1822 if (DeleteAnyEquivalentCookie(key, *cc, secure_source, !modify_http_only, | |
| 1823 already_expired)) { | |
| 1781 std::string error; | 1824 std::string error; |
| 1782 error = | 1825 error = |
| 1783 "SetCookie() not clobbering httponly cookie or secure cookie for " | 1826 "SetCookie() not clobbering httponly cookie or secure cookie for " |
| 1784 "insecure scheme"; | 1827 "insecure scheme"; |
| 1785 | 1828 |
| 1786 VLOG(kVlogSetCookies) << error; | 1829 VLOG(kVlogSetCookies) << error; |
| 1787 return false; | 1830 return false; |
| 1788 } | 1831 } |
| 1789 | 1832 |
| 1790 VLOG(kVlogSetCookies) << "SetCookie() key: " << key | 1833 VLOG(kVlogSetCookies) << "SetCookie() key: " << key |
| 1791 << " cc: " << cc->DebugString(); | 1834 << " cc: " << cc->DebugString(); |
| 1792 | 1835 |
| 1793 // Realize that we might be setting an expired cookie, and the only point | 1836 // Realize that we might be setting an expired cookie, and the only point |
| 1794 // was to delete the cookie which we've already done. | 1837 // was to delete the cookie which we've already done. |
| 1795 if (!already_expired) { | 1838 if (!already_expired) { |
| 1796 // See InitializeHistograms() for details. | 1839 // See InitializeHistograms() for details. |
| 1797 if (cc->IsPersistent()) { | 1840 if (cc->IsPersistent()) { |
| 1798 histogram_expiration_duration_minutes_->Add( | 1841 histogram_expiration_duration_minutes_->Add( |
| 1799 (cc->ExpiryDate() - creation_time).InMinutes()); | 1842 (cc->ExpiryDate() - creation_date).InMinutes()); |
| 1800 } | 1843 } |
| 1801 | 1844 |
| 1802 InternalInsertCookie(key, std::move(cc), source_url, true); | 1845 InternalInsertCookie(key, std::move(cc), secure_source, true); |
| 1803 } else { | 1846 } else { |
| 1804 VLOG(kVlogSetCookies) << "SetCookie() not storing already expired cookie."; | 1847 VLOG(kVlogSetCookies) << "SetCookie() not storing already expired cookie."; |
| 1805 } | 1848 } |
| 1806 | 1849 |
| 1807 // We assume that hopefully setting a cookie will be less common than | 1850 // We assume that hopefully setting a cookie will be less common than |
| 1808 // querying a cookie. Since setting a cookie can put us over our limits, | 1851 // querying a cookie. Since setting a cookie can put us over our limits, |
| 1809 // make sure that we garbage collect... We can also make the assumption that | 1852 // make sure that we garbage collect... We can also make the assumption that |
| 1810 // if a cookie was set, in the common case it will be used soon after, | 1853 // if a cookie was set, in the common case it will be used soon after, |
| 1811 // and we will purge the expired cookies in GetCookies(). | 1854 // and we will purge the expired cookies in GetCookies(). |
| 1812 GarbageCollect(creation_time, key); | 1855 GarbageCollect(creation_date, key); |
| 1813 | 1856 |
| 1814 return true; | 1857 return true; |
| 1815 } | 1858 } |
| 1816 | 1859 |
| 1817 bool CookieMonster::SetCanonicalCookies(const CookieList& list) { | 1860 bool CookieMonster::SetCanonicalCookiesInternal(const CookieList& list) { |
| 1818 DCHECK(thread_checker_.CalledOnValidThread()); | 1861 DCHECK(thread_checker_.CalledOnValidThread()); |
| 1819 | 1862 |
| 1820 CookieOptions options; | 1863 CookieOptions options; |
| 1821 options.set_include_httponly(); | 1864 options.set_include_httponly(); |
| 1822 | 1865 |
| 1823 for (const auto& cookie : list) { | 1866 for (const auto& cookie : list) { |
| 1824 // Use an empty GURL. This method does not support setting secure cookies. | 1867 // Use an empty GURL. This method does not support setting secure cookies. |
| 1825 if (!SetCanonicalCookie(base::MakeUnique<CanonicalCookie>(cookie), GURL(), | 1868 if (!SetCanonicalCookie(base::MakeUnique<CanonicalCookie>(cookie), false, |
| 1826 options)) { | 1869 true)) { |
| 1827 return false; | 1870 return false; |
| 1828 } | 1871 } |
| 1829 } | 1872 } |
| 1830 | 1873 |
| 1831 return true; | 1874 return true; |
| 1832 } | 1875 } |
| 1833 | 1876 |
| 1834 void CookieMonster::InternalUpdateCookieAccessTime(CanonicalCookie* cc, | 1877 void CookieMonster::InternalUpdateCookieAccessTime(CanonicalCookie* cc, |
| 1835 const Time& current) { | 1878 const Time& current) { |
| 1836 DCHECK(thread_checker_.CalledOnValidThread()); | 1879 DCHECK(thread_checker_.CalledOnValidThread()); |
| (...skipping 411 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2248 "Cookie.Count", 1, 4000, 50, base::Histogram::kUmaTargetedHistogramFlag); | 2291 "Cookie.Count", 1, 4000, 50, base::Histogram::kUmaTargetedHistogramFlag); |
| 2249 | 2292 |
| 2250 // From UMA_HISTOGRAM_ENUMERATION | 2293 // From UMA_HISTOGRAM_ENUMERATION |
| 2251 histogram_cookie_deletion_cause_ = base::LinearHistogram::FactoryGet( | 2294 histogram_cookie_deletion_cause_ = base::LinearHistogram::FactoryGet( |
| 2252 "Cookie.DeletionCause", 1, DELETE_COOKIE_LAST_ENTRY - 1, | 2295 "Cookie.DeletionCause", 1, DELETE_COOKIE_LAST_ENTRY - 1, |
| 2253 DELETE_COOKIE_LAST_ENTRY, base::Histogram::kUmaTargetedHistogramFlag); | 2296 DELETE_COOKIE_LAST_ENTRY, base::Histogram::kUmaTargetedHistogramFlag); |
| 2254 histogram_cookie_type_ = base::LinearHistogram::FactoryGet( | 2297 histogram_cookie_type_ = base::LinearHistogram::FactoryGet( |
| 2255 "Cookie.Type", 1, (1 << COOKIE_TYPE_LAST_ENTRY) - 1, | 2298 "Cookie.Type", 1, (1 << COOKIE_TYPE_LAST_ENTRY) - 1, |
| 2256 1 << COOKIE_TYPE_LAST_ENTRY, base::Histogram::kUmaTargetedHistogramFlag); | 2299 1 << COOKIE_TYPE_LAST_ENTRY, base::Histogram::kUmaTargetedHistogramFlag); |
| 2257 histogram_cookie_source_scheme_ = base::LinearHistogram::FactoryGet( | 2300 histogram_cookie_source_scheme_ = base::LinearHistogram::FactoryGet( |
| 2258 "Cookie.CookieSourceScheme", 1, COOKIE_SOURCE_LAST_ENTRY - 1, | 2301 "Cookie.CookieSourceScheme2", 1, COOKIE_SOURCE_LAST_ENTRY - 1, |
| 2259 COOKIE_SOURCE_LAST_ENTRY, base::Histogram::kUmaTargetedHistogramFlag); | 2302 COOKIE_SOURCE_LAST_ENTRY, base::Histogram::kUmaTargetedHistogramFlag); |
| 2260 histogram_cookie_delete_equivalent_ = base::LinearHistogram::FactoryGet( | 2303 histogram_cookie_delete_equivalent_ = base::LinearHistogram::FactoryGet( |
| 2261 "Cookie.CookieDeleteEquivalent", 1, | 2304 "Cookie.CookieDeleteEquivalent", 1, |
| 2262 COOKIE_DELETE_EQUIVALENT_LAST_ENTRY - 1, | 2305 COOKIE_DELETE_EQUIVALENT_LAST_ENTRY - 1, |
| 2263 COOKIE_DELETE_EQUIVALENT_LAST_ENTRY, | 2306 COOKIE_DELETE_EQUIVALENT_LAST_ENTRY, |
| 2264 base::Histogram::kUmaTargetedHistogramFlag); | 2307 base::Histogram::kUmaTargetedHistogramFlag); |
| 2265 | 2308 |
| 2266 // From UMA_HISTOGRAM_{CUSTOM_,}TIMES | 2309 // From UMA_HISTOGRAM_{CUSTOM_,}TIMES |
| 2267 histogram_time_blocked_on_load_ = base::Histogram::FactoryTimeGet( | 2310 histogram_time_blocked_on_load_ = base::Histogram::FactoryTimeGet( |
| 2268 "Cookie.TimeBlockedOnLoad", base::TimeDelta::FromMilliseconds(1), | 2311 "Cookie.TimeBlockedOnLoad", base::TimeDelta::FromMilliseconds(1), |
| (...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2392 it != hook_map_.end(); ++it) { | 2435 it != hook_map_.end(); ++it) { |
| 2393 std::pair<GURL, std::string> key = it->first; | 2436 std::pair<GURL, std::string> key = it->first; |
| 2394 if (cookie.IncludeForRequestURL(key.first, opts) && | 2437 if (cookie.IncludeForRequestURL(key.first, opts) && |
| 2395 cookie.Name() == key.second) { | 2438 cookie.Name() == key.second) { |
| 2396 it->second->Notify(cookie, cause); | 2439 it->second->Notify(cookie, cause); |
| 2397 } | 2440 } |
| 2398 } | 2441 } |
| 2399 } | 2442 } |
| 2400 | 2443 |
| 2401 } // namespace net | 2444 } // namespace net |
| OLD | NEW |