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 |