Chromium Code Reviews| Index: net/cookies/cookie_monster.cc |
| diff --git a/net/cookies/cookie_monster.cc b/net/cookies/cookie_monster.cc |
| index 6947756a30db9d1cb90b3c5860df2742148c264a..f68f0c9b37c58fdd61f5801cbeaf8338bb9ae85f 100644 |
| --- a/net/cookies/cookie_monster.cc |
| +++ b/net/cookies/cookie_monster.cc |
| @@ -163,6 +163,53 @@ bool LRACookieSorter(const CookieMonster::CookieMap::iterator& it1, |
| return it1->second->CreationDate() < it2->second->CreationDate(); |
| } |
| +// Compare cookies using name, domain and path, so that "equivalent" cookies |
| +// (per RFC 2965) are equal to each other. |
| +int PartialDiffCookieOrdering(const net::CanonicalCookie& a, |
| + const net::CanonicalCookie& b) { |
| + int diff = a.Name().compare(b.Name()); |
| + if (diff != 0) |
| + return diff; |
| + |
| + diff = a.Domain().compare(b.Domain()); |
| + if (diff != 0) |
| + return diff; |
| + |
| + return a.Path().compare(b.Path()); |
| +} |
| + |
| +bool PartialDiffCookieSorter(const net::CanonicalCookie& a, |
| + const net::CanonicalCookie& b) { |
| + return PartialDiffCookieOrdering(a, b) < 0; |
| +} |
| + |
| +// This is a stricter ordering than PartialDiffCookieOrdering, where all fields |
| +// are used except the last access time and the creation date. |
| +bool FullDiffCookieSorter(const net::CanonicalCookie& a, |
| + const net::CanonicalCookie& b) { |
| + int diff = PartialDiffCookieOrdering(a, b); |
| + if (diff != 0) |
| + return diff < 0; |
| + |
| + DCHECK(a.IsEquivalent(b)); |
| + |
| + // Compare other fields. |
| + diff = a.Value().compare(b.Value()); |
| + if (diff != 0) |
| + return diff < 0; |
| + |
| + if (a.ExpiryDate() != b.ExpiryDate()) |
| + return a.ExpiryDate() < b.ExpiryDate(); |
| + |
| + if (a.IsSecure() != b.IsSecure()) |
| + return a.IsSecure(); |
| + |
| + if (a.IsHttpOnly() != b.IsHttpOnly()) |
| + return a.IsHttpOnly(); |
| + |
| + return a.Priority() < b.Priority(); |
| +} |
| + |
| // Our strategy to find duplicates is: |
| // (1) Build a map from (cookiename, cookiepath) to |
| // {list of cookies with this signature, sorted by creation time}. |
| @@ -764,6 +811,49 @@ void CookieMonster::SetCookieWithOptionsTask::Run() { |
| } |
| } |
| +// Task class for SetAllCookies call. |
| +class CookieMonster::SetAllCookiesTask : public CookieMonsterTask { |
| + public: |
| + SetAllCookiesTask(CookieMonster* cookie_monster, |
| + const CookieList& list, |
| + const SetCookiesCallback& callback) |
| + : CookieMonsterTask(cookie_monster), list_(list), callback_(callback) {} |
| + |
| + // CookieMonsterTask: |
| + void Run() override; |
| + |
| + protected: |
| + ~SetAllCookiesTask() override {} |
| + |
| + private: |
| + CookieList list_; |
| + SetCookiesCallback callback_; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(SetAllCookiesTask); |
| +}; |
| + |
| +void CookieMonster::SetAllCookiesTask::Run() { |
| + CookieList positive_diff; |
| + CookieList negative_diff; |
| + CookieList old_cookies = this->cookie_monster()->GetAllCookies(); |
| + this->cookie_monster()->ComputeCookieDiff(&old_cookies, &list_, |
| + &positive_diff, &negative_diff); |
| + |
| + for (CookieList::const_iterator it = negative_diff.begin(); |
| + it != negative_diff.end(); ++it) { |
| + this->cookie_monster()->DeleteCanonicalCookie(*it); |
| + } |
| + |
| + bool result = true; |
| + if (positive_diff.size() > 0) |
| + result = this->cookie_monster()->SetCanonicalCookies(list_); |
| + |
| + if (!callback_.is_null()) { |
| + this->InvokeCallback(base::Bind(&SetCookiesCallback::Run, |
| + base::Unretained(&callback_), result)); |
| + } |
| +} |
| + |
| // Task class for GetCookiesWithOptions call. |
| class CookieMonster::GetCookiesWithOptionsTask : public CookieMonsterTask { |
| public: |
| @@ -985,6 +1075,13 @@ void CookieMonster::DeleteCanonicalCookieAsync( |
| DoCookieTask(task); |
| } |
| +void CookieMonster::SetAllCookiesAsync(const CookieList& list, |
| + const SetCookiesCallback& callback) { |
| + scoped_refptr<SetAllCookiesTask> task = |
| + new SetAllCookiesTask(this, list, callback); |
| + DoCookieTask(task); |
| +} |
| + |
| void CookieMonster::SetCookieWithOptionsAsync( |
| const GURL& url, |
| const std::string& cookie_line, |
| @@ -1843,6 +1940,21 @@ bool CookieMonster::SetCanonicalCookie(scoped_ptr<CanonicalCookie>* cc, |
| return true; |
| } |
| +bool CookieMonster::SetCanonicalCookies(const CookieList& list) { |
| + base::AutoLock autolock(lock_); |
| + |
| + net::CookieOptions options; |
| + options.set_include_httponly(); |
| + |
| + for (CookieList::const_iterator it = list.begin(); it != list.end(); ++it) { |
| + scoped_ptr<CanonicalCookie> canonical_cookie(new CanonicalCookie(*it)); |
| + if (!SetCanonicalCookie(&canonical_cookie, it->CreationDate(), options)) |
| + return false; |
| + } |
| + |
| + return true; |
| +} |
| + |
| void CookieMonster::InternalUpdateCookieAccessTime(CanonicalCookie* cc, |
| const Time& current) { |
| lock_.AssertAcquired(); |
| @@ -2226,6 +2338,37 @@ Time CookieMonster::CurrentTime() { |
| last_time_seen_.ToInternalValue() + 1)); |
| } |
| +void CookieMonster::ComputeCookieDiff(CookieList* old_cookies, |
| + CookieList* new_cookies, |
| + CookieList* cookies_to_add, |
| + CookieList* cookies_to_delete) { |
| + DCHECK(old_cookies); |
| + DCHECK(new_cookies); |
| + DCHECK(cookies_to_add); |
| + DCHECK(cookies_to_delete); |
| + DCHECK(cookies_to_add->empty()); |
| + DCHECK(cookies_to_delete->empty()); |
| + |
| + // Sort both lists. |
| + std::sort(old_cookies->begin(), old_cookies->end(), FullDiffCookieSorter); |
| + std::sort(new_cookies->begin(), new_cookies->end(), FullDiffCookieSorter); |
| + |
| + // Compute the cookies to be deleted. |
| + // 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::
|
| + // the list was sorted using FullDiffCookieSorter. |
| + 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.
|
| + old_cookies->begin(), old_cookies->end(), new_cookies->begin(), |
| + new_cookies->end(), |
| + std::inserter(*cookies_to_delete, cookies_to_delete->begin()), |
| + PartialDiffCookieSorter); |
| + |
| + // Compute the cookies to be added. |
| + 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.
|
| + old_cookies->begin(), old_cookies->end(), |
| + std::inserter(*cookies_to_add, cookies_to_add->begin()), |
| + FullDiffCookieSorter); |
| +} |
| + |
| scoped_ptr<CookieStore::CookieChangedSubscription> |
| CookieMonster::AddCallbackForCookie(const GURL& gurl, |
| const std::string& name, |