| 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 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 189 | 189 |
| 190 bool LRACookieSorter(const CookieMonster::CookieMap::iterator& it1, | 190 bool LRACookieSorter(const CookieMonster::CookieMap::iterator& it1, |
| 191 const CookieMonster::CookieMap::iterator& it2) { | 191 const CookieMonster::CookieMap::iterator& it2) { |
| 192 if (it1->second->LastAccessDate() != it2->second->LastAccessDate()) | 192 if (it1->second->LastAccessDate() != it2->second->LastAccessDate()) |
| 193 return it1->second->LastAccessDate() < it2->second->LastAccessDate(); | 193 return it1->second->LastAccessDate() < it2->second->LastAccessDate(); |
| 194 | 194 |
| 195 // Ensure stability for == last access times by falling back to creation. | 195 // Ensure stability for == last access times by falling back to creation. |
| 196 return it1->second->CreationDate() < it2->second->CreationDate(); | 196 return it1->second->CreationDate() < it2->second->CreationDate(); |
| 197 } | 197 } |
| 198 | 198 |
| 199 // Compare cookies using name, domain and path, so that "equivalent" cookies | |
| 200 // (per RFC 2965) are equal to each other. | |
| 201 bool PartialDiffCookieSorter(const CanonicalCookie& a, | |
| 202 const CanonicalCookie& b) { | |
| 203 return a.PartialCompare(b); | |
| 204 } | |
| 205 | |
| 206 // This is a stricter ordering than PartialDiffCookieOrdering, where all fields | |
| 207 // are used. | |
| 208 bool FullDiffCookieSorter(const CanonicalCookie& a, const CanonicalCookie& b) { | |
| 209 return a.FullCompare(b); | |
| 210 } | |
| 211 | |
| 212 // Our strategy to find duplicates is: | 199 // Our strategy to find duplicates is: |
| 213 // (1) Build a map from (cookiename, cookiepath) to | 200 // (1) Build a map from (cookiename, cookiepath) to |
| 214 // {list of cookies with this signature, sorted by creation time}. | 201 // {list of cookies with this signature, sorted by creation time}. |
| 215 // (2) For each list with more than 1 entry, keep the cookie having the | 202 // (2) For each list with more than 1 entry, keep the cookie having the |
| 216 // most recent creation time, and delete the others. | 203 // most recent creation time, and delete the others. |
| 217 // | 204 // |
| 218 // Two cookies are considered equivalent if they have the same domain, | 205 // Two cookies are considered equivalent if they have the same domain, |
| 219 // name, and path. | 206 // name, and path. |
| 220 struct CookieSignature { | 207 struct CookieSignature { |
| 221 public: | 208 public: |
| (...skipping 1253 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1475 // if a cookie was set, in the common case it will be used soon after, | 1462 // if a cookie was set, in the common case it will be used soon after, |
| 1476 // and we will purge the expired cookies in GetCookies(). | 1463 // and we will purge the expired cookies in GetCookies(). |
| 1477 GarbageCollect(creation_date, key); | 1464 GarbageCollect(creation_date, key); |
| 1478 | 1465 |
| 1479 MaybeRunCookieCallback(std::move(callback), true); | 1466 MaybeRunCookieCallback(std::move(callback), true); |
| 1480 } | 1467 } |
| 1481 | 1468 |
| 1482 void CookieMonster::SetAllCookies(CookieList list, | 1469 void CookieMonster::SetAllCookies(CookieList list, |
| 1483 SetCookiesCallback callback) { | 1470 SetCookiesCallback callback) { |
| 1484 DCHECK(thread_checker_.CalledOnValidThread()); | 1471 DCHECK(thread_checker_.CalledOnValidThread()); |
| 1485 CookieList positive_diff; | |
| 1486 CookieList negative_diff; | |
| 1487 | 1472 |
| 1488 CookieList old_cookies; | 1473 // Nuke the existing store. |
| 1489 old_cookies.reserve(cookies_.size()); | 1474 while (!cookies_.empty()) { |
| 1490 for (const auto& cookie : cookies_) | 1475 // TODO(rdsmith): The CANONICAL is a lie. |
| 1491 old_cookies.push_back(*cookie.second.get()); | 1476 InternalDeleteCookie(cookies_.begin(), true, DELETE_COOKIE_CANONICAL); |
| 1492 | |
| 1493 ComputeCookieDiff(&old_cookies, &list, &positive_diff, &negative_diff); | |
| 1494 | |
| 1495 for (const auto& cookie_to_delete : negative_diff) { | |
| 1496 for (CookieMapItPair its = | |
| 1497 cookies_.equal_range(GetKey(cookie_to_delete.Domain())); | |
| 1498 its.first != its.second; ++its.first) { | |
| 1499 // The creation date acts as the unique index... | |
| 1500 if (its.first->second->CreationDate() == | |
| 1501 cookie_to_delete.CreationDate()) { | |
| 1502 // TODO(rdsmith): DELETE_COOKIE_CANONICAL is incorrect and should | |
| 1503 // be changed. | |
| 1504 InternalDeleteCookie(its.first, true, DELETE_COOKIE_CANONICAL); | |
| 1505 break; | |
| 1506 } | |
| 1507 } | |
| 1508 } | 1477 } |
| 1509 | 1478 |
| 1510 if (positive_diff.size() == 0) { | 1479 // Set all passed in cookies. |
| 1511 MaybeRunCookieCallback(std::move(callback), true); | |
| 1512 return; | |
| 1513 } | |
| 1514 | |
| 1515 for (const auto& cookie : list) { | 1480 for (const auto& cookie : list) { |
| 1516 const std::string key(GetKey(cookie.Domain())); | 1481 const std::string key(GetKey(cookie.Domain())); |
| 1517 Time creation_time = cookie.CreationDate(); | 1482 Time creation_time = cookie.CreationDate(); |
| 1518 bool already_expired = cookie.IsExpired(creation_time); | 1483 if (cookie.IsExpired(creation_time)) |
| 1519 | |
| 1520 bool result = | |
| 1521 DeleteAnyEquivalentCookie(key, cookie, true, false, already_expired); | |
| 1522 DCHECK(!result); | |
| 1523 | |
| 1524 if (already_expired) | |
| 1525 continue; | 1484 continue; |
| 1526 | 1485 |
| 1527 if (cookie.IsPersistent()) { | 1486 if (cookie.IsPersistent()) { |
| 1528 histogram_expiration_duration_minutes_->Add( | 1487 histogram_expiration_duration_minutes_->Add( |
| 1529 (cookie.ExpiryDate() - creation_time).InMinutes()); | 1488 (cookie.ExpiryDate() - creation_time).InMinutes()); |
| 1530 } | 1489 } |
| 1531 | 1490 |
| 1532 InternalInsertCookie(key, base::MakeUnique<CanonicalCookie>(cookie), true); | 1491 InternalInsertCookie(key, base::MakeUnique<CanonicalCookie>(cookie), true); |
| 1533 GarbageCollect(creation_time, key); | 1492 GarbageCollect(creation_time, key); |
| 1534 } | 1493 } |
| (...skipping 512 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2047 .first; | 2006 .first; |
| 2048 } | 2007 } |
| 2049 it->second.push_back(std::move(callback)); | 2008 it->second.push_back(std::move(callback)); |
| 2050 return; | 2009 return; |
| 2051 } | 2010 } |
| 2052 } | 2011 } |
| 2053 | 2012 |
| 2054 std::move(callback).Run(); | 2013 std::move(callback).Run(); |
| 2055 } | 2014 } |
| 2056 | 2015 |
| 2057 void CookieMonster::ComputeCookieDiff(CookieList* old_cookies, | |
| 2058 CookieList* new_cookies, | |
| 2059 CookieList* cookies_to_add, | |
| 2060 CookieList* cookies_to_delete) { | |
| 2061 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 2062 | |
| 2063 DCHECK(old_cookies); | |
| 2064 DCHECK(new_cookies); | |
| 2065 DCHECK(cookies_to_add); | |
| 2066 DCHECK(cookies_to_delete); | |
| 2067 DCHECK(cookies_to_add->empty()); | |
| 2068 DCHECK(cookies_to_delete->empty()); | |
| 2069 | |
| 2070 // Sort both lists. | |
| 2071 // A set ordered by FullDiffCookieSorter is also ordered by | |
| 2072 // PartialDiffCookieSorter. | |
| 2073 std::sort(old_cookies->begin(), old_cookies->end(), FullDiffCookieSorter); | |
| 2074 std::sort(new_cookies->begin(), new_cookies->end(), FullDiffCookieSorter); | |
| 2075 | |
| 2076 // Select any old cookie for deletion if no new cookie has the same name, | |
| 2077 // domain, and path. | |
| 2078 std::set_difference( | |
| 2079 old_cookies->begin(), old_cookies->end(), new_cookies->begin(), | |
| 2080 new_cookies->end(), | |
| 2081 std::inserter(*cookies_to_delete, cookies_to_delete->begin()), | |
| 2082 PartialDiffCookieSorter); | |
| 2083 | |
| 2084 // Select any new cookie for addition (or update) if no old cookie is exactly | |
| 2085 // equivalent. | |
| 2086 std::set_difference(new_cookies->begin(), new_cookies->end(), | |
| 2087 old_cookies->begin(), old_cookies->end(), | |
| 2088 std::inserter(*cookies_to_add, cookies_to_add->begin()), | |
| 2089 FullDiffCookieSorter); | |
| 2090 } | |
| 2091 | |
| 2092 void CookieMonster::RunCookieChangedCallbacks(const CanonicalCookie& cookie, | 2016 void CookieMonster::RunCookieChangedCallbacks(const CanonicalCookie& cookie, |
| 2093 ChangeCause cause) { | 2017 ChangeCause cause) { |
| 2094 DCHECK(thread_checker_.CalledOnValidThread()); | 2018 DCHECK(thread_checker_.CalledOnValidThread()); |
| 2095 | 2019 |
| 2096 CookieOptions opts; | 2020 CookieOptions opts; |
| 2097 opts.set_include_httponly(); | 2021 opts.set_include_httponly(); |
| 2098 opts.set_same_site_cookie_mode( | 2022 opts.set_same_site_cookie_mode( |
| 2099 CookieOptions::SameSiteCookieMode::INCLUDE_STRICT_AND_LAX); | 2023 CookieOptions::SameSiteCookieMode::INCLUDE_STRICT_AND_LAX); |
| 2100 // Note that the callbacks in hook_map_ are wrapped with RunAsync(), so they | 2024 // Note that the callbacks in hook_map_ are wrapped with RunAsync(), so they |
| 2101 // are guaranteed to not take long - they just post a RunAsync task back to | 2025 // are guaranteed to not take long - they just post a RunAsync task back to |
| 2102 // the appropriate thread's message loop and return. | 2026 // the appropriate thread's message loop and return. |
| 2103 // TODO(mmenke): Consider running these synchronously? | 2027 // TODO(mmenke): Consider running these synchronously? |
| 2104 for (CookieChangedHookMap::iterator it = hook_map_.begin(); | 2028 for (CookieChangedHookMap::iterator it = hook_map_.begin(); |
| 2105 it != hook_map_.end(); ++it) { | 2029 it != hook_map_.end(); ++it) { |
| 2106 std::pair<GURL, std::string> key = it->first; | 2030 std::pair<GURL, std::string> key = it->first; |
| 2107 if (cookie.IncludeForRequestURL(key.first, opts) && | 2031 if (cookie.IncludeForRequestURL(key.first, opts) && |
| 2108 cookie.Name() == key.second) { | 2032 cookie.Name() == key.second) { |
| 2109 it->second->Notify(cookie, cause); | 2033 it->second->Notify(cookie, cause); |
| 2110 } | 2034 } |
| 2111 } | 2035 } |
| 2112 } | 2036 } |
| 2113 | 2037 |
| 2114 } // namespace net | 2038 } // namespace net |
| OLD | NEW |