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 bool PartialDiffCookieSorter(const net::CanonicalCookie& a, |
| 169 const net::CanonicalCookie& b) { |
| 170 return a.PartialCompare(b); |
| 171 } |
| 172 |
| 173 // This is a stricter ordering than PartialDiffCookieOrdering, where all fields |
| 174 // are used. |
| 175 bool FullDiffCookieSorter(const net::CanonicalCookie& a, |
| 176 const net::CanonicalCookie& b) { |
| 177 return a.FullCompare(b); |
| 178 } |
| 179 |
166 // Our strategy to find duplicates is: | 180 // Our strategy to find duplicates is: |
167 // (1) Build a map from (cookiename, cookiepath) to | 181 // (1) Build a map from (cookiename, cookiepath) to |
168 // {list of cookies with this signature, sorted by creation time}. | 182 // {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 | 183 // (2) For each list with more than 1 entry, keep the cookie having the |
170 // most recent creation time, and delete the others. | 184 // most recent creation time, and delete the others. |
171 // | 185 // |
172 // Two cookies are considered equivalent if they have the same domain, | 186 // Two cookies are considered equivalent if they have the same domain, |
173 // name, and path. | 187 // name, and path. |
174 struct CookieSignature { | 188 struct CookieSignature { |
175 public: | 189 public: |
(...skipping 581 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
757 FROM_HERE_WITH_EXPLICIT_FUNCTION( | 771 FROM_HERE_WITH_EXPLICIT_FUNCTION( |
758 "456373 CookieMonster::SetCookieWithOptionsTask::Run")); | 772 "456373 CookieMonster::SetCookieWithOptionsTask::Run")); |
759 bool result = this->cookie_monster()->SetCookieWithOptions(url_, cookie_line_, | 773 bool result = this->cookie_monster()->SetCookieWithOptions(url_, cookie_line_, |
760 options_); | 774 options_); |
761 if (!callback_.is_null()) { | 775 if (!callback_.is_null()) { |
762 this->InvokeCallback(base::Bind(&SetCookiesCallback::Run, | 776 this->InvokeCallback(base::Bind(&SetCookiesCallback::Run, |
763 base::Unretained(&callback_), result)); | 777 base::Unretained(&callback_), result)); |
764 } | 778 } |
765 } | 779 } |
766 | 780 |
| 781 // Task class for SetAllCookies call. |
| 782 class CookieMonster::SetAllCookiesTask : public CookieMonsterTask { |
| 783 public: |
| 784 SetAllCookiesTask(CookieMonster* cookie_monster, |
| 785 const CookieList& list, |
| 786 const SetCookiesCallback& callback) |
| 787 : CookieMonsterTask(cookie_monster), list_(list), callback_(callback) {} |
| 788 |
| 789 // CookieMonsterTask: |
| 790 void Run() override; |
| 791 |
| 792 protected: |
| 793 ~SetAllCookiesTask() override {} |
| 794 |
| 795 private: |
| 796 CookieList list_; |
| 797 SetCookiesCallback callback_; |
| 798 |
| 799 DISALLOW_COPY_AND_ASSIGN(SetAllCookiesTask); |
| 800 }; |
| 801 |
| 802 void CookieMonster::SetAllCookiesTask::Run() { |
| 803 CookieList positive_diff; |
| 804 CookieList negative_diff; |
| 805 CookieList old_cookies = this->cookie_monster()->GetAllCookies(); |
| 806 this->cookie_monster()->ComputeCookieDiff(&old_cookies, &list_, |
| 807 &positive_diff, &negative_diff); |
| 808 |
| 809 for (CookieList::const_iterator it = negative_diff.begin(); |
| 810 it != negative_diff.end(); ++it) { |
| 811 this->cookie_monster()->DeleteCanonicalCookie(*it); |
| 812 } |
| 813 |
| 814 bool result = true; |
| 815 if (positive_diff.size() > 0) |
| 816 result = this->cookie_monster()->SetCanonicalCookies(list_); |
| 817 |
| 818 if (!callback_.is_null()) { |
| 819 this->InvokeCallback(base::Bind(&SetCookiesCallback::Run, |
| 820 base::Unretained(&callback_), result)); |
| 821 } |
| 822 } |
| 823 |
767 // Task class for GetCookiesWithOptions call. | 824 // Task class for GetCookiesWithOptions call. |
768 class CookieMonster::GetCookiesWithOptionsTask : public CookieMonsterTask { | 825 class CookieMonster::GetCookiesWithOptionsTask : public CookieMonsterTask { |
769 public: | 826 public: |
770 GetCookiesWithOptionsTask(CookieMonster* cookie_monster, | 827 GetCookiesWithOptionsTask(CookieMonster* cookie_monster, |
771 const GURL& url, | 828 const GURL& url, |
772 const CookieOptions& options, | 829 const CookieOptions& options, |
773 const GetCookiesCallback& callback) | 830 const GetCookiesCallback& callback) |
774 : CookieMonsterTask(cookie_monster), | 831 : CookieMonsterTask(cookie_monster), |
775 url_(url), | 832 url_(url), |
776 options_(options), | 833 options_(options), |
(...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
978 | 1035 |
979 void CookieMonster::DeleteCanonicalCookieAsync( | 1036 void CookieMonster::DeleteCanonicalCookieAsync( |
980 const CanonicalCookie& cookie, | 1037 const CanonicalCookie& cookie, |
981 const DeleteCookieCallback& callback) { | 1038 const DeleteCookieCallback& callback) { |
982 scoped_refptr<DeleteCanonicalCookieTask> task = | 1039 scoped_refptr<DeleteCanonicalCookieTask> task = |
983 new DeleteCanonicalCookieTask(this, cookie, callback); | 1040 new DeleteCanonicalCookieTask(this, cookie, callback); |
984 | 1041 |
985 DoCookieTask(task); | 1042 DoCookieTask(task); |
986 } | 1043 } |
987 | 1044 |
| 1045 void CookieMonster::SetAllCookiesAsync(const CookieList& list, |
| 1046 const SetCookiesCallback& callback) { |
| 1047 scoped_refptr<SetAllCookiesTask> task = |
| 1048 new SetAllCookiesTask(this, list, callback); |
| 1049 DoCookieTask(task); |
| 1050 } |
| 1051 |
988 void CookieMonster::SetCookieWithOptionsAsync( | 1052 void CookieMonster::SetCookieWithOptionsAsync( |
989 const GURL& url, | 1053 const GURL& url, |
990 const std::string& cookie_line, | 1054 const std::string& cookie_line, |
991 const CookieOptions& options, | 1055 const CookieOptions& options, |
992 const SetCookiesCallback& callback) { | 1056 const SetCookiesCallback& callback) { |
993 scoped_refptr<SetCookieWithOptionsTask> task = | 1057 scoped_refptr<SetCookieWithOptionsTask> task = |
994 new SetCookieWithOptionsTask(this, url, cookie_line, options, callback); | 1058 new SetCookieWithOptionsTask(this, url, cookie_line, options, callback); |
995 | 1059 |
996 DoCookieTaskForURL(task, url); | 1060 DoCookieTaskForURL(task, url); |
997 } | 1061 } |
(...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 | 1900 // 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, | 1901 // 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 | 1902 // 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, | 1903 // 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(). | 1904 // and we will purge the expired cookies in GetCookies(). |
1841 GarbageCollect(creation_time, key); | 1905 GarbageCollect(creation_time, key); |
1842 | 1906 |
1843 return true; | 1907 return true; |
1844 } | 1908 } |
1845 | 1909 |
| 1910 bool CookieMonster::SetCanonicalCookies(const CookieList& list) { |
| 1911 base::AutoLock autolock(lock_); |
| 1912 |
| 1913 net::CookieOptions options; |
| 1914 options.set_include_httponly(); |
| 1915 |
| 1916 for (CookieList::const_iterator it = list.begin(); it != list.end(); ++it) { |
| 1917 scoped_ptr<CanonicalCookie> canonical_cookie(new CanonicalCookie(*it)); |
| 1918 if (!SetCanonicalCookie(&canonical_cookie, it->CreationDate(), options)) |
| 1919 return false; |
| 1920 } |
| 1921 |
| 1922 return true; |
| 1923 } |
| 1924 |
1846 void CookieMonster::InternalUpdateCookieAccessTime(CanonicalCookie* cc, | 1925 void CookieMonster::InternalUpdateCookieAccessTime(CanonicalCookie* cc, |
1847 const Time& current) { | 1926 const Time& current) { |
1848 lock_.AssertAcquired(); | 1927 lock_.AssertAcquired(); |
1849 | 1928 |
1850 // Based off the Mozilla code. When a cookie has been accessed recently, | 1929 // 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 | 1930 // 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 | 1931 // 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. | 1932 // backend will hit its batch thresholds and be forced to update. |
1854 if ((current - cc->LastAccessDate()) < last_access_threshold_) | 1933 if ((current - cc->LastAccessDate()) < last_access_threshold_) |
1855 return; | 1934 return; |
(...skipping 363 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2219 } | 2298 } |
2220 | 2299 |
2221 // The system resolution is not high enough, so we can have multiple | 2300 // 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 | 2301 // 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. | 2302 // increment by one Time unit. Let's hope computers don't get too fast. |
2224 Time CookieMonster::CurrentTime() { | 2303 Time CookieMonster::CurrentTime() { |
2225 return std::max(Time::Now(), Time::FromInternalValue( | 2304 return std::max(Time::Now(), Time::FromInternalValue( |
2226 last_time_seen_.ToInternalValue() + 1)); | 2305 last_time_seen_.ToInternalValue() + 1)); |
2227 } | 2306 } |
2228 | 2307 |
| 2308 void CookieMonster::ComputeCookieDiff(CookieList* old_cookies, |
| 2309 CookieList* new_cookies, |
| 2310 CookieList* cookies_to_add, |
| 2311 CookieList* cookies_to_delete) { |
| 2312 DCHECK(old_cookies); |
| 2313 DCHECK(new_cookies); |
| 2314 DCHECK(cookies_to_add); |
| 2315 DCHECK(cookies_to_delete); |
| 2316 DCHECK(cookies_to_add->empty()); |
| 2317 DCHECK(cookies_to_delete->empty()); |
| 2318 |
| 2319 // Sort both lists. |
| 2320 // A set ordered by FullDiffCookieSorter is also ordered by |
| 2321 // PartialDiffCookieSorter. |
| 2322 std::sort(old_cookies->begin(), old_cookies->end(), FullDiffCookieSorter); |
| 2323 std::sort(new_cookies->begin(), new_cookies->end(), FullDiffCookieSorter); |
| 2324 |
| 2325 // Select any old cookie for deletion if no new cookie has the same name, |
| 2326 // domain, and path. |
| 2327 std::set_difference( |
| 2328 old_cookies->begin(), old_cookies->end(), new_cookies->begin(), |
| 2329 new_cookies->end(), |
| 2330 std::inserter(*cookies_to_delete, cookies_to_delete->begin()), |
| 2331 PartialDiffCookieSorter); |
| 2332 |
| 2333 // Select any new cookie for addition (or update) if no old cookie is exactly |
| 2334 // equivalent. |
| 2335 std::set_difference(new_cookies->begin(), new_cookies->end(), |
| 2336 old_cookies->begin(), old_cookies->end(), |
| 2337 std::inserter(*cookies_to_add, cookies_to_add->begin()), |
| 2338 FullDiffCookieSorter); |
| 2339 } |
| 2340 |
2229 scoped_ptr<CookieStore::CookieChangedSubscription> | 2341 scoped_ptr<CookieStore::CookieChangedSubscription> |
2230 CookieMonster::AddCallbackForCookie(const GURL& gurl, | 2342 CookieMonster::AddCallbackForCookie(const GURL& gurl, |
2231 const std::string& name, | 2343 const std::string& name, |
2232 const CookieChangedCallback& callback) { | 2344 const CookieChangedCallback& callback) { |
2233 base::AutoLock autolock(lock_); | 2345 base::AutoLock autolock(lock_); |
2234 std::pair<GURL, std::string> key(gurl, name); | 2346 std::pair<GURL, std::string> key(gurl, name); |
2235 if (hook_map_.count(key) == 0) | 2347 if (hook_map_.count(key) == 0) |
2236 hook_map_[key] = make_linked_ptr(new CookieChangedCallbackList()); | 2348 hook_map_[key] = make_linked_ptr(new CookieChangedCallbackList()); |
2237 return hook_map_[key]->Add( | 2349 return hook_map_[key]->Add( |
2238 base::Bind(&RunAsync, base::MessageLoopProxy::current(), callback)); | 2350 base::Bind(&RunAsync, base::MessageLoopProxy::current(), callback)); |
(...skipping 13 matching lines...) Expand all Loading... |
2252 it != hook_map_.end(); ++it) { | 2364 it != hook_map_.end(); ++it) { |
2253 std::pair<GURL, std::string> key = it->first; | 2365 std::pair<GURL, std::string> key = it->first; |
2254 if (cookie.IncludeForRequestURL(key.first, opts) && | 2366 if (cookie.IncludeForRequestURL(key.first, opts) && |
2255 cookie.Name() == key.second) { | 2367 cookie.Name() == key.second) { |
2256 it->second->Notify(cookie, removed); | 2368 it->second->Notify(cookie, removed); |
2257 } | 2369 } |
2258 } | 2370 } |
2259 } | 2371 } |
2260 | 2372 |
2261 } // namespace net | 2373 } // namespace net |
OLD | NEW |