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 |