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 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 156 // Cookies accessed less recently should be deleted first. | 156 // Cookies accessed less recently should be deleted first. |
| 157 if (it1->second->LastAccessDate() != it2->second->LastAccessDate()) | 157 if (it1->second->LastAccessDate() != it2->second->LastAccessDate()) |
| 158 return it1->second->LastAccessDate() < it2->second->LastAccessDate(); | 158 return it1->second->LastAccessDate() < it2->second->LastAccessDate(); |
| 159 | 159 |
| 160 // In rare cases we might have two cookies with identical last access times. | 160 // In rare cases we might have two cookies with identical last access times. |
| 161 // To preserve the stability of the sort, in these cases prefer to delete | 161 // To preserve the stability of the sort, in these cases prefer to delete |
| 162 // older cookies over newer ones. CreationDate() is guaranteed to be unique. | 162 // older cookies over newer ones. CreationDate() is guaranteed to be unique. |
| 163 return it1->second->CreationDate() < it2->second->CreationDate(); | 163 return it1->second->CreationDate() < it2->second->CreationDate(); |
| 164 } | 164 } |
| 165 | 165 |
| 166 // Compare cookies using name, domain and path, so that "equivalent" cookies | |
| 167 // (per RFC 2965) are equal to each other. | |
| 168 int PartialDiffCookieOrdering(const net::CanonicalCookie& a, | |
| 169 const net::CanonicalCookie& b) { | |
| 170 int diff = a.Name().compare(b.Name()); | |
| 171 if (diff != 0) | |
| 172 return diff; | |
| 173 | |
| 174 diff = a.Domain().compare(b.Domain()); | |
| 175 if (diff != 0) | |
| 176 return diff; | |
| 177 | |
| 178 return a.Path().compare(b.Path()); | |
| 179 } | |
| 180 | |
| 181 bool PartialDiffCookieSorter(const net::CanonicalCookie& a, | |
| 182 const net::CanonicalCookie& b) { | |
| 183 return PartialDiffCookieOrdering(a, b) < 0; | |
| 184 } | |
| 185 | |
| 186 // This is a stricter ordering than PartialDiffCookieOrdering, where all fields | |
| 187 // are used except the last access time and the creation date. | |
| 188 bool FullDiffCookieSorter(const net::CanonicalCookie& a, | |
| 189 const net::CanonicalCookie& b) { | |
| 190 int diff = PartialDiffCookieOrdering(a, b); | |
| 191 if (diff != 0) | |
| 192 return diff < 0; | |
| 193 | |
| 194 DCHECK(a.IsEquivalent(b)); | |
| 195 | |
| 196 // Compare other fields. | |
| 197 diff = a.Value().compare(b.Value()); | |
| 198 if (diff != 0) | |
| 199 return diff < 0; | |
| 200 | |
| 201 if (a.ExpiryDate() != b.ExpiryDate()) | |
| 202 return a.ExpiryDate() < b.ExpiryDate(); | |
| 203 | |
| 204 if (a.IsSecure() != b.IsSecure()) | |
| 205 return a.IsSecure(); | |
| 206 | |
| 207 if (a.IsHttpOnly() != b.IsHttpOnly()) | |
| 208 return a.IsHttpOnly(); | |
| 209 | |
| 210 return a.Priority() < b.Priority(); | |
| 211 } | |
| 212 | |
| 166 // Our strategy to find duplicates is: | 213 // Our strategy to find duplicates is: |
| 167 // (1) Build a map from (cookiename, cookiepath) to | 214 // (1) Build a map from (cookiename, cookiepath) to |
| 168 // {list of cookies with this signature, sorted by creation time}. | 215 // {list of cookies with this signature, sorted by creation time}. |
| 169 // (2) For each list with more than 1 entry, keep the cookie having the | 216 // (2) For each list with more than 1 entry, keep the cookie having the |
| 170 // most recent creation time, and delete the others. | 217 // most recent creation time, and delete the others. |
| 171 // | 218 // |
| 172 // Two cookies are considered equivalent if they have the same domain, | 219 // Two cookies are considered equivalent if they have the same domain, |
| 173 // name, and path. | 220 // name, and path. |
| 174 struct CookieSignature { | 221 struct CookieSignature { |
| 175 public: | 222 public: |
| (...skipping 581 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 757 FROM_HERE_WITH_EXPLICIT_FUNCTION( | 804 FROM_HERE_WITH_EXPLICIT_FUNCTION( |
| 758 "456373 CookieMonster::SetCookieWithOptionsTask::Run")); | 805 "456373 CookieMonster::SetCookieWithOptionsTask::Run")); |
| 759 bool result = this->cookie_monster()->SetCookieWithOptions(url_, cookie_line_, | 806 bool result = this->cookie_monster()->SetCookieWithOptions(url_, cookie_line_, |
| 760 options_); | 807 options_); |
| 761 if (!callback_.is_null()) { | 808 if (!callback_.is_null()) { |
| 762 this->InvokeCallback(base::Bind(&SetCookiesCallback::Run, | 809 this->InvokeCallback(base::Bind(&SetCookiesCallback::Run, |
| 763 base::Unretained(&callback_), result)); | 810 base::Unretained(&callback_), result)); |
| 764 } | 811 } |
| 765 } | 812 } |
| 766 | 813 |
| 814 // Task class for SetAllCookies call. | |
| 815 class CookieMonster::SetAllCookiesTask : public CookieMonsterTask { | |
| 816 public: | |
| 817 SetAllCookiesTask(CookieMonster* cookie_monster, | |
| 818 const CookieList& list, | |
| 819 const SetCookiesCallback& callback) | |
| 820 : CookieMonsterTask(cookie_monster), list_(list), callback_(callback) {} | |
| 821 | |
| 822 // CookieMonsterTask: | |
| 823 void Run() override; | |
| 824 | |
| 825 protected: | |
| 826 ~SetAllCookiesTask() override {} | |
| 827 | |
| 828 private: | |
| 829 CookieList list_; | |
| 830 SetCookiesCallback callback_; | |
| 831 | |
| 832 DISALLOW_COPY_AND_ASSIGN(SetAllCookiesTask); | |
| 833 }; | |
| 834 | |
| 835 void CookieMonster::SetAllCookiesTask::Run() { | |
| 836 CookieList positive_diff; | |
| 837 CookieList negative_diff; | |
| 838 CookieList old_cookies = this->cookie_monster()->GetAllCookies(); | |
| 839 this->cookie_monster()->ComputeCookieDiff(&old_cookies, &list_, | |
| 840 &positive_diff, &negative_diff); | |
| 841 | |
| 842 for (CookieList::const_iterator it = negative_diff.begin(); | |
| 843 it != negative_diff.end(); ++it) { | |
| 844 this->cookie_monster()->DeleteCanonicalCookie(*it); | |
| 845 } | |
| 846 | |
| 847 bool result = true; | |
| 848 if (positive_diff.size() > 0) | |
| 849 result = this->cookie_monster()->SetCanonicalCookies(list_); | |
| 850 | |
| 851 if (!callback_.is_null()) { | |
| 852 this->InvokeCallback(base::Bind(&SetCookiesCallback::Run, | |
| 853 base::Unretained(&callback_), result)); | |
| 854 } | |
| 855 } | |
| 856 | |
| 767 // Task class for GetCookiesWithOptions call. | 857 // Task class for GetCookiesWithOptions call. |
| 768 class CookieMonster::GetCookiesWithOptionsTask : public CookieMonsterTask { | 858 class CookieMonster::GetCookiesWithOptionsTask : public CookieMonsterTask { |
| 769 public: | 859 public: |
| 770 GetCookiesWithOptionsTask(CookieMonster* cookie_monster, | 860 GetCookiesWithOptionsTask(CookieMonster* cookie_monster, |
| 771 const GURL& url, | 861 const GURL& url, |
| 772 const CookieOptions& options, | 862 const CookieOptions& options, |
| 773 const GetCookiesCallback& callback) | 863 const GetCookiesCallback& callback) |
| 774 : CookieMonsterTask(cookie_monster), | 864 : CookieMonsterTask(cookie_monster), |
| 775 url_(url), | 865 url_(url), |
| 776 options_(options), | 866 options_(options), |
| (...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 978 | 1068 |
| 979 void CookieMonster::DeleteCanonicalCookieAsync( | 1069 void CookieMonster::DeleteCanonicalCookieAsync( |
| 980 const CanonicalCookie& cookie, | 1070 const CanonicalCookie& cookie, |
| 981 const DeleteCookieCallback& callback) { | 1071 const DeleteCookieCallback& callback) { |
| 982 scoped_refptr<DeleteCanonicalCookieTask> task = | 1072 scoped_refptr<DeleteCanonicalCookieTask> task = |
| 983 new DeleteCanonicalCookieTask(this, cookie, callback); | 1073 new DeleteCanonicalCookieTask(this, cookie, callback); |
| 984 | 1074 |
| 985 DoCookieTask(task); | 1075 DoCookieTask(task); |
| 986 } | 1076 } |
| 987 | 1077 |
| 1078 void CookieMonster::SetAllCookiesAsync(const CookieList& list, | |
| 1079 const SetCookiesCallback& callback) { | |
| 1080 scoped_refptr<SetAllCookiesTask> task = | |
| 1081 new SetAllCookiesTask(this, list, callback); | |
| 1082 DoCookieTask(task); | |
| 1083 } | |
| 1084 | |
| 988 void CookieMonster::SetCookieWithOptionsAsync( | 1085 void CookieMonster::SetCookieWithOptionsAsync( |
| 989 const GURL& url, | 1086 const GURL& url, |
| 990 const std::string& cookie_line, | 1087 const std::string& cookie_line, |
| 991 const CookieOptions& options, | 1088 const CookieOptions& options, |
| 992 const SetCookiesCallback& callback) { | 1089 const SetCookiesCallback& callback) { |
| 993 scoped_refptr<SetCookieWithOptionsTask> task = | 1090 scoped_refptr<SetCookieWithOptionsTask> task = |
| 994 new SetCookieWithOptionsTask(this, url, cookie_line, options, callback); | 1091 new SetCookieWithOptionsTask(this, url, cookie_line, options, callback); |
| 995 | 1092 |
| 996 DoCookieTaskForURL(task, url); | 1093 DoCookieTaskForURL(task, url); |
| 997 } | 1094 } |
| (...skipping 838 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1836 // We assume that hopefully setting a cookie will be less common than | 1933 // We assume that hopefully setting a cookie will be less common than |
| 1837 // querying a cookie. Since setting a cookie can put us over our limits, | 1934 // querying a cookie. Since setting a cookie can put us over our limits, |
| 1838 // make sure that we garbage collect... We can also make the assumption that | 1935 // make sure that we garbage collect... We can also make the assumption that |
| 1839 // if a cookie was set, in the common case it will be used soon after, | 1936 // if a cookie was set, in the common case it will be used soon after, |
| 1840 // and we will purge the expired cookies in GetCookies(). | 1937 // and we will purge the expired cookies in GetCookies(). |
| 1841 GarbageCollect(creation_time, key); | 1938 GarbageCollect(creation_time, key); |
| 1842 | 1939 |
| 1843 return true; | 1940 return true; |
| 1844 } | 1941 } |
| 1845 | 1942 |
| 1943 bool CookieMonster::SetCanonicalCookies(const CookieList& list) { | |
| 1944 base::AutoLock autolock(lock_); | |
| 1945 | |
| 1946 net::CookieOptions options; | |
| 1947 options.set_include_httponly(); | |
| 1948 | |
| 1949 for (CookieList::const_iterator it = list.begin(); it != list.end(); ++it) { | |
| 1950 scoped_ptr<CanonicalCookie> canonical_cookie(new CanonicalCookie(*it)); | |
| 1951 if (!SetCanonicalCookie(&canonical_cookie, it->CreationDate(), options)) | |
| 1952 return false; | |
| 1953 } | |
| 1954 | |
| 1955 return true; | |
| 1956 } | |
| 1957 | |
| 1846 void CookieMonster::InternalUpdateCookieAccessTime(CanonicalCookie* cc, | 1958 void CookieMonster::InternalUpdateCookieAccessTime(CanonicalCookie* cc, |
| 1847 const Time& current) { | 1959 const Time& current) { |
| 1848 lock_.AssertAcquired(); | 1960 lock_.AssertAcquired(); |
| 1849 | 1961 |
| 1850 // Based off the Mozilla code. When a cookie has been accessed recently, | 1962 // Based off the Mozilla code. When a cookie has been accessed recently, |
| 1851 // don't bother updating its access time again. This reduces the number of | 1963 // don't bother updating its access time again. This reduces the number of |
| 1852 // updates we do during pageload, which in turn reduces the chance our storage | 1964 // updates we do during pageload, which in turn reduces the chance our storage |
| 1853 // backend will hit its batch thresholds and be forced to update. | 1965 // backend will hit its batch thresholds and be forced to update. |
| 1854 if ((current - cc->LastAccessDate()) < last_access_threshold_) | 1966 if ((current - cc->LastAccessDate()) < last_access_threshold_) |
| 1855 return; | 1967 return; |
| (...skipping 363 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2219 } | 2331 } |
| 2220 | 2332 |
| 2221 // The system resolution is not high enough, so we can have multiple | 2333 // The system resolution is not high enough, so we can have multiple |
| 2222 // set cookies that result in the same system time. When this happens, we | 2334 // set cookies that result in the same system time. When this happens, we |
| 2223 // increment by one Time unit. Let's hope computers don't get too fast. | 2335 // increment by one Time unit. Let's hope computers don't get too fast. |
| 2224 Time CookieMonster::CurrentTime() { | 2336 Time CookieMonster::CurrentTime() { |
| 2225 return std::max(Time::Now(), Time::FromInternalValue( | 2337 return std::max(Time::Now(), Time::FromInternalValue( |
| 2226 last_time_seen_.ToInternalValue() + 1)); | 2338 last_time_seen_.ToInternalValue() + 1)); |
| 2227 } | 2339 } |
| 2228 | 2340 |
| 2341 void CookieMonster::ComputeCookieDiff(CookieList* old_cookies, | |
| 2342 CookieList* new_cookies, | |
| 2343 CookieList* cookies_to_add, | |
| 2344 CookieList* cookies_to_delete) { | |
| 2345 DCHECK(old_cookies); | |
| 2346 DCHECK(new_cookies); | |
| 2347 DCHECK(cookies_to_add); | |
| 2348 DCHECK(cookies_to_delete); | |
| 2349 DCHECK(cookies_to_add->empty()); | |
| 2350 DCHECK(cookies_to_delete->empty()); | |
| 2351 | |
| 2352 // Sort both lists. | |
| 2353 std::sort(old_cookies->begin(), old_cookies->end(), FullDiffCookieSorter); | |
| 2354 std::sort(new_cookies->begin(), new_cookies->end(), FullDiffCookieSorter); | |
| 2355 | |
| 2356 // Compute the cookies to be deleted. | |
| 2357 // It is OK to call set_difference using PartialDiffCookieSorter even though | |
|
erikwright (departed)
2015/03/13 13:59:01
// A set ordered by FullDiffCookieSorter is also o
droger
2015/03/16 13:03:50
Comment updated.
Unfortunately it seems that std::
| |
| 2358 // the list was sorted using FullDiffCookieSorter. | |
| 2359 std::set_difference( | |
|
erikwright (departed)
2015/03/13 13:59:01
How about the following comment.
// Select any ol
droger
2015/03/16 13:03:50
Done.
| |
| 2360 old_cookies->begin(), old_cookies->end(), new_cookies->begin(), | |
| 2361 new_cookies->end(), | |
| 2362 std::inserter(*cookies_to_delete, cookies_to_delete->begin()), | |
| 2363 PartialDiffCookieSorter); | |
| 2364 | |
| 2365 // Compute the cookies to be added. | |
| 2366 std::set_difference(new_cookies->begin(), new_cookies->end(), | |
|
erikwright (departed)
2015/03/13 13:59:01
// Select any new cookie for addition (or update)
droger
2015/03/16 13:03:50
Done.
| |
| 2367 old_cookies->begin(), old_cookies->end(), | |
| 2368 std::inserter(*cookies_to_add, cookies_to_add->begin()), | |
| 2369 FullDiffCookieSorter); | |
| 2370 } | |
| 2371 | |
| 2229 scoped_ptr<CookieStore::CookieChangedSubscription> | 2372 scoped_ptr<CookieStore::CookieChangedSubscription> |
| 2230 CookieMonster::AddCallbackForCookie(const GURL& gurl, | 2373 CookieMonster::AddCallbackForCookie(const GURL& gurl, |
| 2231 const std::string& name, | 2374 const std::string& name, |
| 2232 const CookieChangedCallback& callback) { | 2375 const CookieChangedCallback& callback) { |
| 2233 base::AutoLock autolock(lock_); | 2376 base::AutoLock autolock(lock_); |
| 2234 std::pair<GURL, std::string> key(gurl, name); | 2377 std::pair<GURL, std::string> key(gurl, name); |
| 2235 if (hook_map_.count(key) == 0) | 2378 if (hook_map_.count(key) == 0) |
| 2236 hook_map_[key] = make_linked_ptr(new CookieChangedCallbackList()); | 2379 hook_map_[key] = make_linked_ptr(new CookieChangedCallbackList()); |
| 2237 return hook_map_[key]->Add( | 2380 return hook_map_[key]->Add( |
| 2238 base::Bind(&RunAsync, base::MessageLoopProxy::current(), callback)); | 2381 base::Bind(&RunAsync, base::MessageLoopProxy::current(), callback)); |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 2252 it != hook_map_.end(); ++it) { | 2395 it != hook_map_.end(); ++it) { |
| 2253 std::pair<GURL, std::string> key = it->first; | 2396 std::pair<GURL, std::string> key = it->first; |
| 2254 if (cookie.IncludeForRequestURL(key.first, opts) && | 2397 if (cookie.IncludeForRequestURL(key.first, opts) && |
| 2255 cookie.Name() == key.second) { | 2398 cookie.Name() == key.second) { |
| 2256 it->second->Notify(cookie, removed); | 2399 it->second->Notify(cookie, removed); |
| 2257 } | 2400 } |
| 2258 } | 2401 } |
| 2259 } | 2402 } |
| 2260 | 2403 |
| 2261 } // namespace net | 2404 } // namespace net |
| OLD | NEW |