| Index: net/cookies/cookie_monster.cc
|
| diff --git a/net/cookies/cookie_monster.cc b/net/cookies/cookie_monster.cc
|
| index 6947756a30db9d1cb90b3c5860df2742148c264a..aa39b608b8bb5ed8db616b2ab38fe0e5e9e48047 100644
|
| --- a/net/cookies/cookie_monster.cc
|
| +++ b/net/cookies/cookie_monster.cc
|
| @@ -163,6 +163,20 @@ 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.
|
| +bool PartialDiffCookieSorter(const net::CanonicalCookie& a,
|
| + const net::CanonicalCookie& b) {
|
| + return a.PartialCompare(b);
|
| +}
|
| +
|
| +// This is a stricter ordering than PartialDiffCookieOrdering, where all fields
|
| +// are used.
|
| +bool FullDiffCookieSorter(const net::CanonicalCookie& a,
|
| + const net::CanonicalCookie& b) {
|
| + return a.FullCompare(b);
|
| +}
|
| +
|
| // 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 +778,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 +1042,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 +1907,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 +2305,39 @@ 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.
|
| + // A set ordered by FullDiffCookieSorter is also ordered by
|
| + // PartialDiffCookieSorter.
|
| + std::sort(old_cookies->begin(), old_cookies->end(), FullDiffCookieSorter);
|
| + std::sort(new_cookies->begin(), new_cookies->end(), FullDiffCookieSorter);
|
| +
|
| + // Select any old cookie for deletion if no new cookie has the same name,
|
| + // domain, and path.
|
| + std::set_difference(
|
| + old_cookies->begin(), old_cookies->end(), new_cookies->begin(),
|
| + new_cookies->end(),
|
| + std::inserter(*cookies_to_delete, cookies_to_delete->begin()),
|
| + PartialDiffCookieSorter);
|
| +
|
| + // Select any new cookie for addition (or update) if no old cookie is exactly
|
| + // equivalent.
|
| + std::set_difference(new_cookies->begin(), new_cookies->end(),
|
| + 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,
|
|
|