blob: b01599923ef13e75072f8c9479366916605f4d96 [file] [log] [blame]
[email protected]8e1583672012-02-11 04:39:411// Copyright (c) 2012 The Chromium Authors. All rights reserved.
license.botbf09a502008-08-24 00:55:552// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
initial.commit586acc5fe2008-07-26 22:42:524
5// Portions of this code based on Mozilla:
6// (netwerk/cookie/src/nsCookieService.cpp)
7/* ***** BEGIN LICENSE BLOCK *****
8 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
9 *
10 * The contents of this file are subject to the Mozilla Public License Version
11 * 1.1 (the "License"); you may not use this file except in compliance with
12 * the License. You may obtain a copy of the License at
13 * http://www.mozilla.org/MPL/
14 *
15 * Software distributed under the License is distributed on an "AS IS" basis,
16 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
17 * for the specific language governing rights and limitations under the
18 * License.
19 *
20 * The Original Code is mozilla.org code.
21 *
22 * The Initial Developer of the Original Code is
23 * Netscape Communications Corporation.
24 * Portions created by the Initial Developer are Copyright (C) 2003
25 * the Initial Developer. All Rights Reserved.
26 *
27 * Contributor(s):
28 * Daniel Witte ([email protected])
29 * Michiel van Leeuwen ([email protected])
30 *
31 * Alternatively, the contents of this file may be used under the terms of
32 * either the GNU General Public License Version 2 or later (the "GPL"), or
33 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
34 * in which case the provisions of the GPL or the LGPL are applicable instead
35 * of those above. If you wish to allow use of your version of this file only
36 * under the terms of either the GPL or the LGPL, and not to allow others to
37 * use your version of this file under the terms of the MPL, indicate your
38 * decision by deleting the provisions above and replace them with the notice
39 * and other provisions required by the GPL or the LGPL. If you do not delete
40 * the provisions above, a recipient may use your version of this file under
41 * the terms of any one of the MPL, the GPL or the LGPL.
42 *
43 * ***** END LICENSE BLOCK ***** */
44
[email protected]63ee33bd2012-03-15 09:29:5845#include "net/cookies/cookie_monster.h"
initial.commit586acc5fe2008-07-26 22:42:5246
47#include <algorithm>
[email protected]8ad5d462013-05-02 08:45:2648#include <functional>
danakja9850e12016-04-18 22:28:0849#include <memory>
[email protected]09666482011-07-12 12:50:4050#include <set>
initial.commit586acc5fe2008-07-26 22:42:5251
[email protected]218aa6a12011-09-13 17:38:3852#include "base/bind.h"
[email protected]85620342011-10-17 17:35:0453#include "base/callback.h"
skyostil4891b25b2015-06-11 11:43:4554#include "base/location.h"
initial.commit586acc5fe2008-07-26 22:42:5255#include "base/logging.h"
Avi Drissman13fc8932015-12-20 04:40:4656#include "base/macros.h"
danakja9850e12016-04-18 22:28:0857#include "base/memory/ptr_util.h"
erikchen1dd72a72015-05-06 20:45:0558#include "base/metrics/field_trial.h"
[email protected]835d7c82010-10-14 04:38:3859#include "base/metrics/histogram.h"
pkastingb60049a2015-02-07 03:25:2560#include "base/profiler/scoped_tracker.h"
anujk.sharmaafc45172015-05-15 00:50:3461#include "base/single_thread_task_runner.h"
[email protected]4b355212013-06-11 10:35:1962#include "base/strings/string_util.h"
63#include "base/strings/stringprintf.h"
gabf767595f2016-05-11 18:50:3564#include "base/threading/thread_task_runner_handle.h"
[email protected]be28b5f42012-07-20 11:31:2565#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
[email protected]4b355212013-06-11 10:35:1966#include "net/cookies/canonical_cookie.h"
[email protected]63ee33bd2012-03-15 09:29:5867#include "net/cookies/cookie_util.h"
[email protected]ebfe3172012-07-12 12:21:4168#include "net/cookies/parsed_cookie.h"
nharper2b0ad9a2017-05-22 18:33:4569#include "net/ssl/channel_id_service.h"
mkwst8241a122015-10-20 07:15:1070#include "url/origin.h"
initial.commit586acc5fe2008-07-26 22:42:5271
[email protected]e1acf6f2008-10-27 20:43:3372using base::Time;
73using base::TimeDelta;
[email protected]7a964a72010-09-07 19:33:2674using base::TimeTicks;
[email protected]e1acf6f2008-10-27 20:43:3375
[email protected]85620342011-10-17 17:35:0476// In steady state, most cookie requests can be satisfied by the in memory
erikchen1dd72a72015-05-06 20:45:0577// cookie monster store. If the cookie request cannot be satisfied by the in
78// memory store, the relevant cookies must be fetched from the persistent
79// store. The task is queued in CookieMonster::tasks_pending_ if it requires
80// all cookies to be loaded from the backend, or tasks_pending_for_key_ if it
81// only requires all cookies associated with an eTLD+1.
[email protected]85620342011-10-17 17:35:0482//
83// On the browser critical paths (e.g. for loading initial web pages in a
84// session restore) it may take too long to wait for the full load. If a cookie
85// request is for a specific URL, DoCookieTaskForURL is called, which triggers a
86// priority load if the key is not loaded yet by calling PersistentCookieStore
[email protected]0184df32013-05-14 00:53:5587// :: LoadCookiesForKey. The request is queued in
88// CookieMonster::tasks_pending_for_key_ and executed upon receiving
89// notification of key load completion via CookieMonster::OnKeyLoaded(). If
90// multiple requests for the same eTLD+1 are received before key load
91// completion, only the first request calls
[email protected]85620342011-10-17 17:35:0492// PersistentCookieStore::LoadCookiesForKey, all subsequent requests are queued
[email protected]0184df32013-05-14 00:53:5593// in CookieMonster::tasks_pending_for_key_ and executed upon receiving
94// notification of key load completion triggered by the first request for the
95// same eTLD+1.
[email protected]85620342011-10-17 17:35:0496
[email protected]c4058fb2010-06-22 17:25:2697static const int kMinutesInTenYears = 10 * 365 * 24 * 60;
98
erikchen1dd72a72015-05-06 20:45:0599namespace {
100
101const char kFetchWhenNecessaryName[] = "FetchWhenNecessary";
102const char kAlwaysFetchName[] = "AlwaysFetch";
103const char kCookieMonsterFetchStrategyName[] = "CookieMonsterFetchStrategy";
104
105} // namespace
106
[email protected]8ac1a752008-07-31 19:40:37107namespace net {
108
[email protected]7a964a72010-09-07 19:33:26109// See comments at declaration of these variables in cookie_monster.h
110// for details.
mkwstbe84af312015-02-20 08:52:45111const size_t CookieMonster::kDomainMaxCookies = 180;
112const size_t CookieMonster::kDomainPurgeCookies = 30;
113const size_t CookieMonster::kMaxCookies = 3300;
114const size_t CookieMonster::kPurgeCookies = 300;
[email protected]8ad5d462013-05-02 08:45:26115
mkwst87734352016-03-03 17:36:23116const size_t CookieMonster::kDomainCookiesQuotaLow = 30;
117const size_t CookieMonster::kDomainCookiesQuotaMedium = 50;
118const size_t CookieMonster::kDomainCookiesQuotaHigh =
119 kDomainMaxCookies - kDomainPurgeCookies - kDomainCookiesQuotaLow -
120 kDomainCookiesQuotaMedium;
[email protected]8ad5d462013-05-02 08:45:26121
mkwstbe84af312015-02-20 08:52:45122const int CookieMonster::kSafeFromGlobalPurgeDays = 30;
[email protected]297a4ed02010-02-12 08:12:52123
[email protected]7a964a72010-09-07 19:33:26124namespace {
[email protected]e32306c52008-11-06 16:59:05125
[email protected]6210ce52013-09-20 03:33:14126bool ContainsControlCharacter(const std::string& s) {
127 for (std::string::const_iterator i = s.begin(); i != s.end(); ++i) {
128 if ((*i >= 0) && (*i <= 31))
129 return true;
130 }
131
132 return false;
133}
134
[email protected]5b9bc352012-07-18 13:13:34135typedef std::vector<CanonicalCookie*> CanonicalCookieVector;
[email protected]34a160d2011-05-12 22:12:49136
[email protected]77e0a462008-11-01 00:43:35137// Default minimum delay after updating a cookie's LastAccessDate before we
138// will update it again.
[email protected]297a4ed02010-02-12 08:12:52139const int kDefaultAccessUpdateThresholdSeconds = 60;
140
141// Comparator to sort cookies from highest creation date to lowest
142// creation date.
143struct OrderByCreationTimeDesc {
144 bool operator()(const CookieMonster::CookieMap::iterator& a,
145 const CookieMonster::CookieMap::iterator& b) const {
146 return a->second->CreationDate() > b->second->CreationDate();
147 }
148};
149
[email protected]4d3ce782010-10-29 18:31:28150// Constants for use in VLOG
151const int kVlogPerCookieMonster = 1;
[email protected]4d3ce782010-10-29 18:31:28152const int kVlogGarbageCollection = 5;
153const int kVlogSetCookies = 7;
154const int kVlogGetCookies = 9;
155
[email protected]f48b9432011-01-11 07:25:40156// Mozilla sorts on the path length (longest first), and then it
157// sorts by creation time (oldest first).
158// The RFC says the sort order for the domain attribute is undefined.
[email protected]5b9bc352012-07-18 13:13:34159bool CookieSorter(CanonicalCookie* cc1, CanonicalCookie* cc2) {
[email protected]f48b9432011-01-11 07:25:40160 if (cc1->Path().length() == cc2->Path().length())
161 return cc1->CreationDate() < cc2->CreationDate();
162 return cc1->Path().length() > cc2->Path().length();
initial.commit586acc5fe2008-07-26 22:42:52163}
164
[email protected]8ad5d462013-05-02 08:45:26165bool LRACookieSorter(const CookieMonster::CookieMap::iterator& it1,
[email protected]f48b9432011-01-11 07:25:40166 const CookieMonster::CookieMap::iterator& it2) {
[email protected]f48b9432011-01-11 07:25:40167 if (it1->second->LastAccessDate() != it2->second->LastAccessDate())
168 return it1->second->LastAccessDate() < it2->second->LastAccessDate();
initial.commit586acc5fe2008-07-26 22:42:52169
mkwste079ac412016-03-11 09:04:06170 // Ensure stability for == last access times by falling back to creation.
[email protected]f48b9432011-01-11 07:25:40171 return it1->second->CreationDate() < it2->second->CreationDate();
[email protected]297a4ed02010-02-12 08:12:52172}
173
drogerd5d1278c2015-03-17 19:21:51174// Compare cookies using name, domain and path, so that "equivalent" cookies
175// (per RFC 2965) are equal to each other.
ttuttle859dc7a2015-04-23 19:42:29176bool PartialDiffCookieSorter(const CanonicalCookie& a,
177 const CanonicalCookie& b) {
drogerd5d1278c2015-03-17 19:21:51178 return a.PartialCompare(b);
179}
180
181// This is a stricter ordering than PartialDiffCookieOrdering, where all fields
182// are used.
ttuttle859dc7a2015-04-23 19:42:29183bool FullDiffCookieSorter(const CanonicalCookie& a, const CanonicalCookie& b) {
drogerd5d1278c2015-03-17 19:21:51184 return a.FullCompare(b);
185}
186
[email protected]297a4ed02010-02-12 08:12:52187// Our strategy to find duplicates is:
188// (1) Build a map from (cookiename, cookiepath) to
189// {list of cookies with this signature, sorted by creation time}.
190// (2) For each list with more than 1 entry, keep the cookie having the
191// most recent creation time, and delete the others.
[email protected]f48b9432011-01-11 07:25:40192//
[email protected]1655ba342010-07-14 18:17:42193// Two cookies are considered equivalent if they have the same domain,
194// name, and path.
195struct CookieSignature {
196 public:
[email protected]dedec0b2013-02-28 04:50:10197 CookieSignature(const std::string& name,
198 const std::string& domain,
[email protected]1655ba342010-07-14 18:17:42199 const std::string& path)
mkwstbe84af312015-02-20 08:52:45200 : name(name), domain(domain), path(path) {}
[email protected]1655ba342010-07-14 18:17:42201
202 // To be a key for a map this class needs to be assignable, copyable,
203 // and have an operator<. The default assignment operator
204 // and copy constructor are exactly what we want.
205
206 bool operator<(const CookieSignature& cs) const {
207 // Name compare dominates, then domain, then path.
208 int diff = name.compare(cs.name);
209 if (diff != 0)
210 return diff < 0;
211
212 diff = domain.compare(cs.domain);
213 if (diff != 0)
214 return diff < 0;
215
216 return path.compare(cs.path) < 0;
217 }
218
219 std::string name;
220 std::string domain;
221 std::string path;
222};
[email protected]f48b9432011-01-11 07:25:40223
[email protected]8ad5d462013-05-02 08:45:26224// For a CookieItVector iterator range [|it_begin|, |it_end|),
mmenkef4721d992017-06-07 17:13:59225// sorts the first |num_sort| elements by LastAccessDate().
mkwstbe84af312015-02-20 08:52:45226void SortLeastRecentlyAccessed(CookieMonster::CookieItVector::iterator it_begin,
227 CookieMonster::CookieItVector::iterator it_end,
228 size_t num_sort) {
mmenkef4721d992017-06-07 17:13:59229 DCHECK_LE(static_cast<int>(num_sort), it_end - it_begin);
230 std::partial_sort(it_begin, it_begin + num_sort, it_end, LRACookieSorter);
[email protected]8ad5d462013-05-02 08:45:26231}
[email protected]f48b9432011-01-11 07:25:40232
jww82d99c12015-11-25 18:39:53233// Given a single cookie vector |cookie_its|, pushs all of the secure cookies in
234// |cookie_its| into |secure_cookie_its| and all of the non-secure cookies into
235// |non_secure_cookie_its|. Both |secure_cookie_its| and |non_secure_cookie_its|
236// must be non-NULL.
237void SplitCookieVectorIntoSecureAndNonSecure(
238 const CookieMonster::CookieItVector& cookie_its,
239 CookieMonster::CookieItVector* secure_cookie_its,
240 CookieMonster::CookieItVector* non_secure_cookie_its) {
241 DCHECK(secure_cookie_its && non_secure_cookie_its);
242 for (const auto& curit : cookie_its) {
243 if (curit->second->IsSecure())
244 secure_cookie_its->push_back(curit);
245 else
246 non_secure_cookie_its->push_back(curit);
247 }
248}
249
mkwstbe84af312015-02-20 08:52:45250bool LowerBoundAccessDateComparator(const CookieMonster::CookieMap::iterator it,
251 const Time& access_date) {
[email protected]8ad5d462013-05-02 08:45:26252 return it->second->LastAccessDate() < access_date;
253}
254
255// For a CookieItVector iterator range [|it_begin|, |it_end|)
256// from a CookieItVector sorted by LastAccessDate(), returns the
257// first iterator with access date >= |access_date|, or cookie_its_end if this
258// holds for all.
259CookieMonster::CookieItVector::iterator LowerBoundAccessDate(
260 const CookieMonster::CookieItVector::iterator its_begin,
261 const CookieMonster::CookieItVector::iterator its_end,
262 const Time& access_date) {
263 return std::lower_bound(its_begin, its_end, access_date,
264 LowerBoundAccessDateComparator);
[email protected]7a964a72010-09-07 19:33:26265}
266
nharper352933e2016-09-30 18:24:57267// Mapping between DeletionCause and CookieStore::ChangeCause; the
[email protected]7c4b66b2014-01-04 12:28:13268// mapping also provides a boolean that specifies whether or not an
269// OnCookieChanged notification ought to be generated.
[email protected]8bb846f2011-03-23 12:08:18270typedef struct ChangeCausePair_struct {
nharper352933e2016-09-30 18:24:57271 CookieStore::ChangeCause cause;
[email protected]8bb846f2011-03-23 12:08:18272 bool notify;
273} ChangeCausePair;
nharper352933e2016-09-30 18:24:57274const ChangeCausePair kChangeCauseMapping[] = {
mkwstbe84af312015-02-20 08:52:45275 // DELETE_COOKIE_EXPLICIT
nharper68903362017-01-20 04:07:14276 {CookieStore::ChangeCause::EXPLICIT, true},
mkwstbe84af312015-02-20 08:52:45277 // DELETE_COOKIE_OVERWRITE
nharper352933e2016-09-30 18:24:57278 {CookieStore::ChangeCause::OVERWRITE, true},
mkwstbe84af312015-02-20 08:52:45279 // DELETE_COOKIE_EXPIRED
nharper352933e2016-09-30 18:24:57280 {CookieStore::ChangeCause::EXPIRED, true},
mkwstbe84af312015-02-20 08:52:45281 // DELETE_COOKIE_EVICTED
nharper352933e2016-09-30 18:24:57282 {CookieStore::ChangeCause::EVICTED, true},
mkwstbe84af312015-02-20 08:52:45283 // DELETE_COOKIE_DUPLICATE_IN_BACKING_STORE
nharper68903362017-01-20 04:07:14284 {CookieStore::ChangeCause::EXPLICIT, false},
mkwstbe84af312015-02-20 08:52:45285 // DELETE_COOKIE_DONT_RECORD
nharper68903362017-01-20 04:07:14286 {CookieStore::ChangeCause::EXPLICIT, false},
mkwstbe84af312015-02-20 08:52:45287 // DELETE_COOKIE_EVICTED_DOMAIN
nharper352933e2016-09-30 18:24:57288 {CookieStore::ChangeCause::EVICTED, true},
mkwstbe84af312015-02-20 08:52:45289 // DELETE_COOKIE_EVICTED_GLOBAL
nharper352933e2016-09-30 18:24:57290 {CookieStore::ChangeCause::EVICTED, true},
mkwstbe84af312015-02-20 08:52:45291 // DELETE_COOKIE_EVICTED_DOMAIN_PRE_SAFE
nharper352933e2016-09-30 18:24:57292 {CookieStore::ChangeCause::EVICTED, true},
mkwstbe84af312015-02-20 08:52:45293 // DELETE_COOKIE_EVICTED_DOMAIN_POST_SAFE
nharper352933e2016-09-30 18:24:57294 {CookieStore::ChangeCause::EVICTED, true},
mkwstbe84af312015-02-20 08:52:45295 // DELETE_COOKIE_EXPIRED_OVERWRITE
nharper352933e2016-09-30 18:24:57296 {CookieStore::ChangeCause::EXPIRED_OVERWRITE, true},
mkwstbe84af312015-02-20 08:52:45297 // DELETE_COOKIE_CONTROL_CHAR
nharper352933e2016-09-30 18:24:57298 {CookieStore::ChangeCause::EVICTED, true},
jww82d99c12015-11-25 18:39:53299 // DELETE_COOKIE_NON_SECURE
nharper352933e2016-09-30 18:24:57300 {CookieStore::ChangeCause::EVICTED, true},
nharper68903362017-01-20 04:07:14301 // DELETE_COOKIE_CREATED_BETWEEN
302 {CookieStore::ChangeCause::EXPLICIT_DELETE_BETWEEN, true},
303 // DELETE_COOKIE_CREATED_BETWEEN_WITH_PREDICATE
304 {CookieStore::ChangeCause::EXPLICIT_DELETE_PREDICATE, true},
305 // DELETE_COOKIE_SINGLE
306 {CookieStore::ChangeCause::EXPLICIT_DELETE_SINGLE, true},
307 // DELETE_COOKIE_CANONICAL
308 {CookieStore::ChangeCause::EXPLICIT_DELETE_CANONICAL, true},
mkwstbe84af312015-02-20 08:52:45309 // DELETE_COOKIE_LAST_ENTRY
nharper68903362017-01-20 04:07:14310 {CookieStore::ChangeCause::EXPLICIT, false}};
[email protected]8bb846f2011-03-23 12:08:18311
ellyjones399e35a22014-10-27 11:09:56312void RunAsync(scoped_refptr<base::TaskRunner> proxy,
msarda0aad8f02014-10-30 09:22:39313 const CookieStore::CookieChangedCallback& callback,
314 const CanonicalCookie& cookie,
nharper352933e2016-09-30 18:24:57315 CookieStore::ChangeCause cause) {
316 proxy->PostTask(FROM_HERE, base::Bind(callback, cookie, cause));
ellyjones399e35a22014-10-27 11:09:56317}
318
jwwc00ac712016-05-05 22:21:44319bool IsCookieEligibleForEviction(CookiePriority current_priority_level,
320 bool protect_secure_cookies,
321 const CanonicalCookie* cookie) {
mmenke645ca6772016-06-17 18:46:43322 if (cookie->Priority() == current_priority_level && protect_secure_cookies)
323 return !cookie->IsSecure();
jwwc00ac712016-05-05 22:21:44324
mmenke645ca6772016-06-17 18:46:43325 return cookie->Priority() == current_priority_level;
326}
jwwc00ac712016-05-05 22:21:44327
mmenke645ca6772016-06-17 18:46:43328size_t CountCookiesForPossibleDeletion(
329 CookiePriority priority,
330 const CookieMonster::CookieItVector* cookies,
331 bool protect_secure_cookies) {
332 size_t cookies_count = 0U;
333 for (const auto& cookie : *cookies) {
334 if (cookie->second->Priority() == priority) {
335 if (!protect_secure_cookies || cookie->second->IsSecure())
336 cookies_count++;
337 }
338 }
339 return cookies_count;
jwwc00ac712016-05-05 22:21:44340}
341
[email protected]f48b9432011-01-11 07:25:40342} // namespace
343
[email protected]7c4b66b2014-01-04 12:28:13344CookieMonster::CookieMonster(PersistentCookieStore* store,
345 CookieMonsterDelegate* delegate)
shessf0bc1182016-05-19 04:35:58346 : CookieMonster(
347 store,
348 delegate,
nharper2b0ad9a2017-05-22 18:33:45349 nullptr,
shessf0bc1182016-05-19 04:35:58350 base::TimeDelta::FromSeconds(kDefaultAccessUpdateThresholdSeconds)) {}
[email protected]2d0f89a2010-12-06 12:02:23351
[email protected]f48b9432011-01-11 07:25:40352CookieMonster::CookieMonster(PersistentCookieStore* store,
[email protected]7c4b66b2014-01-04 12:28:13353 CookieMonsterDelegate* delegate,
nharper2b0ad9a2017-05-22 18:33:45354 ChannelIDService* channel_id_service)
355 : CookieMonster(
356 store,
357 delegate,
358 channel_id_service,
359 base::TimeDelta::FromSeconds(kDefaultAccessUpdateThresholdSeconds)) {}
360
361CookieMonster::CookieMonster(PersistentCookieStore* store,
362 CookieMonsterDelegate* delegate,
363 base::TimeDelta last_access_threshold)
364 : CookieMonster(store, delegate, nullptr, last_access_threshold) {}
365
366CookieMonster::CookieMonster(PersistentCookieStore* store,
367 CookieMonsterDelegate* delegate,
368 ChannelIDService* channel_id_service,
shessf0bc1182016-05-19 04:35:58369 base::TimeDelta last_access_threshold)
[email protected]f48b9432011-01-11 07:25:40370 : initialized_(false),
erikchen1dd72a72015-05-06 20:45:05371 started_fetching_all_cookies_(false),
372 finished_fetching_all_cookies_(false),
373 fetch_strategy_(kUnknownFetch),
mmenkef49fca0e2016-03-08 12:46:24374 seen_global_task_(false),
[email protected]f48b9432011-01-11 07:25:40375 store_(store),
shessf0bc1182016-05-19 04:35:58376 last_access_threshold_(last_access_threshold),
[email protected]f48b9432011-01-11 07:25:40377 delegate_(delegate),
nharper2b0ad9a2017-05-22 18:33:45378 channel_id_service_(channel_id_service),
[email protected]82388662011-03-10 21:04:06379 last_statistic_record_time_(base::Time::Now()),
mmenkebe0910d2016-03-01 19:09:09380 persist_session_cookies_(false),
381 weak_ptr_factory_(this) {
[email protected]f48b9432011-01-11 07:25:40382 InitializeHistograms();
mmenke18dd8ba2016-02-01 18:42:10383 cookieable_schemes_.insert(
384 cookieable_schemes_.begin(), kDefaultCookieableSchemes,
385 kDefaultCookieableSchemes + kDefaultCookieableSchemesCount);
initial.commit586acc5fe2008-07-26 22:42:52386}
387
[email protected]218aa6a12011-09-13 17:38:38388// Task classes for queueing the coming request.
389
390class CookieMonster::CookieMonsterTask
391 : public base::RefCountedThreadSafe<CookieMonsterTask> {
392 public:
393 // Runs the task and invokes the client callback on the thread that
394 // originally constructed the task.
395 virtual void Run() = 0;
396
397 protected:
398 explicit CookieMonsterTask(CookieMonster* cookie_monster);
399 virtual ~CookieMonsterTask();
400
mkwstbe84af312015-02-20 08:52:45401 CookieMonster* cookie_monster() { return cookie_monster_; }
[email protected]218aa6a12011-09-13 17:38:38402
[email protected]a9813302012-04-28 09:29:28403 private:
[email protected]218aa6a12011-09-13 17:38:38404 friend class base::RefCountedThreadSafe<CookieMonsterTask>;
405
[email protected]218aa6a12011-09-13 17:38:38406 CookieMonster* cookie_monster_;
[email protected]218aa6a12011-09-13 17:38:38407
408 DISALLOW_COPY_AND_ASSIGN(CookieMonsterTask);
409};
410
411CookieMonster::CookieMonsterTask::CookieMonsterTask(
412 CookieMonster* cookie_monster)
mmenkebe0910d2016-03-01 19:09:09413 : cookie_monster_(cookie_monster) {}
[email protected]218aa6a12011-09-13 17:38:38414
mkwstbe84af312015-02-20 08:52:45415CookieMonster::CookieMonsterTask::~CookieMonsterTask() {
416}
[email protected]218aa6a12011-09-13 17:38:38417
[email protected]218aa6a12011-09-13 17:38:38418// Task class for SetCookieWithDetails call.
[email protected]5fa4f9a2013-10-03 10:13:16419class CookieMonster::SetCookieWithDetailsTask : public CookieMonsterTask {
[email protected]218aa6a12011-09-13 17:38:38420 public:
[email protected]dedec0b2013-02-28 04:50:10421 SetCookieWithDetailsTask(CookieMonster* cookie_monster,
422 const GURL& url,
423 const std::string& name,
424 const std::string& value,
425 const std::string& domain,
426 const std::string& path,
mmenkefdd4fc72016-02-05 20:53:24427 base::Time creation_time,
428 base::Time expiration_time,
429 base::Time last_access_time,
[email protected]dedec0b2013-02-28 04:50:10430 bool secure,
431 bool http_only,
mkwste1a29582016-03-15 10:07:52432 CookieSameSite same_site,
[email protected]ab2d75c82013-04-19 18:39:04433 CookiePriority priority,
[email protected]5fa4f9a2013-10-03 10:13:16434 const SetCookiesCallback& callback)
[email protected]218aa6a12011-09-13 17:38:38435 : CookieMonsterTask(cookie_monster),
436 url_(url),
437 name_(name),
438 value_(value),
439 domain_(domain),
440 path_(path),
mmenkeea4cd402016-02-02 04:03:10441 creation_time_(creation_time),
[email protected]218aa6a12011-09-13 17:38:38442 expiration_time_(expiration_time),
mmenkefdd4fc72016-02-05 20:53:24443 last_access_time_(last_access_time),
[email protected]218aa6a12011-09-13 17:38:38444 secure_(secure),
445 http_only_(http_only),
mkwst46549412016-02-01 10:05:37446 same_site_(same_site),
[email protected]ab2d75c82013-04-19 18:39:04447 priority_(priority),
mkwstbe84af312015-02-20 08:52:45448 callback_(callback) {}
[email protected]218aa6a12011-09-13 17:38:38449
[email protected]5fa4f9a2013-10-03 10:13:16450 // CookieMonsterTask:
dchengb03027d2014-10-21 12:00:20451 void Run() override;
[email protected]218aa6a12011-09-13 17:38:38452
[email protected]a9813302012-04-28 09:29:28453 protected:
dchengb03027d2014-10-21 12:00:20454 ~SetCookieWithDetailsTask() override {}
[email protected]a9813302012-04-28 09:29:28455
[email protected]218aa6a12011-09-13 17:38:38456 private:
457 GURL url_;
458 std::string name_;
459 std::string value_;
460 std::string domain_;
461 std::string path_;
mmenkeea4cd402016-02-02 04:03:10462 base::Time creation_time_;
[email protected]218aa6a12011-09-13 17:38:38463 base::Time expiration_time_;
mmenkefdd4fc72016-02-05 20:53:24464 base::Time last_access_time_;
[email protected]218aa6a12011-09-13 17:38:38465 bool secure_;
466 bool http_only_;
mkwste1a29582016-03-15 10:07:52467 CookieSameSite same_site_;
[email protected]ab2d75c82013-04-19 18:39:04468 CookiePriority priority_;
[email protected]5fa4f9a2013-10-03 10:13:16469 SetCookiesCallback callback_;
[email protected]218aa6a12011-09-13 17:38:38470
471 DISALLOW_COPY_AND_ASSIGN(SetCookieWithDetailsTask);
472};
473
474void CookieMonster::SetCookieWithDetailsTask::Run() {
mkwstbe84af312015-02-20 08:52:45475 bool success = this->cookie_monster()->SetCookieWithDetails(
mmenkeea4cd402016-02-02 04:03:10476 url_, name_, value_, domain_, path_, creation_time_, expiration_time_,
jwwa26e439d2017-01-27 18:17:27477 last_access_time_, secure_, http_only_, same_site_, priority_);
mmenkebe0910d2016-03-01 19:09:09478 if (!callback_.is_null())
479 callback_.Run(success);
[email protected]218aa6a12011-09-13 17:38:38480}
481
482// Task class for GetAllCookies call.
[email protected]5fa4f9a2013-10-03 10:13:16483class CookieMonster::GetAllCookiesTask : public CookieMonsterTask {
[email protected]218aa6a12011-09-13 17:38:38484 public:
485 GetAllCookiesTask(CookieMonster* cookie_monster,
[email protected]5fa4f9a2013-10-03 10:13:16486 const GetCookieListCallback& callback)
mkwstbe84af312015-02-20 08:52:45487 : CookieMonsterTask(cookie_monster), callback_(callback) {}
[email protected]218aa6a12011-09-13 17:38:38488
[email protected]5fa4f9a2013-10-03 10:13:16489 // CookieMonsterTask
dchengb03027d2014-10-21 12:00:20490 void Run() override;
[email protected]218aa6a12011-09-13 17:38:38491
[email protected]a9813302012-04-28 09:29:28492 protected:
dchengb03027d2014-10-21 12:00:20493 ~GetAllCookiesTask() override {}
[email protected]a9813302012-04-28 09:29:28494
[email protected]218aa6a12011-09-13 17:38:38495 private:
[email protected]5fa4f9a2013-10-03 10:13:16496 GetCookieListCallback callback_;
[email protected]218aa6a12011-09-13 17:38:38497
498 DISALLOW_COPY_AND_ASSIGN(GetAllCookiesTask);
499};
500
501void CookieMonster::GetAllCookiesTask::Run() {
502 if (!callback_.is_null()) {
503 CookieList cookies = this->cookie_monster()->GetAllCookies();
mmenkebe0910d2016-03-01 19:09:09504 callback_.Run(cookies);
mkwstbe84af312015-02-20 08:52:45505 }
[email protected]218aa6a12011-09-13 17:38:38506}
507
mkwstc611e6d2016-02-23 15:45:55508// Task class for GetCookieListWithOptionsAsync call.
509class CookieMonster::GetCookieListWithOptionsTask : public CookieMonsterTask {
[email protected]218aa6a12011-09-13 17:38:38510 public:
mkwstc611e6d2016-02-23 15:45:55511 GetCookieListWithOptionsTask(CookieMonster* cookie_monster,
512 const GURL& url,
513 const CookieOptions& options,
514 const GetCookieListCallback& callback)
[email protected]218aa6a12011-09-13 17:38:38515 : CookieMonsterTask(cookie_monster),
516 url_(url),
517 options_(options),
mkwstbe84af312015-02-20 08:52:45518 callback_(callback) {}
[email protected]218aa6a12011-09-13 17:38:38519
[email protected]5fa4f9a2013-10-03 10:13:16520 // CookieMonsterTask:
dchengb03027d2014-10-21 12:00:20521 void Run() override;
[email protected]218aa6a12011-09-13 17:38:38522
[email protected]a9813302012-04-28 09:29:28523 protected:
mkwstc611e6d2016-02-23 15:45:55524 ~GetCookieListWithOptionsTask() override {}
[email protected]a9813302012-04-28 09:29:28525
[email protected]218aa6a12011-09-13 17:38:38526 private:
527 GURL url_;
528 CookieOptions options_;
[email protected]5fa4f9a2013-10-03 10:13:16529 GetCookieListCallback callback_;
[email protected]218aa6a12011-09-13 17:38:38530
mkwstc611e6d2016-02-23 15:45:55531 DISALLOW_COPY_AND_ASSIGN(GetCookieListWithOptionsTask);
[email protected]218aa6a12011-09-13 17:38:38532};
533
mkwstc611e6d2016-02-23 15:45:55534void CookieMonster::GetCookieListWithOptionsTask::Run() {
[email protected]218aa6a12011-09-13 17:38:38535 if (!callback_.is_null()) {
mkwstbe84af312015-02-20 08:52:45536 CookieList cookies =
mkwstc611e6d2016-02-23 15:45:55537 this->cookie_monster()->GetCookieListWithOptions(url_, options_);
mmenkebe0910d2016-03-01 19:09:09538 callback_.Run(cookies);
[email protected]218aa6a12011-09-13 17:38:38539 }
540}
541
mkwstbe84af312015-02-20 08:52:45542template <typename Result>
543struct CallbackType {
[email protected]5fa4f9a2013-10-03 10:13:16544 typedef base::Callback<void(Result)> Type;
545};
546
mkwstbe84af312015-02-20 08:52:45547template <>
548struct CallbackType<void> {
[email protected]5fa4f9a2013-10-03 10:13:16549 typedef base::Closure Type;
550};
551
552// Base task class for Delete*Task.
553template <typename Result>
554class CookieMonster::DeleteTask : public CookieMonsterTask {
[email protected]218aa6a12011-09-13 17:38:38555 public:
[email protected]5fa4f9a2013-10-03 10:13:16556 DeleteTask(CookieMonster* cookie_monster,
557 const typename CallbackType<Result>::Type& callback)
mkwstbe84af312015-02-20 08:52:45558 : CookieMonsterTask(cookie_monster), callback_(callback) {}
[email protected]218aa6a12011-09-13 17:38:38559
[email protected]5fa4f9a2013-10-03 10:13:16560 // CookieMonsterTask:
nickd3f30d022015-04-23 10:18:37561 void Run() override;
[email protected]218aa6a12011-09-13 17:38:38562
dmichaeld6e570d2014-12-18 22:30:57563 protected:
564 ~DeleteTask() override;
565
[email protected]5fa4f9a2013-10-03 10:13:16566 private:
567 // Runs the delete task and returns a result.
568 virtual Result RunDeleteTask() = 0;
mmenkebe0910d2016-03-01 19:09:09569 // Runs the delete task and then returns a callback to be called after
570 // flushing the persistent store.
571 // TODO(mmenke): This seems like a pretty ugly and needlessly confusing API.
572 // Simplify it?
[email protected]5fa4f9a2013-10-03 10:13:16573 base::Closure RunDeleteTaskAndBindCallback();
[email protected]5fa4f9a2013-10-03 10:13:16574
575 typename CallbackType<Result>::Type callback_;
576
577 DISALLOW_COPY_AND_ASSIGN(DeleteTask);
578};
579
580template <typename Result>
dmichaeld6e570d2014-12-18 22:30:57581CookieMonster::DeleteTask<Result>::~DeleteTask() {
582}
583
584template <typename Result>
585base::Closure
586CookieMonster::DeleteTask<Result>::RunDeleteTaskAndBindCallback() {
[email protected]5fa4f9a2013-10-03 10:13:16587 Result result = RunDeleteTask();
588 if (callback_.is_null())
589 return base::Closure();
590 return base::Bind(callback_, result);
591}
592
593template <>
594base::Closure CookieMonster::DeleteTask<void>::RunDeleteTaskAndBindCallback() {
595 RunDeleteTask();
596 return callback_;
597}
598
599template <typename Result>
600void CookieMonster::DeleteTask<Result>::Run() {
mmenkebe0910d2016-03-01 19:09:09601 base::Closure callback = RunDeleteTaskAndBindCallback();
[email protected]5fa4f9a2013-10-03 10:13:16602 if (!callback.is_null()) {
mmenkebe0910d2016-03-01 19:09:09603 callback = base::Bind(
604 &CookieMonster::RunCallback,
605 this->cookie_monster()->weak_ptr_factory_.GetWeakPtr(), callback);
[email protected]5fa4f9a2013-10-03 10:13:16606 }
mmenkebe0910d2016-03-01 19:09:09607 this->cookie_monster()->FlushStore(callback);
[email protected]5fa4f9a2013-10-03 10:13:16608}
609
[email protected]218aa6a12011-09-13 17:38:38610// Task class for DeleteAllCreatedBetween call.
[email protected]5fa4f9a2013-10-03 10:13:16611class CookieMonster::DeleteAllCreatedBetweenTask : public DeleteTask<int> {
[email protected]218aa6a12011-09-13 17:38:38612 public:
[email protected]dedec0b2013-02-28 04:50:10613 DeleteAllCreatedBetweenTask(CookieMonster* cookie_monster,
614 const Time& delete_begin,
615 const Time& delete_end,
[email protected]5fa4f9a2013-10-03 10:13:16616 const DeleteCallback& callback)
[email protected]151132f2013-11-18 21:37:00617 : DeleteTask<int>(cookie_monster, callback),
[email protected]218aa6a12011-09-13 17:38:38618 delete_begin_(delete_begin),
mkwstbe84af312015-02-20 08:52:45619 delete_end_(delete_end) {}
[email protected]218aa6a12011-09-13 17:38:38620
[email protected]5fa4f9a2013-10-03 10:13:16621 // DeleteTask:
dchengb03027d2014-10-21 12:00:20622 int RunDeleteTask() override;
[email protected]218aa6a12011-09-13 17:38:38623
[email protected]a9813302012-04-28 09:29:28624 protected:
dchengb03027d2014-10-21 12:00:20625 ~DeleteAllCreatedBetweenTask() override {}
[email protected]a9813302012-04-28 09:29:28626
[email protected]218aa6a12011-09-13 17:38:38627 private:
628 Time delete_begin_;
629 Time delete_end_;
[email protected]218aa6a12011-09-13 17:38:38630
631 DISALLOW_COPY_AND_ASSIGN(DeleteAllCreatedBetweenTask);
632};
633
[email protected]5fa4f9a2013-10-03 10:13:16634int CookieMonster::DeleteAllCreatedBetweenTask::RunDeleteTask() {
mkwstbe84af312015-02-20 08:52:45635 return this->cookie_monster()->DeleteAllCreatedBetween(delete_begin_,
636 delete_end_);
[email protected]218aa6a12011-09-13 17:38:38637}
638
dmurphfaea244c2016-04-09 00:42:30639// Task class for DeleteAllCreatedBetweenWithPredicate call.
640class CookieMonster::DeleteAllCreatedBetweenWithPredicateTask
[email protected]5fa4f9a2013-10-03 10:13:16641 : public DeleteTask<int> {
[email protected]d8428d52013-08-07 06:58:25642 public:
dmurphfaea244c2016-04-09 00:42:30643 DeleteAllCreatedBetweenWithPredicateTask(
644 CookieMonster* cookie_monster,
645 Time delete_begin,
646 Time delete_end,
647 base::Callback<bool(const CanonicalCookie&)> predicate,
648 const DeleteCallback& callback)
[email protected]151132f2013-11-18 21:37:00649 : DeleteTask<int>(cookie_monster, callback),
[email protected]d8428d52013-08-07 06:58:25650 delete_begin_(delete_begin),
651 delete_end_(delete_end),
dmurphfaea244c2016-04-09 00:42:30652 predicate_(predicate) {}
[email protected]d8428d52013-08-07 06:58:25653
[email protected]5fa4f9a2013-10-03 10:13:16654 // DeleteTask:
dchengb03027d2014-10-21 12:00:20655 int RunDeleteTask() override;
[email protected]d8428d52013-08-07 06:58:25656
657 protected:
dmurphfaea244c2016-04-09 00:42:30658 ~DeleteAllCreatedBetweenWithPredicateTask() override {}
[email protected]d8428d52013-08-07 06:58:25659
660 private:
661 Time delete_begin_;
662 Time delete_end_;
dmurphfaea244c2016-04-09 00:42:30663 base::Callback<bool(const CanonicalCookie&)> predicate_;
[email protected]d8428d52013-08-07 06:58:25664
dmurphfaea244c2016-04-09 00:42:30665 DISALLOW_COPY_AND_ASSIGN(DeleteAllCreatedBetweenWithPredicateTask);
[email protected]d8428d52013-08-07 06:58:25666};
667
dmurphfaea244c2016-04-09 00:42:30668int CookieMonster::DeleteAllCreatedBetweenWithPredicateTask::RunDeleteTask() {
669 return this->cookie_monster()->DeleteAllCreatedBetweenWithPredicate(
670 delete_begin_, delete_end_, predicate_);
[email protected]d8428d52013-08-07 06:58:25671}
672
[email protected]218aa6a12011-09-13 17:38:38673// Task class for DeleteCanonicalCookie call.
mmenke24379d52016-02-05 23:50:17674class CookieMonster::DeleteCanonicalCookieTask : public DeleteTask<int> {
[email protected]218aa6a12011-09-13 17:38:38675 public:
[email protected]dedec0b2013-02-28 04:50:10676 DeleteCanonicalCookieTask(CookieMonster* cookie_monster,
677 const CanonicalCookie& cookie,
mmenke24379d52016-02-05 23:50:17678 const DeleteCallback& callback)
679 : DeleteTask<int>(cookie_monster, callback), cookie_(cookie) {}
[email protected]218aa6a12011-09-13 17:38:38680
[email protected]5fa4f9a2013-10-03 10:13:16681 // DeleteTask:
mmenke24379d52016-02-05 23:50:17682 int RunDeleteTask() override;
[email protected]218aa6a12011-09-13 17:38:38683
[email protected]a9813302012-04-28 09:29:28684 protected:
dchengb03027d2014-10-21 12:00:20685 ~DeleteCanonicalCookieTask() override {}
[email protected]a9813302012-04-28 09:29:28686
[email protected]218aa6a12011-09-13 17:38:38687 private:
[email protected]5b9bc352012-07-18 13:13:34688 CanonicalCookie cookie_;
[email protected]218aa6a12011-09-13 17:38:38689
690 DISALLOW_COPY_AND_ASSIGN(DeleteCanonicalCookieTask);
691};
692
mmenke24379d52016-02-05 23:50:17693int CookieMonster::DeleteCanonicalCookieTask::RunDeleteTask() {
[email protected]5fa4f9a2013-10-03 10:13:16694 return this->cookie_monster()->DeleteCanonicalCookie(cookie_);
[email protected]218aa6a12011-09-13 17:38:38695}
696
697// Task class for SetCookieWithOptions call.
[email protected]5fa4f9a2013-10-03 10:13:16698class CookieMonster::SetCookieWithOptionsTask : public CookieMonsterTask {
[email protected]218aa6a12011-09-13 17:38:38699 public:
700 SetCookieWithOptionsTask(CookieMonster* cookie_monster,
701 const GURL& url,
702 const std::string& cookie_line,
703 const CookieOptions& options,
[email protected]5fa4f9a2013-10-03 10:13:16704 const SetCookiesCallback& callback)
[email protected]218aa6a12011-09-13 17:38:38705 : CookieMonsterTask(cookie_monster),
706 url_(url),
707 cookie_line_(cookie_line),
708 options_(options),
mkwstbe84af312015-02-20 08:52:45709 callback_(callback) {}
[email protected]218aa6a12011-09-13 17:38:38710
[email protected]5fa4f9a2013-10-03 10:13:16711 // CookieMonsterTask:
dchengb03027d2014-10-21 12:00:20712 void Run() override;
[email protected]218aa6a12011-09-13 17:38:38713
[email protected]a9813302012-04-28 09:29:28714 protected:
dchengb03027d2014-10-21 12:00:20715 ~SetCookieWithOptionsTask() override {}
[email protected]a9813302012-04-28 09:29:28716
[email protected]218aa6a12011-09-13 17:38:38717 private:
718 GURL url_;
719 std::string cookie_line_;
720 CookieOptions options_;
[email protected]5fa4f9a2013-10-03 10:13:16721 SetCookiesCallback callback_;
[email protected]218aa6a12011-09-13 17:38:38722
723 DISALLOW_COPY_AND_ASSIGN(SetCookieWithOptionsTask);
724};
725
726void CookieMonster::SetCookieWithOptionsTask::Run() {
mkwstbe84af312015-02-20 08:52:45727 bool result = this->cookie_monster()->SetCookieWithOptions(url_, cookie_line_,
728 options_);
mmenkebe0910d2016-03-01 19:09:09729 if (!callback_.is_null())
730 callback_.Run(result);
[email protected]218aa6a12011-09-13 17:38:38731}
732
drogerd5d1278c2015-03-17 19:21:51733// Task class for SetAllCookies call.
734class CookieMonster::SetAllCookiesTask : public CookieMonsterTask {
735 public:
736 SetAllCookiesTask(CookieMonster* cookie_monster,
737 const CookieList& list,
738 const SetCookiesCallback& callback)
739 : CookieMonsterTask(cookie_monster), list_(list), callback_(callback) {}
740
741 // CookieMonsterTask:
742 void Run() override;
743
744 protected:
745 ~SetAllCookiesTask() override {}
746
747 private:
748 CookieList list_;
749 SetCookiesCallback callback_;
750
751 DISALLOW_COPY_AND_ASSIGN(SetAllCookiesTask);
752};
753
754void CookieMonster::SetAllCookiesTask::Run() {
755 CookieList positive_diff;
756 CookieList negative_diff;
757 CookieList old_cookies = this->cookie_monster()->GetAllCookies();
758 this->cookie_monster()->ComputeCookieDiff(&old_cookies, &list_,
759 &positive_diff, &negative_diff);
760
761 for (CookieList::const_iterator it = negative_diff.begin();
762 it != negative_diff.end(); ++it) {
763 this->cookie_monster()->DeleteCanonicalCookie(*it);
764 }
765
766 bool result = true;
767 if (positive_diff.size() > 0)
768 result = this->cookie_monster()->SetCanonicalCookies(list_);
769
mmenkebe0910d2016-03-01 19:09:09770 if (!callback_.is_null())
771 callback_.Run(result);
drogerd5d1278c2015-03-17 19:21:51772}
773
[email protected]218aa6a12011-09-13 17:38:38774// Task class for GetCookiesWithOptions call.
[email protected]5fa4f9a2013-10-03 10:13:16775class CookieMonster::GetCookiesWithOptionsTask : public CookieMonsterTask {
[email protected]218aa6a12011-09-13 17:38:38776 public:
777 GetCookiesWithOptionsTask(CookieMonster* cookie_monster,
[email protected]0298caf82011-12-20 23:15:46778 const GURL& url,
[email protected]218aa6a12011-09-13 17:38:38779 const CookieOptions& options,
[email protected]5fa4f9a2013-10-03 10:13:16780 const GetCookiesCallback& callback)
[email protected]218aa6a12011-09-13 17:38:38781 : CookieMonsterTask(cookie_monster),
782 url_(url),
783 options_(options),
mkwstbe84af312015-02-20 08:52:45784 callback_(callback) {}
[email protected]218aa6a12011-09-13 17:38:38785
[email protected]5fa4f9a2013-10-03 10:13:16786 // CookieMonsterTask:
dchengb03027d2014-10-21 12:00:20787 void Run() override;
[email protected]218aa6a12011-09-13 17:38:38788
[email protected]a9813302012-04-28 09:29:28789 protected:
dchengb03027d2014-10-21 12:00:20790 ~GetCookiesWithOptionsTask() override {}
[email protected]a9813302012-04-28 09:29:28791
[email protected]218aa6a12011-09-13 17:38:38792 private:
793 GURL url_;
794 CookieOptions options_;
[email protected]5fa4f9a2013-10-03 10:13:16795 GetCookiesCallback callback_;
[email protected]218aa6a12011-09-13 17:38:38796
797 DISALLOW_COPY_AND_ASSIGN(GetCookiesWithOptionsTask);
798};
799
800void CookieMonster::GetCookiesWithOptionsTask::Run() {
mkwstbe84af312015-02-20 08:52:45801 std::string cookie =
802 this->cookie_monster()->GetCookiesWithOptions(url_, options_);
mmenkebe0910d2016-03-01 19:09:09803 if (!callback_.is_null())
804 callback_.Run(cookie);
[email protected]218aa6a12011-09-13 17:38:38805}
806
[email protected]218aa6a12011-09-13 17:38:38807// Task class for DeleteCookie call.
[email protected]5fa4f9a2013-10-03 10:13:16808class CookieMonster::DeleteCookieTask : public DeleteTask<void> {
[email protected]218aa6a12011-09-13 17:38:38809 public:
810 DeleteCookieTask(CookieMonster* cookie_monster,
[email protected]0298caf82011-12-20 23:15:46811 const GURL& url,
[email protected]218aa6a12011-09-13 17:38:38812 const std::string& cookie_name,
813 const base::Closure& callback)
[email protected]151132f2013-11-18 21:37:00814 : DeleteTask<void>(cookie_monster, callback),
[email protected]218aa6a12011-09-13 17:38:38815 url_(url),
mkwstbe84af312015-02-20 08:52:45816 cookie_name_(cookie_name) {}
[email protected]218aa6a12011-09-13 17:38:38817
[email protected]5fa4f9a2013-10-03 10:13:16818 // DeleteTask:
dchengb03027d2014-10-21 12:00:20819 void RunDeleteTask() override;
[email protected]218aa6a12011-09-13 17:38:38820
[email protected]a9813302012-04-28 09:29:28821 protected:
dchengb03027d2014-10-21 12:00:20822 ~DeleteCookieTask() override {}
[email protected]a9813302012-04-28 09:29:28823
[email protected]218aa6a12011-09-13 17:38:38824 private:
825 GURL url_;
826 std::string cookie_name_;
[email protected]218aa6a12011-09-13 17:38:38827
828 DISALLOW_COPY_AND_ASSIGN(DeleteCookieTask);
829};
830
[email protected]5fa4f9a2013-10-03 10:13:16831void CookieMonster::DeleteCookieTask::RunDeleteTask() {
[email protected]218aa6a12011-09-13 17:38:38832 this->cookie_monster()->DeleteCookie(url_, cookie_name_);
[email protected]218aa6a12011-09-13 17:38:38833}
834
[email protected]264807b2012-04-25 14:49:37835// Task class for DeleteSessionCookies call.
[email protected]5fa4f9a2013-10-03 10:13:16836class CookieMonster::DeleteSessionCookiesTask : public DeleteTask<int> {
[email protected]264807b2012-04-25 14:49:37837 public:
[email protected]dedec0b2013-02-28 04:50:10838 DeleteSessionCookiesTask(CookieMonster* cookie_monster,
[email protected]5fa4f9a2013-10-03 10:13:16839 const DeleteCallback& callback)
mkwstbe84af312015-02-20 08:52:45840 : DeleteTask<int>(cookie_monster, callback) {}
[email protected]264807b2012-04-25 14:49:37841
[email protected]5fa4f9a2013-10-03 10:13:16842 // DeleteTask:
dchengb03027d2014-10-21 12:00:20843 int RunDeleteTask() override;
[email protected]264807b2012-04-25 14:49:37844
[email protected]a9813302012-04-28 09:29:28845 protected:
dchengb03027d2014-10-21 12:00:20846 ~DeleteSessionCookiesTask() override {}
[email protected]a9813302012-04-28 09:29:28847
[email protected]264807b2012-04-25 14:49:37848 private:
[email protected]264807b2012-04-25 14:49:37849 DISALLOW_COPY_AND_ASSIGN(DeleteSessionCookiesTask);
850};
851
[email protected]5fa4f9a2013-10-03 10:13:16852int CookieMonster::DeleteSessionCookiesTask::RunDeleteTask() {
853 return this->cookie_monster()->DeleteSessionCookies();
[email protected]264807b2012-04-25 14:49:37854}
855
[email protected]218aa6a12011-09-13 17:38:38856// Asynchronous CookieMonster API
857
858void CookieMonster::SetCookieWithDetailsAsync(
[email protected]dedec0b2013-02-28 04:50:10859 const GURL& url,
860 const std::string& name,
861 const std::string& value,
862 const std::string& domain,
863 const std::string& path,
mmenkefdd4fc72016-02-05 20:53:24864 Time creation_time,
865 Time expiration_time,
866 Time last_access_time,
[email protected]dedec0b2013-02-28 04:50:10867 bool secure,
868 bool http_only,
mkwste1a29582016-03-15 10:07:52869 CookieSameSite same_site,
[email protected]ab2d75c82013-04-19 18:39:04870 CookiePriority priority,
[email protected]218aa6a12011-09-13 17:38:38871 const SetCookiesCallback& callback) {
mkwstbe84af312015-02-20 08:52:45872 scoped_refptr<SetCookieWithDetailsTask> task = new SetCookieWithDetailsTask(
mmenkeea4cd402016-02-02 04:03:10873 this, url, name, value, domain, path, creation_time, expiration_time,
jwwa26e439d2017-01-27 18:17:27874 last_access_time, secure, http_only, same_site, priority, callback);
[email protected]85620342011-10-17 17:35:04875 DoCookieTaskForURL(task, url);
[email protected]218aa6a12011-09-13 17:38:38876}
877
mmenke74bcbd52016-01-21 17:17:56878void CookieMonster::FlushStore(const base::Closure& callback) {
mmenkebe0910d2016-03-01 19:09:09879 DCHECK(thread_checker_.CalledOnValidThread());
mmenke606c59c2016-03-07 18:20:55880
nharper2b0ad9a2017-05-22 18:33:45881 if (initialized_ && store_.get()) {
882 if (channel_id_service_) {
883 channel_id_service_->GetChannelIDStore()->Flush();
884 }
mmenke74bcbd52016-01-21 17:17:56885 store_->Flush(callback);
nharper2b0ad9a2017-05-22 18:33:45886 } else if (!callback.is_null()) {
mmenke74bcbd52016-01-21 17:17:56887 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, callback);
nharper2b0ad9a2017-05-22 18:33:45888 }
mmenke74bcbd52016-01-21 17:17:56889}
890
mmenkeded79da2016-02-06 08:28:51891void CookieMonster::SetForceKeepSessionState() {
mmenkebe0910d2016-03-01 19:09:09892 DCHECK(thread_checker_.CalledOnValidThread());
mmenke606c59c2016-03-07 18:20:55893
mmenkeded79da2016-02-06 08:28:51894 if (store_)
895 store_->SetForceKeepSessionState();
896}
897
drogerd5d1278c2015-03-17 19:21:51898void CookieMonster::SetAllCookiesAsync(const CookieList& list,
899 const SetCookiesCallback& callback) {
900 scoped_refptr<SetAllCookiesTask> task =
901 new SetAllCookiesTask(this, list, callback);
902 DoCookieTask(task);
903}
904
[email protected]218aa6a12011-09-13 17:38:38905void CookieMonster::SetCookieWithOptionsAsync(
906 const GURL& url,
907 const std::string& cookie_line,
908 const CookieOptions& options,
909 const SetCookiesCallback& callback) {
910 scoped_refptr<SetCookieWithOptionsTask> task =
911 new SetCookieWithOptionsTask(this, url, cookie_line, options, callback);
912
[email protected]85620342011-10-17 17:35:04913 DoCookieTaskForURL(task, url);
[email protected]218aa6a12011-09-13 17:38:38914}
915
916void CookieMonster::GetCookiesWithOptionsAsync(
917 const GURL& url,
918 const CookieOptions& options,
919 const GetCookiesCallback& callback) {
920 scoped_refptr<GetCookiesWithOptionsTask> task =
921 new GetCookiesWithOptionsTask(this, url, options, callback);
922
[email protected]85620342011-10-17 17:35:04923 DoCookieTaskForURL(task, url);
[email protected]218aa6a12011-09-13 17:38:38924}
925
mkwstc611e6d2016-02-23 15:45:55926void CookieMonster::GetCookieListWithOptionsAsync(
mmenke74bcbd52016-01-21 17:17:56927 const GURL& url,
mkwstc611e6d2016-02-23 15:45:55928 const CookieOptions& options,
mmenke74bcbd52016-01-21 17:17:56929 const GetCookieListCallback& callback) {
mkwstc611e6d2016-02-23 15:45:55930 scoped_refptr<GetCookieListWithOptionsTask> task =
931 new GetCookieListWithOptionsTask(this, url, options, callback);
mmenke74bcbd52016-01-21 17:17:56932
933 DoCookieTaskForURL(task, url);
934}
935
mmenke9fa44f2d2016-01-22 23:36:39936void CookieMonster::GetAllCookiesAsync(const GetCookieListCallback& callback) {
937 scoped_refptr<GetAllCookiesTask> task = new GetAllCookiesTask(this, callback);
938
939 DoCookieTask(task);
940}
941
[email protected]218aa6a12011-09-13 17:38:38942void CookieMonster::DeleteCookieAsync(const GURL& url,
943 const std::string& cookie_name,
944 const base::Closure& callback) {
945 scoped_refptr<DeleteCookieTask> task =
946 new DeleteCookieTask(this, url, cookie_name, callback);
947
[email protected]85620342011-10-17 17:35:04948 DoCookieTaskForURL(task, url);
[email protected]218aa6a12011-09-13 17:38:38949}
950
mmenke24379d52016-02-05 23:50:17951void CookieMonster::DeleteCanonicalCookieAsync(const CanonicalCookie& cookie,
952 const DeleteCallback& callback) {
953 scoped_refptr<DeleteCanonicalCookieTask> task =
954 new DeleteCanonicalCookieTask(this, cookie, callback);
955
956 DoCookieTask(task);
957}
958
mmenke74bcbd52016-01-21 17:17:56959void CookieMonster::DeleteAllCreatedBetweenAsync(
960 const Time& delete_begin,
961 const Time& delete_end,
962 const DeleteCallback& callback) {
963 scoped_refptr<DeleteAllCreatedBetweenTask> task =
964 new DeleteAllCreatedBetweenTask(this, delete_begin, delete_end, callback);
965
966 DoCookieTask(task);
967}
968
dmurphfaea244c2016-04-09 00:42:30969void CookieMonster::DeleteAllCreatedBetweenWithPredicateAsync(
970 const Time& delete_begin,
971 const Time& delete_end,
972 const base::Callback<bool(const CanonicalCookie&)>& predicate,
mmenke74bcbd52016-01-21 17:17:56973 const DeleteCallback& callback) {
dmurphfaea244c2016-04-09 00:42:30974 if (predicate.is_null()) {
975 callback.Run(0);
976 return;
977 }
978 scoped_refptr<DeleteAllCreatedBetweenWithPredicateTask> task =
979 new DeleteAllCreatedBetweenWithPredicateTask(
980 this, delete_begin, delete_end, predicate, callback);
981 DoCookieTask(task);
mmenke74bcbd52016-01-21 17:17:56982}
983
[email protected]264807b2012-04-25 14:49:37984void CookieMonster::DeleteSessionCookiesAsync(
985 const CookieStore::DeleteCallback& callback) {
986 scoped_refptr<DeleteSessionCookiesTask> task =
987 new DeleteSessionCookiesTask(this, callback);
988
989 DoCookieTask(task);
990}
991
mmenke18dd8ba2016-02-01 18:42:10992void CookieMonster::SetCookieableSchemes(
993 const std::vector<std::string>& schemes) {
mmenkebe0910d2016-03-01 19:09:09994 DCHECK(thread_checker_.CalledOnValidThread());
mmenke74bcbd52016-01-21 17:17:56995
996 // Calls to this method will have no effect if made after a WebView or
997 // CookieManager instance has been created.
mmenke18dd8ba2016-02-01 18:42:10998 if (initialized_)
mmenke74bcbd52016-01-21 17:17:56999 return;
mmenke74bcbd52016-01-21 17:17:561000
mmenke18dd8ba2016-02-01 18:42:101001 cookieable_schemes_ = schemes;
mmenke74bcbd52016-01-21 17:17:561002}
1003
mmenke74bcbd52016-01-21 17:17:561004// This function must be called before the CookieMonster is used.
1005void CookieMonster::SetPersistSessionCookies(bool persist_session_cookies) {
mmenkebe0910d2016-03-01 19:09:091006 DCHECK(thread_checker_.CalledOnValidThread());
mmenke74bcbd52016-01-21 17:17:561007 DCHECK(!initialized_);
1008 persist_session_cookies_ = persist_session_cookies;
1009}
1010
1011bool CookieMonster::IsCookieableScheme(const std::string& scheme) {
mmenkebe0910d2016-03-01 19:09:091012 DCHECK(thread_checker_.CalledOnValidThread());
mmenke74bcbd52016-01-21 17:17:561013
1014 return std::find(cookieable_schemes_.begin(), cookieable_schemes_.end(),
1015 scheme) != cookieable_schemes_.end();
1016}
1017
mmenke18dd8ba2016-02-01 18:42:101018const char* const CookieMonster::kDefaultCookieableSchemes[] = {"http", "https",
1019 "ws", "wss"};
mmenke74bcbd52016-01-21 17:17:561020const int CookieMonster::kDefaultCookieableSchemesCount =
1021 arraysize(kDefaultCookieableSchemes);
1022
danakja9850e12016-04-18 22:28:081023std::unique_ptr<CookieStore::CookieChangedSubscription>
mmenke74bcbd52016-01-21 17:17:561024CookieMonster::AddCallbackForCookie(const GURL& gurl,
1025 const std::string& name,
1026 const CookieChangedCallback& callback) {
mmenkebe0910d2016-03-01 19:09:091027 DCHECK(thread_checker_.CalledOnValidThread());
mmenke606c59c2016-03-07 18:20:551028
mmenke74bcbd52016-01-21 17:17:561029 std::pair<GURL, std::string> key(gurl, name);
1030 if (hook_map_.count(key) == 0)
avie7cd11a2016-10-11 02:00:351031 hook_map_[key] = base::MakeUnique<CookieChangedCallbackList>();
mmenke74bcbd52016-01-21 17:17:561032 return hook_map_[key]->Add(
1033 base::Bind(&RunAsync, base::ThreadTaskRunnerHandle::Get(), callback));
1034}
1035
nharper5babb5e62016-03-09 18:58:071036bool CookieMonster::IsEphemeral() {
1037 return store_.get() == nullptr;
1038}
1039
mmenke74bcbd52016-01-21 17:17:561040CookieMonster::~CookieMonster() {
mmenkebe0910d2016-03-01 19:09:091041 DCHECK(thread_checker_.CalledOnValidThread());
mmenke05255cf2016-02-03 15:49:311042
mmenke606c59c2016-03-07 18:20:551043 // TODO(mmenke): Does it really make sense to run |delegate_| and
1044 // CookieChanged callbacks when the CookieStore is destroyed?
mmenke05255cf2016-02-03 15:49:311045 for (CookieMap::iterator cookie_it = cookies_.begin();
1046 cookie_it != cookies_.end();) {
1047 CookieMap::iterator current_cookie_it = cookie_it;
1048 ++cookie_it;
1049 InternalDeleteCookie(current_cookie_it, false /* sync_to_store */,
1050 DELETE_COOKIE_DONT_RECORD);
1051 }
[email protected]85620342011-10-17 17:35:041052}
1053
[email protected]dedec0b2013-02-28 04:50:101054bool CookieMonster::SetCookieWithDetails(const GURL& url,
1055 const std::string& name,
1056 const std::string& value,
1057 const std::string& domain,
1058 const std::string& path,
mmenkefdd4fc72016-02-05 20:53:241059 base::Time creation_time,
1060 base::Time expiration_time,
1061 base::Time last_access_time,
[email protected]dedec0b2013-02-28 04:50:101062 bool secure,
[email protected]ab2d75c82013-04-19 18:39:041063 bool http_only,
mkwste1a29582016-03-15 10:07:521064 CookieSameSite same_site,
[email protected]ab2d75c82013-04-19 18:39:041065 CookiePriority priority) {
mmenkebe0910d2016-03-01 19:09:091066 DCHECK(thread_checker_.CalledOnValidThread());
[email protected]69bb5872010-01-12 20:33:521067
[email protected]f48b9432011-01-11 07:25:401068 if (!HasCookieableScheme(url))
initial.commit586acc5fe2008-07-26 22:42:521069 return false;
1070
mmenkeea4cd402016-02-02 04:03:101071 // TODO(mmenke): This class assumes each cookie to have a unique creation
1072 // time. Allowing the caller to set the creation time violates that
1073 // assumption. Worth fixing? Worth noting that time changes between browser
1074 // restarts can cause the same issue.
1075 base::Time actual_creation_time = creation_time;
1076 if (creation_time.is_null()) {
1077 actual_creation_time = CurrentTime();
1078 last_time_seen_ = actual_creation_time;
1079 }
[email protected]f48b9432011-01-11 07:25:401080
rdsmithb4ecb4c2017-05-12 18:39:031081 // Validate consistency of passed arguments.
1082 if (ParsedCookie::ParseTokenString(name) != name ||
1083 ParsedCookie::ParseValueString(value) != value ||
1084 ParsedCookie::ParseValueString(domain) != domain ||
1085 ParsedCookie::ParseValueString(path) != path) {
1086 return false;
1087 }
1088
1089 // Validate passed arguments against URL.
1090 if (secure && !url.SchemeIsCryptographic())
1091 return false;
1092
1093 std::string cookie_domain;
1094 if (!cookie_util::GetCookieDomainWithString(url, domain, &cookie_domain))
1095 return false;
1096
1097 std::string cookie_path = CanonicalCookie::CanonPathWithString(url, path);
1098 if (!path.empty() && cookie_path != path)
1099 return false;
1100
1101 // Canonicalize path again to make sure it escapes characters as needed.
1102 url::Component path_component(0, cookie_path.length());
1103 url::RawCanonOutputT<char> canon_path;
1104 url::Component canon_path_component;
1105 url::CanonicalizePath(cookie_path.data(), path_component, &canon_path,
1106 &canon_path_component);
1107 cookie_path = std::string(canon_path.data() + canon_path_component.begin,
1108 canon_path_component.len);
1109
rdsmith51010b02017-05-16 16:23:191110 std::unique_ptr<CanonicalCookie> cc(base::MakeUnique<CanonicalCookie>(
rdsmithb4ecb4c2017-05-12 18:39:031111 name, value, cookie_domain, cookie_path, actual_creation_time,
1112 expiration_time, last_access_time, secure, http_only, same_site,
1113 priority));
[email protected]f48b9432011-01-11 07:25:401114
[email protected]f48b9432011-01-11 07:25:401115 CookieOptions options;
1116 options.set_include_httponly();
mkwstf71d0bd2016-03-21 14:15:241117 options.set_same_site_cookie_mode(
1118 CookieOptions::SameSiteCookieMode::INCLUDE_STRICT_AND_LAX);
mmenke009cf62e2016-07-18 19:33:311119 return SetCanonicalCookie(std::move(cc), url, options);
initial.commit586acc5fe2008-07-26 22:42:521120}
1121
[email protected]f48b9432011-01-11 07:25:401122CookieList CookieMonster::GetAllCookies() {
mmenkebe0910d2016-03-01 19:09:091123 DCHECK(thread_checker_.CalledOnValidThread());
[email protected]f48b9432011-01-11 07:25:401124
1125 // This function is being called to scrape the cookie list for management UI
1126 // or similar. We shouldn't show expired cookies in this list since it will
1127 // just be confusing to users, and this function is called rarely enough (and
1128 // is already slow enough) that it's OK to take the time to garbage collect
1129 // the expired cookies now.
1130 //
1131 // Note that this does not prune cookies to be below our limits (if we've
1132 // exceeded them) the way that calling GarbageCollect() would.
mkwstbe84af312015-02-20 08:52:451133 GarbageCollectExpired(
1134 Time::Now(), CookieMapItPair(cookies_.begin(), cookies_.end()), NULL);
[email protected]f48b9432011-01-11 07:25:401135
1136 // Copy the CanonicalCookie pointers from the map so that we can use the same
1137 // sorter as elsewhere, then copy the result out.
1138 std::vector<CanonicalCookie*> cookie_ptrs;
1139 cookie_ptrs.reserve(cookies_.size());
avie7cd11a2016-10-11 02:00:351140 for (const auto& cookie : cookies_)
1141 cookie_ptrs.push_back(cookie.second.get());
[email protected]f48b9432011-01-11 07:25:401142 std::sort(cookie_ptrs.begin(), cookie_ptrs.end(), CookieSorter);
1143
1144 CookieList cookie_list;
1145 cookie_list.reserve(cookie_ptrs.size());
vmpstr6d9996c82017-02-23 00:43:251146 for (auto* cookie_ptr : cookie_ptrs)
avie7cd11a2016-10-11 02:00:351147 cookie_list.push_back(*cookie_ptr);
[email protected]f48b9432011-01-11 07:25:401148
1149 return cookie_list;
[email protected]f325f1e12010-04-30 22:38:551150}
1151
mkwstc611e6d2016-02-23 15:45:551152CookieList CookieMonster::GetCookieListWithOptions(
[email protected]f48b9432011-01-11 07:25:401153 const GURL& url,
1154 const CookieOptions& options) {
mmenkebe0910d2016-03-01 19:09:091155 DCHECK(thread_checker_.CalledOnValidThread());
initial.commit586acc5fe2008-07-26 22:42:521156
mkwstc611e6d2016-02-23 15:45:551157 CookieList cookies;
1158 if (!HasCookieableScheme(url))
1159 return cookies;
1160
[email protected]f48b9432011-01-11 07:25:401161 std::vector<CanonicalCookie*> cookie_ptrs;
mkwst72b65162016-02-22 19:58:541162 FindCookiesForHostAndDomain(url, options, &cookie_ptrs);
[email protected]f48b9432011-01-11 07:25:401163 std::sort(cookie_ptrs.begin(), cookie_ptrs.end(), CookieSorter);
initial.commit586acc5fe2008-07-26 22:42:521164
georgesakc15df6722014-12-02 23:52:121165 cookies.reserve(cookie_ptrs.size());
[email protected]f48b9432011-01-11 07:25:401166 for (std::vector<CanonicalCookie*>::const_iterator it = cookie_ptrs.begin();
1167 it != cookie_ptrs.end(); it++)
1168 cookies.push_back(**it);
initial.commit586acc5fe2008-07-26 22:42:521169
[email protected]f48b9432011-01-11 07:25:401170 return cookies;
initial.commit586acc5fe2008-07-26 22:42:521171}
1172
[email protected]f48b9432011-01-11 07:25:401173int CookieMonster::DeleteAllCreatedBetween(const Time& delete_begin,
[email protected]218aa6a12011-09-13 17:38:381174 const Time& delete_end) {
mmenkebe0910d2016-03-01 19:09:091175 DCHECK(thread_checker_.CalledOnValidThread());
[email protected]d0980332010-11-16 17:08:531176
[email protected]f48b9432011-01-11 07:25:401177 int num_deleted = 0;
1178 for (CookieMap::iterator it = cookies_.begin(); it != cookies_.end();) {
1179 CookieMap::iterator curit = it;
avie7cd11a2016-10-11 02:00:351180 CanonicalCookie* cc = curit->second.get();
[email protected]f48b9432011-01-11 07:25:401181 ++it;
[email protected]d0980332010-11-16 17:08:531182
[email protected]f48b9432011-01-11 07:25:401183 if (cc->CreationDate() >= delete_begin &&
1184 (delete_end.is_null() || cc->CreationDate() < delete_end)) {
mkwstbe84af312015-02-20 08:52:451185 InternalDeleteCookie(curit, true, /*sync_to_store*/
nharper68903362017-01-20 04:07:141186 DELETE_COOKIE_CREATED_BETWEEN);
[email protected]f48b9432011-01-11 07:25:401187 ++num_deleted;
initial.commit586acc5fe2008-07-26 22:42:521188 }
1189 }
1190
[email protected]f48b9432011-01-11 07:25:401191 return num_deleted;
1192}
1193
dmurphfaea244c2016-04-09 00:42:301194int CookieMonster::DeleteAllCreatedBetweenWithPredicate(
1195 const base::Time& delete_begin,
1196 const base::Time& delete_end,
1197 const base::Callback<bool(const CanonicalCookie&)>& predicate) {
[email protected]f48b9432011-01-11 07:25:401198 int num_deleted = 0;
dmurphfaea244c2016-04-09 00:42:301199 for (CookieMap::iterator it = cookies_.begin(); it != cookies_.end();) {
1200 CookieMap::iterator curit = it;
avie7cd11a2016-10-11 02:00:351201 CanonicalCookie* cc = curit->second.get();
dmurphfaea244c2016-04-09 00:42:301202 ++it;
[email protected]f48b9432011-01-11 07:25:401203
dmurphfaea244c2016-04-09 00:42:301204 if (cc->CreationDate() >= delete_begin &&
[email protected]d8428d52013-08-07 06:58:251205 // The assumption that null |delete_end| is equivalent to
1206 // Time::Max() is confusing.
dmurphfaea244c2016-04-09 00:42:301207 (delete_end.is_null() || cc->CreationDate() < delete_end) &&
1208 predicate.Run(*cc)) {
1209 InternalDeleteCookie(curit, true, /*sync_to_store*/
nharper68903362017-01-20 04:07:141210 DELETE_COOKIE_CREATED_BETWEEN_WITH_PREDICATE);
dmurphfaea244c2016-04-09 00:42:301211 ++num_deleted;
[email protected]f48b9432011-01-11 07:25:401212 }
1213 }
dmurphfaea244c2016-04-09 00:42:301214
[email protected]f48b9432011-01-11 07:25:401215 return num_deleted;
1216}
1217
[email protected]f48b9432011-01-11 07:25:401218bool CookieMonster::SetCookieWithOptions(const GURL& url,
1219 const std::string& cookie_line,
1220 const CookieOptions& options) {
mmenkebe0910d2016-03-01 19:09:091221 DCHECK(thread_checker_.CalledOnValidThread());
[email protected]f48b9432011-01-11 07:25:401222
1223 if (!HasCookieableScheme(url)) {
1224 return false;
1225 }
1226
[email protected]f48b9432011-01-11 07:25:401227 return SetCookieWithCreationTimeAndOptions(url, cookie_line, Time(), options);
1228}
1229
1230std::string CookieMonster::GetCookiesWithOptions(const GURL& url,
1231 const CookieOptions& options) {
mmenkebe0910d2016-03-01 19:09:091232 DCHECK(thread_checker_.CalledOnValidThread());
[email protected]f48b9432011-01-11 07:25:401233
[email protected]34a160d2011-05-12 22:12:491234 if (!HasCookieableScheme(url))
[email protected]f48b9432011-01-11 07:25:401235 return std::string();
[email protected]f48b9432011-01-11 07:25:401236
[email protected]f48b9432011-01-11 07:25:401237 std::vector<CanonicalCookie*> cookies;
mkwst72b65162016-02-22 19:58:541238 FindCookiesForHostAndDomain(url, options, &cookies);
[email protected]f48b9432011-01-11 07:25:401239 std::sort(cookies.begin(), cookies.end(), CookieSorter);
1240
[email protected]34a160d2011-05-12 22:12:491241 std::string cookie_line = BuildCookieLine(cookies);
[email protected]f48b9432011-01-11 07:25:401242
[email protected]f48b9432011-01-11 07:25:401243 VLOG(kVlogGetCookies) << "GetCookies() result: " << cookie_line;
1244
1245 return cookie_line;
1246}
1247
1248void CookieMonster::DeleteCookie(const GURL& url,
1249 const std::string& cookie_name) {
mmenkebe0910d2016-03-01 19:09:091250 DCHECK(thread_checker_.CalledOnValidThread());
[email protected]f48b9432011-01-11 07:25:401251
1252 if (!HasCookieableScheme(url))
1253 return;
1254
1255 CookieOptions options;
1256 options.set_include_httponly();
mkwstf71d0bd2016-03-21 14:15:241257 options.set_same_site_cookie_mode(
1258 CookieOptions::SameSiteCookieMode::INCLUDE_STRICT_AND_LAX);
[email protected]f48b9432011-01-11 07:25:401259 // Get the cookies for this host and its domain(s).
1260 std::vector<CanonicalCookie*> cookies;
mkwst72b65162016-02-22 19:58:541261 FindCookiesForHostAndDomain(url, options, &cookies);
[email protected]f48b9432011-01-11 07:25:401262 std::set<CanonicalCookie*> matching_cookies;
1263
vmpstr6f21f242016-06-29 02:16:471264 for (auto* cookie : cookies) {
mmenke4379aeb2016-03-05 12:22:071265 if (cookie->Name() != cookie_name)
[email protected]f48b9432011-01-11 07:25:401266 continue;
mmenke4379aeb2016-03-05 12:22:071267 if (!cookie->IsOnPath(url.path()))
[email protected]f48b9432011-01-11 07:25:401268 continue;
mmenke4379aeb2016-03-05 12:22:071269 matching_cookies.insert(cookie);
[email protected]f48b9432011-01-11 07:25:401270 }
1271
1272 for (CookieMap::iterator it = cookies_.begin(); it != cookies_.end();) {
1273 CookieMap::iterator curit = it;
1274 ++it;
avie7cd11a2016-10-11 02:00:351275 if (matching_cookies.find(curit->second.get()) != matching_cookies.end()) {
nharper68903362017-01-20 04:07:141276 InternalDeleteCookie(curit, true, DELETE_COOKIE_SINGLE);
[email protected]f48b9432011-01-11 07:25:401277 }
1278 }
1279}
1280
mmenke24379d52016-02-05 23:50:171281int CookieMonster::DeleteCanonicalCookie(const CanonicalCookie& cookie) {
mmenkebe0910d2016-03-01 19:09:091282 DCHECK(thread_checker_.CalledOnValidThread());
mmenke24379d52016-02-05 23:50:171283
1284 for (CookieMapItPair its = cookies_.equal_range(GetKey(cookie.Domain()));
1285 its.first != its.second; ++its.first) {
1286 // The creation date acts as the unique index...
1287 if (its.first->second->CreationDate() == cookie.CreationDate()) {
nharper68903362017-01-20 04:07:141288 InternalDeleteCookie(its.first, true, DELETE_COOKIE_CANONICAL);
mmenke24379d52016-02-05 23:50:171289 return 1;
1290 }
1291 }
1292 return 0;
1293}
1294
mmenke74bcbd52016-01-21 17:17:561295bool CookieMonster::SetCookieWithCreationTime(const GURL& url,
1296 const std::string& cookie_line,
1297 const base::Time& creation_time) {
mmenkebe0910d2016-03-01 19:09:091298 DCHECK(thread_checker_.CalledOnValidThread());
mmenke74bcbd52016-01-21 17:17:561299 DCHECK(!store_.get()) << "This method is only to be used by unit-tests.";
mmenke74bcbd52016-01-21 17:17:561300
1301 if (!HasCookieableScheme(url)) {
1302 return false;
1303 }
1304
1305 MarkCookieStoreAsInitialized();
1306 if (ShouldFetchAllCookiesWhenFetchingAnyCookie())
1307 FetchAllCookiesIfNecessary();
1308
1309 return SetCookieWithCreationTimeAndOptions(url, cookie_line, creation_time,
1310 CookieOptions());
1311}
1312
[email protected]264807b2012-04-25 14:49:371313int CookieMonster::DeleteSessionCookies() {
mmenkebe0910d2016-03-01 19:09:091314 DCHECK(thread_checker_.CalledOnValidThread());
[email protected]264807b2012-04-25 14:49:371315
1316 int num_deleted = 0;
1317 for (CookieMap::iterator it = cookies_.begin(); it != cookies_.end();) {
1318 CookieMap::iterator curit = it;
avie7cd11a2016-10-11 02:00:351319 CanonicalCookie* cc = curit->second.get();
[email protected]264807b2012-04-25 14:49:371320 ++it;
1321
1322 if (!cc->IsPersistent()) {
mkwstbe84af312015-02-20 08:52:451323 InternalDeleteCookie(curit, true, /*sync_to_store*/
[email protected]264807b2012-04-25 14:49:371324 DELETE_COOKIE_EXPIRED);
1325 ++num_deleted;
1326 }
1327 }
1328
1329 return num_deleted;
1330}
1331
erikchen1dd72a72015-05-06 20:45:051332void CookieMonster::MarkCookieStoreAsInitialized() {
mmenkebe0910d2016-03-01 19:09:091333 DCHECK(thread_checker_.CalledOnValidThread());
erikchen1dd72a72015-05-06 20:45:051334 initialized_ = true;
1335}
1336
1337void CookieMonster::FetchAllCookiesIfNecessary() {
mmenkebe0910d2016-03-01 19:09:091338 DCHECK(thread_checker_.CalledOnValidThread());
erikchen1dd72a72015-05-06 20:45:051339 if (store_.get() && !started_fetching_all_cookies_) {
1340 started_fetching_all_cookies_ = true;
1341 FetchAllCookies();
1342 }
1343}
1344
mmenke74bcbd52016-01-21 17:17:561345void CookieMonster::FetchAllCookies() {
mmenkebe0910d2016-03-01 19:09:091346 DCHECK(thread_checker_.CalledOnValidThread());
mmenke74bcbd52016-01-21 17:17:561347 DCHECK(store_.get()) << "Store must exist to initialize";
1348 DCHECK(!finished_fetching_all_cookies_)
1349 << "All cookies have already been fetched.";
1350
1351 // We bind in the current time so that we can report the wall-clock time for
1352 // loading cookies.
mmenkebe0910d2016-03-01 19:09:091353 store_->Load(base::Bind(&CookieMonster::OnLoaded,
1354 weak_ptr_factory_.GetWeakPtr(), TimeTicks::Now()));
mmenke74bcbd52016-01-21 17:17:561355}
1356
erikchen1dd72a72015-05-06 20:45:051357bool CookieMonster::ShouldFetchAllCookiesWhenFetchingAnyCookie() {
mmenkebe0910d2016-03-01 19:09:091358 DCHECK(thread_checker_.CalledOnValidThread());
1359
erikchen1dd72a72015-05-06 20:45:051360 if (fetch_strategy_ == kUnknownFetch) {
1361 const std::string group_name =
1362 base::FieldTrialList::FindFullName(kCookieMonsterFetchStrategyName);
1363 if (group_name == kFetchWhenNecessaryName) {
1364 fetch_strategy_ = kFetchWhenNecessary;
1365 } else if (group_name == kAlwaysFetchName) {
1366 fetch_strategy_ = kAlwaysFetch;
1367 } else {
1368 // The logic in the conditional is redundant, but it makes trials of
1369 // the Finch experiment more explicit.
1370 fetch_strategy_ = kAlwaysFetch;
1371 }
1372 }
1373
1374 return fetch_strategy_ == kAlwaysFetch;
1375}
1376
avie7cd11a2016-10-11 02:00:351377void CookieMonster::OnLoaded(
1378 TimeTicks beginning_time,
1379 std::vector<std::unique_ptr<CanonicalCookie>> cookies) {
mmenkebe0910d2016-03-01 19:09:091380 DCHECK(thread_checker_.CalledOnValidThread());
avie7cd11a2016-10-11 02:00:351381 StoreLoadedCookies(std::move(cookies));
[email protected]c7593fb22011-11-14 23:54:271382 histogram_time_blocked_on_load_->AddTime(TimeTicks::Now() - beginning_time);
[email protected]218aa6a12011-09-13 17:38:381383
1384 // Invoke the task queue of cookie request.
1385 InvokeQueue();
1386}
1387
avie7cd11a2016-10-11 02:00:351388void CookieMonster::OnKeyLoaded(
1389 const std::string& key,
1390 std::vector<std::unique_ptr<CanonicalCookie>> cookies) {
mmenkebe0910d2016-03-01 19:09:091391 DCHECK(thread_checker_.CalledOnValidThread());
1392
avie7cd11a2016-10-11 02:00:351393 StoreLoadedCookies(std::move(cookies));
[email protected]85620342011-10-17 17:35:041394
mmenkebe0910d2016-03-01 19:09:091395 auto tasks_pending_for_key = tasks_pending_for_key_.find(key);
[email protected]85620342011-10-17 17:35:041396
mmenkebe0910d2016-03-01 19:09:091397 // TODO(mmenke): Can this be turned into a DCHECK?
1398 if (tasks_pending_for_key == tasks_pending_for_key_.end())
1399 return;
[email protected]bab72ec2013-10-30 20:50:021400
mmenkebe0910d2016-03-01 19:09:091401 // Run all tasks for the key. Note that running a task can result in multiple
1402 // tasks being added to the back of the deque.
1403 while (!tasks_pending_for_key->second.empty()) {
1404 scoped_refptr<CookieMonsterTask> task =
1405 tasks_pending_for_key->second.front();
1406 tasks_pending_for_key->second.pop_front();
1407
1408 task->Run();
[email protected]85620342011-10-17 17:35:041409 }
mmenkebe0910d2016-03-01 19:09:091410
1411 tasks_pending_for_key_.erase(tasks_pending_for_key);
1412
1413 // This has to be done last, in case running a task queues a new task for the
1414 // key, to ensure tasks are run in the correct order.
1415 keys_loaded_.insert(key);
[email protected]85620342011-10-17 17:35:041416}
1417
[email protected]218aa6a12011-09-13 17:38:381418void CookieMonster::StoreLoadedCookies(
avie7cd11a2016-10-11 02:00:351419 std::vector<std::unique_ptr<CanonicalCookie>> cookies) {
mmenkebe0910d2016-03-01 19:09:091420 DCHECK(thread_checker_.CalledOnValidThread());
1421
pkastingec2cdb52015-05-02 01:19:341422 // TODO(erikwright): Remove ScopedTracker below once crbug.com/457528 is
1423 // fixed.
1424 tracked_objects::ScopedTracker tracking_profile(
1425 FROM_HERE_WITH_EXPLICIT_FUNCTION(
1426 "457528 CookieMonster::StoreLoadedCookies"));
1427
mmenkebe0910d2016-03-01 19:09:091428 // Even if a key is expired, insert it so it can be garbage collected,
1429 // removed, and sync'd.
[email protected]6210ce52013-09-20 03:33:141430 CookieItVector cookies_with_control_chars;
1431
avie7cd11a2016-10-11 02:00:351432 for (auto& cookie : cookies) {
1433 int64_t cookie_creation_time = cookie->CreationDate().ToInternalValue();
[email protected]f48b9432011-01-11 07:25:401434
[email protected]85620342011-10-17 17:35:041435 if (creation_times_.insert(cookie_creation_time).second) {
avie7cd11a2016-10-11 02:00:351436 CanonicalCookie* cookie_ptr = cookie.get();
1437 CookieMap::iterator inserted = InternalInsertCookie(
1438 GetKey(cookie_ptr->Domain()), std::move(cookie), GURL(), false);
1439 const Time cookie_access_time(cookie_ptr->LastAccessDate());
[email protected]85620342011-10-17 17:35:041440 if (earliest_access_time_.is_null() ||
1441 cookie_access_time < earliest_access_time_)
1442 earliest_access_time_ = cookie_access_time;
[email protected]6210ce52013-09-20 03:33:141443
avie7cd11a2016-10-11 02:00:351444 if (ContainsControlCharacter(cookie_ptr->Name()) ||
1445 ContainsControlCharacter(cookie_ptr->Value())) {
mkwstbe84af312015-02-20 08:52:451446 cookies_with_control_chars.push_back(inserted);
[email protected]6210ce52013-09-20 03:33:141447 }
[email protected]f48b9432011-01-11 07:25:401448 } else {
mkwstbe84af312015-02-20 08:52:451449 LOG(ERROR) << base::StringPrintf(
1450 "Found cookies with duplicate creation "
1451 "times in backing store: "
1452 "{name='%s', domain='%s', path='%s'}",
avie7cd11a2016-10-11 02:00:351453 cookie->Name().c_str(), cookie->Domain().c_str(),
1454 cookie->Path().c_str());
[email protected]f48b9432011-01-11 07:25:401455 }
1456 }
[email protected]f48b9432011-01-11 07:25:401457
[email protected]6210ce52013-09-20 03:33:141458 // Any cookies that contain control characters that we have loaded from the
1459 // persistent store should be deleted. See http://crbug.com/238041.
1460 for (CookieItVector::iterator it = cookies_with_control_chars.begin();
1461 it != cookies_with_control_chars.end();) {
1462 CookieItVector::iterator curit = it;
1463 ++it;
1464
1465 InternalDeleteCookie(*curit, true, DELETE_COOKIE_CONTROL_CHAR);
1466 }
1467
[email protected]f48b9432011-01-11 07:25:401468 // After importing cookies from the PersistentCookieStore, verify that
1469 // none of our other constraints are violated.
[email protected]f48b9432011-01-11 07:25:401470 // In particular, the backing store might have given us duplicate cookies.
[email protected]85620342011-10-17 17:35:041471
1472 // This method could be called multiple times due to priority loading, thus
1473 // cookies loaded in previous runs will be validated again, but this is OK
1474 // since they are expected to be much fewer than total DB.
[email protected]f48b9432011-01-11 07:25:401475 EnsureCookiesMapIsValid();
[email protected]218aa6a12011-09-13 17:38:381476}
[email protected]f48b9432011-01-11 07:25:401477
[email protected]218aa6a12011-09-13 17:38:381478void CookieMonster::InvokeQueue() {
mmenkebe0910d2016-03-01 19:09:091479 DCHECK(thread_checker_.CalledOnValidThread());
1480
mmenkef49fca0e2016-03-08 12:46:241481 // Move all per-key tasks into the global queue, if there are any. This is
1482 // protection about a race where the store learns about all cookies loading
1483 // before it learned about the cookies for a key loading.
1484
1485 // Needed to prevent any recursively queued tasks from going back into the
1486 // per-key queues.
1487 seen_global_task_ = true;
1488 for (const auto& tasks_for_key : tasks_pending_for_key_) {
1489 tasks_pending_.insert(tasks_pending_.begin(), tasks_for_key.second.begin(),
1490 tasks_for_key.second.end());
1491 }
1492 tasks_pending_for_key_.clear();
1493
mmenkebe0910d2016-03-01 19:09:091494 while (!tasks_pending_.empty()) {
1495 scoped_refptr<CookieMonsterTask> request_task = tasks_pending_.front();
mmenkef49fca0e2016-03-08 12:46:241496 tasks_pending_.pop_front();
[email protected]218aa6a12011-09-13 17:38:381497 request_task->Run();
1498 }
mmenkebe0910d2016-03-01 19:09:091499
mmenkef49fca0e2016-03-08 12:46:241500 DCHECK(tasks_pending_for_key_.empty());
1501
mmenkebe0910d2016-03-01 19:09:091502 finished_fetching_all_cookies_ = true;
1503 creation_times_.clear();
1504 keys_loaded_.clear();
[email protected]f48b9432011-01-11 07:25:401505}
1506
1507void CookieMonster::EnsureCookiesMapIsValid() {
mmenkebe0910d2016-03-01 19:09:091508 DCHECK(thread_checker_.CalledOnValidThread());
[email protected]f48b9432011-01-11 07:25:401509
[email protected]f48b9432011-01-11 07:25:401510 // Iterate through all the of the cookies, grouped by host.
1511 CookieMap::iterator prev_range_end = cookies_.begin();
1512 while (prev_range_end != cookies_.end()) {
1513 CookieMap::iterator cur_range_begin = prev_range_end;
1514 const std::string key = cur_range_begin->first; // Keep a copy.
1515 CookieMap::iterator cur_range_end = cookies_.upper_bound(key);
1516 prev_range_end = cur_range_end;
1517
1518 // Ensure no equivalent cookies for this host.
ellyjonescabf57422015-08-21 18:44:511519 TrimDuplicateCookiesForKey(key, cur_range_begin, cur_range_end);
[email protected]f48b9432011-01-11 07:25:401520 }
[email protected]f48b9432011-01-11 07:25:401521}
1522
ellyjonescabf57422015-08-21 18:44:511523void CookieMonster::TrimDuplicateCookiesForKey(const std::string& key,
1524 CookieMap::iterator begin,
1525 CookieMap::iterator end) {
mmenkebe0910d2016-03-01 19:09:091526 DCHECK(thread_checker_.CalledOnValidThread());
[email protected]f48b9432011-01-11 07:25:401527
1528 // Set of cookies ordered by creation time.
1529 typedef std::set<CookieMap::iterator, OrderByCreationTimeDesc> CookieSet;
1530
1531 // Helper map we populate to find the duplicates.
1532 typedef std::map<CookieSignature, CookieSet> EquivalenceMap;
1533 EquivalenceMap equivalent_cookies;
1534
1535 // The number of duplicate cookies that have been found.
1536 int num_duplicates = 0;
1537
1538 // Iterate through all of the cookies in our range, and insert them into
1539 // the equivalence map.
1540 for (CookieMap::iterator it = begin; it != end; ++it) {
1541 DCHECK_EQ(key, it->first);
avie7cd11a2016-10-11 02:00:351542 CanonicalCookie* cookie = it->second.get();
[email protected]f48b9432011-01-11 07:25:401543
mkwstbe84af312015-02-20 08:52:451544 CookieSignature signature(cookie->Name(), cookie->Domain(), cookie->Path());
[email protected]f48b9432011-01-11 07:25:401545 CookieSet& set = equivalent_cookies[signature];
1546
1547 // We found a duplicate!
1548 if (!set.empty())
1549 num_duplicates++;
1550
1551 // We save the iterator into |cookies_| rather than the actual cookie
1552 // pointer, since we may need to delete it later.
1553 bool insert_success = set.insert(it).second;
mkwstbe84af312015-02-20 08:52:451554 DCHECK(insert_success)
1555 << "Duplicate creation times found in duplicate cookie name scan.";
[email protected]f48b9432011-01-11 07:25:401556 }
1557
1558 // If there were no duplicates, we are done!
1559 if (num_duplicates == 0)
ellyjonescabf57422015-08-21 18:44:511560 return;
[email protected]f48b9432011-01-11 07:25:401561
1562 // Make sure we find everything below that we did above.
1563 int num_duplicates_found = 0;
1564
1565 // Otherwise, delete all the duplicate cookies, both from our in-memory store
1566 // and from the backing store.
1567 for (EquivalenceMap::iterator it = equivalent_cookies.begin();
mkwstbe84af312015-02-20 08:52:451568 it != equivalent_cookies.end(); ++it) {
[email protected]f48b9432011-01-11 07:25:401569 const CookieSignature& signature = it->first;
1570 CookieSet& dupes = it->second;
1571
1572 if (dupes.size() <= 1)
1573 continue; // This cookiename/path has no duplicates.
1574 num_duplicates_found += dupes.size() - 1;
1575
1576 // Since |dups| is sorted by creation time (descending), the first cookie
1577 // is the most recent one, so we will keep it. The rest are duplicates.
1578 dupes.erase(dupes.begin());
1579
1580 LOG(ERROR) << base::StringPrintf(
1581 "Found %d duplicate cookies for host='%s', "
1582 "with {name='%s', domain='%s', path='%s'}",
mkwstbe84af312015-02-20 08:52:451583 static_cast<int>(dupes.size()), key.c_str(), signature.name.c_str(),
1584 signature.domain.c_str(), signature.path.c_str());
[email protected]f48b9432011-01-11 07:25:401585
1586 // Remove all the cookies identified by |dupes|. It is valid to delete our
1587 // list of iterators one at a time, since |cookies_| is a multimap (they
1588 // don't invalidate existing iterators following deletion).
mkwstbe84af312015-02-20 08:52:451589 for (CookieSet::iterator dupes_it = dupes.begin(); dupes_it != dupes.end();
[email protected]f48b9432011-01-11 07:25:401590 ++dupes_it) {
[email protected]218aa6a12011-09-13 17:38:381591 InternalDeleteCookie(*dupes_it, true,
[email protected]f48b9432011-01-11 07:25:401592 DELETE_COOKIE_DUPLICATE_IN_BACKING_STORE);
1593 }
1594 }
1595 DCHECK_EQ(num_duplicates, num_duplicates_found);
[email protected]f48b9432011-01-11 07:25:401596}
1597
[email protected]f48b9432011-01-11 07:25:401598void CookieMonster::FindCookiesForHostAndDomain(
1599 const GURL& url,
1600 const CookieOptions& options,
[email protected]f48b9432011-01-11 07:25:401601 std::vector<CanonicalCookie*>* cookies) {
mmenkebe0910d2016-03-01 19:09:091602 DCHECK(thread_checker_.CalledOnValidThread());
[email protected]f48b9432011-01-11 07:25:401603
1604 const Time current_time(CurrentTime());
1605
1606 // Probe to save statistics relatively frequently. We do it here rather
1607 // than in the set path as many websites won't set cookies, and we
1608 // want to collect statistics whenever the browser's being used.
1609 RecordPeriodicStats(current_time);
1610
[email protected]8e1583672012-02-11 04:39:411611 // Can just dispatch to FindCookiesForKey
1612 const std::string key(GetKey(url.host()));
mkwst72b65162016-02-22 19:58:541613 FindCookiesForKey(key, url, options, current_time, cookies);
[email protected]f48b9432011-01-11 07:25:401614}
1615
[email protected]dedec0b2013-02-28 04:50:101616void CookieMonster::FindCookiesForKey(const std::string& key,
1617 const GURL& url,
1618 const CookieOptions& options,
1619 const Time& current,
[email protected]dedec0b2013-02-28 04:50:101620 std::vector<CanonicalCookie*>* cookies) {
mmenkebe0910d2016-03-01 19:09:091621 DCHECK(thread_checker_.CalledOnValidThread());
[email protected]f48b9432011-01-11 07:25:401622
[email protected]f48b9432011-01-11 07:25:401623 for (CookieMapItPair its = cookies_.equal_range(key);
mkwstbe84af312015-02-20 08:52:451624 its.first != its.second;) {
[email protected]f48b9432011-01-11 07:25:401625 CookieMap::iterator curit = its.first;
avie7cd11a2016-10-11 02:00:351626 CanonicalCookie* cc = curit->second.get();
[email protected]f48b9432011-01-11 07:25:401627 ++its.first;
1628
1629 // If the cookie is expired, delete it.
mmenke3c79a652016-02-12 14:39:201630 if (cc->IsExpired(current)) {
[email protected]f48b9432011-01-11 07:25:401631 InternalDeleteCookie(curit, true, DELETE_COOKIE_EXPIRED);
1632 continue;
1633 }
1634
[email protected]65f4e7e2012-12-12 21:56:541635 // Filter out cookies that should not be included for a request to the
1636 // given |url|. HTTP only cookies are filtered depending on the passed
1637 // cookie |options|.
1638 if (!cc->IncludeForRequestURL(url, options))
[email protected]f48b9432011-01-11 07:25:401639 continue;
1640
[email protected]65f4e7e2012-12-12 21:56:541641 // Add this cookie to the set of matching cookies. Update the access
[email protected]f48b9432011-01-11 07:25:401642 // time if we've been requested to do so.
mkwst72b65162016-02-22 19:58:541643 if (options.update_access_time()) {
[email protected]f48b9432011-01-11 07:25:401644 InternalUpdateCookieAccessTime(cc, current);
1645 }
1646 cookies->push_back(cc);
1647 }
1648}
1649
1650bool CookieMonster::DeleteAnyEquivalentCookie(const std::string& key,
1651 const CanonicalCookie& ecc,
mmenke009cf62e2016-07-18 19:33:311652 const GURL& source_url,
[email protected]e7c590e52011-03-30 08:33:551653 bool skip_httponly,
jwwa26e439d2017-01-27 18:17:271654 bool already_expired) {
mmenkebe0910d2016-03-01 19:09:091655 DCHECK(thread_checker_.CalledOnValidThread());
[email protected]f48b9432011-01-11 07:25:401656
1657 bool found_equivalent_cookie = false;
1658 bool skipped_httponly = false;
jww601411a2015-11-20 19:46:571659 bool skipped_secure_cookie = false;
jww31e32632015-12-16 23:38:341660
1661 histogram_cookie_delete_equivalent_->Add(COOKIE_DELETE_EQUIVALENT_ATTEMPT);
1662
[email protected]f48b9432011-01-11 07:25:401663 for (CookieMapItPair its = cookies_.equal_range(key);
mkwstbe84af312015-02-20 08:52:451664 its.first != its.second;) {
[email protected]f48b9432011-01-11 07:25:401665 CookieMap::iterator curit = its.first;
avie7cd11a2016-10-11 02:00:351666 CanonicalCookie* cc = curit->second.get();
[email protected]f48b9432011-01-11 07:25:401667 ++its.first;
1668
jwwa26e439d2017-01-27 18:17:271669 // If the cookie is being set from an insecure scheme, then if a cookie
1670 // already exists with the same name and it is Secure, then the cookie
1671 // should *not* be updated if they domain-match and ignoring the path
1672 // attribute.
jww601411a2015-11-20 19:46:571673 //
jwwa26e439d2017-01-27 18:17:271674 // See: https://tools.ietf.org/html/draft-ietf-httpbis-cookie-alone
1675 if (cc->IsSecure() && !source_url.SchemeIsCryptographic() &&
mmenke2830b0722016-07-20 16:02:501676 ecc.IsEquivalentForSecureCookieMatching(*cc)) {
jww601411a2015-11-20 19:46:571677 skipped_secure_cookie = true;
jww31e32632015-12-16 23:38:341678 histogram_cookie_delete_equivalent_->Add(
1679 COOKIE_DELETE_EQUIVALENT_SKIPPING_SECURE);
1680 // If the cookie is equivalent to the new cookie and wouldn't have been
1681 // skipped for being HTTP-only, record that it is a skipped secure cookie
1682 // that would have been deleted otherwise.
1683 if (ecc.IsEquivalent(*cc)) {
jwwa9a0d482015-12-16 18:19:411684 found_equivalent_cookie = true;
jww31e32632015-12-16 23:38:341685
1686 if (!skip_httponly || !cc->IsHttpOnly()) {
1687 histogram_cookie_delete_equivalent_->Add(
1688 COOKIE_DELETE_EQUIVALENT_WOULD_HAVE_DELETED);
1689 }
1690 }
jww601411a2015-11-20 19:46:571691 } else if (ecc.IsEquivalent(*cc)) {
[email protected]f48b9432011-01-11 07:25:401692 // We should never have more than one equivalent cookie, since they should
jww601411a2015-11-20 19:46:571693 // overwrite each other, unless secure cookies require secure scheme is
1694 // being enforced. In that case, cookies with different paths might exist
1695 // and be considered equivalent.
mkwstbe84af312015-02-20 08:52:451696 CHECK(!found_equivalent_cookie)
1697 << "Duplicate equivalent cookies found, cookie store is corrupted.";
[email protected]f48b9432011-01-11 07:25:401698 if (skip_httponly && cc->IsHttpOnly()) {
1699 skipped_httponly = true;
1700 } else {
jww31e32632015-12-16 23:38:341701 histogram_cookie_delete_equivalent_->Add(
1702 COOKIE_DELETE_EQUIVALENT_FOUND);
mkwstbe84af312015-02-20 08:52:451703 InternalDeleteCookie(curit, true, already_expired
1704 ? DELETE_COOKIE_EXPIRED_OVERWRITE
1705 : DELETE_COOKIE_OVERWRITE);
[email protected]f48b9432011-01-11 07:25:401706 }
1707 found_equivalent_cookie = true;
1708 }
1709 }
jww601411a2015-11-20 19:46:571710 return skipped_httponly || skipped_secure_cookie;
[email protected]f48b9432011-01-11 07:25:401711}
1712
[email protected]6210ce52013-09-20 03:33:141713CookieMonster::CookieMap::iterator CookieMonster::InternalInsertCookie(
1714 const std::string& key,
avie7cd11a2016-10-11 02:00:351715 std::unique_ptr<CanonicalCookie> cc,
mmenke009cf62e2016-07-18 19:33:311716 const GURL& source_url,
[email protected]6210ce52013-09-20 03:33:141717 bool sync_to_store) {
mmenkebe0910d2016-03-01 19:09:091718 DCHECK(thread_checker_.CalledOnValidThread());
avie7cd11a2016-10-11 02:00:351719 CanonicalCookie* cc_ptr = cc.get();
mmenkebe0910d2016-03-01 19:09:091720
avie7cd11a2016-10-11 02:00:351721 if ((cc_ptr->IsPersistent() || persist_session_cookies_) && store_.get() &&
[email protected]90499482013-06-01 00:39:501722 sync_to_store)
avie7cd11a2016-10-11 02:00:351723 store_->AddCookie(*cc_ptr);
[email protected]6210ce52013-09-20 03:33:141724 CookieMap::iterator inserted =
avie7cd11a2016-10-11 02:00:351725 cookies_.insert(CookieMap::value_type(key, std::move(cc)));
1726 if (delegate_.get()) {
1727 delegate_->OnCookieChanged(*cc_ptr, false,
1728 CookieStore::ChangeCause::INSERTED);
1729 }
mkwstc1aa4cc2015-04-03 19:57:451730
1731 // See InitializeHistograms() for details.
avie7cd11a2016-10-11 02:00:351732 int32_t type_sample = cc_ptr->SameSite() != CookieSameSite::NO_RESTRICTION
mkwste1a29582016-03-15 10:07:521733 ? 1 << COOKIE_TYPE_SAME_SITE
1734 : 0;
avie7cd11a2016-10-11 02:00:351735 type_sample |= cc_ptr->IsHttpOnly() ? 1 << COOKIE_TYPE_HTTPONLY : 0;
1736 type_sample |= cc_ptr->IsSecure() ? 1 << COOKIE_TYPE_SECURE : 0;
mkwst46549412016-02-01 10:05:371737 histogram_cookie_type_->Add(type_sample);
estark7feb65c2b2015-08-21 23:38:201738
1739 // Histogram the type of scheme used on URLs that set cookies. This
1740 // intentionally includes cookies that are set or overwritten by
1741 // http:// URLs, but not cookies that are cleared by http:// URLs, to
1742 // understand if the former behavior can be deprecated for Secure
1743 // cookies.
mmenke009cf62e2016-07-18 19:33:311744 if (!source_url.is_empty()) {
estark7feb65c2b2015-08-21 23:38:201745 CookieSource cookie_source_sample;
mmenke009cf62e2016-07-18 19:33:311746 if (source_url.SchemeIsCryptographic()) {
estark7feb65c2b2015-08-21 23:38:201747 cookie_source_sample =
avie7cd11a2016-10-11 02:00:351748 cc_ptr->IsSecure()
1749 ? COOKIE_SOURCE_SECURE_COOKIE_CRYPTOGRAPHIC_SCHEME
1750 : COOKIE_SOURCE_NONSECURE_COOKIE_CRYPTOGRAPHIC_SCHEME;
estark7feb65c2b2015-08-21 23:38:201751 } else {
1752 cookie_source_sample =
avie7cd11a2016-10-11 02:00:351753 cc_ptr->IsSecure()
estark7feb65c2b2015-08-21 23:38:201754 ? COOKIE_SOURCE_SECURE_COOKIE_NONCRYPTOGRAPHIC_SCHEME
1755 : COOKIE_SOURCE_NONSECURE_COOKIE_NONCRYPTOGRAPHIC_SCHEME;
1756 }
1757 histogram_cookie_source_scheme_->Add(cookie_source_sample);
1758 }
mkwstc1aa4cc2015-04-03 19:57:451759
avie7cd11a2016-10-11 02:00:351760 RunCookieChangedCallbacks(*cc_ptr, CookieStore::ChangeCause::INSERTED);
[email protected]6210ce52013-09-20 03:33:141761
1762 return inserted;
[email protected]f48b9432011-01-11 07:25:401763}
1764
[email protected]34602282010-02-03 22:14:151765bool CookieMonster::SetCookieWithCreationTimeAndOptions(
1766 const GURL& url,
1767 const std::string& cookie_line,
1768 const Time& creation_time_or_null,
1769 const CookieOptions& options) {
mmenkebe0910d2016-03-01 19:09:091770 DCHECK(thread_checker_.CalledOnValidThread());
initial.commit586acc5fe2008-07-26 22:42:521771
[email protected]4d3ce782010-10-29 18:31:281772 VLOG(kVlogSetCookies) << "SetCookie() line: " << cookie_line;
initial.commit586acc5fe2008-07-26 22:42:521773
[email protected]34602282010-02-03 22:14:151774 Time creation_time = creation_time_or_null;
1775 if (creation_time.is_null()) {
1776 creation_time = CurrentTime();
1777 last_time_seen_ = creation_time;
1778 }
1779
danakja9850e12016-04-18 22:28:081780 std::unique_ptr<CanonicalCookie> cc(
[email protected]abbd13b2012-11-15 17:54:201781 CanonicalCookie::Create(url, cookie_line, creation_time, options));
initial.commit586acc5fe2008-07-26 22:42:521782
1783 if (!cc.get()) {
[email protected]4d3ce782010-10-29 18:31:281784 VLOG(kVlogSetCookies) << "WARNING: Failed to allocate CanonicalCookie";
initial.commit586acc5fe2008-07-26 22:42:521785 return false;
1786 }
mmenke009cf62e2016-07-18 19:33:311787 return SetCanonicalCookie(std::move(cc), url, options);
[email protected]f325f1e12010-04-30 22:38:551788}
initial.commit586acc5fe2008-07-26 22:42:521789
danakja9850e12016-04-18 22:28:081790bool CookieMonster::SetCanonicalCookie(std::unique_ptr<CanonicalCookie> cc,
mmenke009cf62e2016-07-18 19:33:311791 const GURL& source_url,
[email protected]f325f1e12010-04-30 22:38:551792 const CookieOptions& options) {
mmenkebe0910d2016-03-01 19:09:091793 DCHECK(thread_checker_.CalledOnValidThread());
1794
mmenkeea4cd402016-02-02 04:03:101795 Time creation_time = cc->CreationDate();
1796 const std::string key(GetKey(cc->Domain()));
1797 bool already_expired = cc->IsExpired(creation_time);
ellyjones399e35a22014-10-27 11:09:561798
mmenke009cf62e2016-07-18 19:33:311799 if (DeleteAnyEquivalentCookie(key, *cc, source_url,
jwwa26e439d2017-01-27 18:17:271800 options.exclude_httponly(), already_expired)) {
jww601411a2015-11-20 19:46:571801 std::string error;
jwwa26e439d2017-01-27 18:17:271802 error =
1803 "SetCookie() not clobbering httponly cookie or secure cookie for "
1804 "insecure scheme";
jww601411a2015-11-20 19:46:571805
1806 VLOG(kVlogSetCookies) << error;
[email protected]3a96c742008-11-19 19:46:271807 return false;
1808 }
initial.commit586acc5fe2008-07-26 22:42:521809
mkwstbe84af312015-02-20 08:52:451810 VLOG(kVlogSetCookies) << "SetCookie() key: " << key
mmenkeea4cd402016-02-02 04:03:101811 << " cc: " << cc->DebugString();
initial.commit586acc5fe2008-07-26 22:42:521812
1813 // Realize that we might be setting an expired cookie, and the only point
1814 // was to delete the cookie which we've already done.
mmenke3c79a652016-02-12 14:39:201815 if (!already_expired) {
[email protected]374f58b2010-07-20 15:29:261816 // See InitializeHistograms() for details.
mmenkeea4cd402016-02-02 04:03:101817 if (cc->IsPersistent()) {
[email protected]8475bee2011-03-17 18:40:241818 histogram_expiration_duration_minutes_->Add(
mmenkeea4cd402016-02-02 04:03:101819 (cc->ExpiryDate() - creation_time).InMinutes());
[email protected]8475bee2011-03-17 18:40:241820 }
1821
avie7cd11a2016-10-11 02:00:351822 InternalInsertCookie(key, std::move(cc), source_url, true);
[email protected]348dd662013-03-13 20:25:071823 } else {
1824 VLOG(kVlogSetCookies) << "SetCookie() not storing already expired cookie.";
[email protected]c4058fb2010-06-22 17:25:261825 }
initial.commit586acc5fe2008-07-26 22:42:521826
1827 // We assume that hopefully setting a cookie will be less common than
1828 // querying a cookie. Since setting a cookie can put us over our limits,
1829 // make sure that we garbage collect... We can also make the assumption that
1830 // if a cookie was set, in the common case it will be used soon after,
1831 // and we will purge the expired cookies in GetCookies().
jwwa26e439d2017-01-27 18:17:271832 GarbageCollect(creation_time, key);
initial.commit586acc5fe2008-07-26 22:42:521833
1834 return true;
1835}
1836
drogerd5d1278c2015-03-17 19:21:511837bool CookieMonster::SetCanonicalCookies(const CookieList& list) {
mmenkebe0910d2016-03-01 19:09:091838 DCHECK(thread_checker_.CalledOnValidThread());
drogerd5d1278c2015-03-17 19:21:511839
ttuttle859dc7a2015-04-23 19:42:291840 CookieOptions options;
drogerd5d1278c2015-03-17 19:21:511841 options.set_include_httponly();
1842
mmenkeea4cd402016-02-02 04:03:101843 for (const auto& cookie : list) {
mmenke009cf62e2016-07-18 19:33:311844 // Use an empty GURL. This method does not support setting secure cookies.
ricea2deef682016-09-09 08:04:071845 if (!SetCanonicalCookie(base::MakeUnique<CanonicalCookie>(cookie), GURL(),
1846 options)) {
drogerd5d1278c2015-03-17 19:21:511847 return false;
mmenkeea4cd402016-02-02 04:03:101848 }
drogerd5d1278c2015-03-17 19:21:511849 }
1850
1851 return true;
1852}
1853
[email protected]7a964a72010-09-07 19:33:261854void CookieMonster::InternalUpdateCookieAccessTime(CanonicalCookie* cc,
1855 const Time& current) {
mmenkebe0910d2016-03-01 19:09:091856 DCHECK(thread_checker_.CalledOnValidThread());
[email protected]bb8905722010-05-21 17:29:041857
[email protected]77e0a462008-11-01 00:43:351858 // Based off the Mozilla code. When a cookie has been accessed recently,
1859 // don't bother updating its access time again. This reduces the number of
1860 // updates we do during pageload, which in turn reduces the chance our storage
1861 // backend will hit its batch thresholds and be forced to update.
[email protected]77e0a462008-11-01 00:43:351862 if ((current - cc->LastAccessDate()) < last_access_threshold_)
1863 return;
1864
1865 cc->SetLastAccessDate(current);
[email protected]90499482013-06-01 00:39:501866 if ((cc->IsPersistent() || persist_session_cookies_) && store_.get())
[email protected]77e0a462008-11-01 00:43:351867 store_->UpdateCookieAccessTime(*cc);
1868}
1869
[email protected]6210ce52013-09-20 03:33:141870// InternalDeleteCookies must not invalidate iterators other than the one being
1871// deleted.
initial.commit586acc5fe2008-07-26 22:42:521872void CookieMonster::InternalDeleteCookie(CookieMap::iterator it,
[email protected]c4058fb2010-06-22 17:25:261873 bool sync_to_store,
1874 DeletionCause deletion_cause) {
mmenkebe0910d2016-03-01 19:09:091875 DCHECK(thread_checker_.CalledOnValidThread());
[email protected]bb8905722010-05-21 17:29:041876
nharper352933e2016-09-30 18:24:571877 // Ideally, this would be asserted up where we define kChangeCauseMapping,
[email protected]8bb846f2011-03-23 12:08:181878 // but DeletionCause's visibility (or lack thereof) forces us to make
1879 // this check here.
nharper352933e2016-09-30 18:24:571880 static_assert(arraysize(kChangeCauseMapping) == DELETE_COOKIE_LAST_ENTRY + 1,
1881 "kChangeCauseMapping size should match DeletionCause size");
[email protected]8bb846f2011-03-23 12:08:181882
[email protected]374f58b2010-07-20 15:29:261883 // See InitializeHistograms() for details.
nharper68903362017-01-20 04:07:141884 DeletionCause deletion_cause_to_record = deletion_cause;
1885 if (deletion_cause >= DELETE_COOKIE_CREATED_BETWEEN &&
1886 deletion_cause <= DELETE_COOKIE_CANONICAL) {
1887 deletion_cause_to_record = DELETE_COOKIE_EXPLICIT;
1888 }
[email protected]7a964a72010-09-07 19:33:261889 if (deletion_cause != DELETE_COOKIE_DONT_RECORD)
nharper68903362017-01-20 04:07:141890 histogram_cookie_deletion_cause_->Add(deletion_cause_to_record);
[email protected]c4058fb2010-06-22 17:25:261891
avie7cd11a2016-10-11 02:00:351892 CanonicalCookie* cc = it->second.get();
xiyuan8dbb89892015-04-13 17:04:301893 VLOG(kVlogSetCookies) << "InternalDeleteCookie()"
1894 << ", cause:" << deletion_cause
1895 << ", cc: " << cc->DebugString();
[email protected]7a964a72010-09-07 19:33:261896
[email protected]90499482013-06-01 00:39:501897 if ((cc->IsPersistent() || persist_session_cookies_) && store_.get() &&
1898 sync_to_store)
initial.commit586acc5fe2008-07-26 22:42:521899 store_->DeleteCookie(*cc);
nharper352933e2016-09-30 18:24:571900 ChangeCausePair mapping = kChangeCauseMapping[deletion_cause];
1901 if (delegate_.get() && mapping.notify)
1902 delegate_->OnCookieChanged(*cc, true, mapping.cause);
1903 RunCookieChangedCallbacks(*cc, mapping.cause);
initial.commit586acc5fe2008-07-26 22:42:521904 cookies_.erase(it);
initial.commit586acc5fe2008-07-26 22:42:521905}
1906
[email protected]8807b322010-10-01 17:10:141907// Domain expiry behavior is unchanged by key/expiry scheme (the
[email protected]8ad5d462013-05-02 08:45:261908// meaning of the key is different, but that's not visible to this routine).
jww82d99c12015-11-25 18:39:531909size_t CookieMonster::GarbageCollect(const Time& current,
jwwa26e439d2017-01-27 18:17:271910 const std::string& key) {
mmenkebe0910d2016-03-01 19:09:091911 DCHECK(thread_checker_.CalledOnValidThread());
[email protected]bb8905722010-05-21 17:29:041912
jww82d99c12015-11-25 18:39:531913 size_t num_deleted = 0;
mkwstbe84af312015-02-20 08:52:451914 Time safe_date(Time::Now() - TimeDelta::FromDays(kSafeFromGlobalPurgeDays));
initial.commit586acc5fe2008-07-26 22:42:521915
[email protected]8ad5d462013-05-02 08:45:261916 // Collect garbage for this key, minding cookie priorities.
[email protected]7a964a72010-09-07 19:33:261917 if (cookies_.count(key) > kDomainMaxCookies) {
[email protected]4d3ce782010-10-29 18:31:281918 VLOG(kVlogGarbageCollection) << "GarbageCollect() key: " << key;
[email protected]7a964a72010-09-07 19:33:261919
mkwst87734352016-03-03 17:36:231920 CookieItVector* cookie_its;
jww601411a2015-11-20 19:46:571921
mkwst87734352016-03-03 17:36:231922 CookieItVector non_expired_cookie_its;
1923 cookie_its = &non_expired_cookie_its;
jww82d99c12015-11-25 18:39:531924 num_deleted +=
mkwst87734352016-03-03 17:36:231925 GarbageCollectExpired(current, cookies_.equal_range(key), cookie_its);
jww82d99c12015-11-25 18:39:531926
mkwst87734352016-03-03 17:36:231927 if (cookie_its->size() > kDomainMaxCookies) {
[email protected]8ad5d462013-05-02 08:45:261928 VLOG(kVlogGarbageCollection) << "Deep Garbage Collect domain.";
1929 size_t purge_goal =
mkwst87734352016-03-03 17:36:231930 cookie_its->size() - (kDomainMaxCookies - kDomainPurgeCookies);
[email protected]8ad5d462013-05-02 08:45:261931 DCHECK(purge_goal > kDomainPurgeCookies);
1932
mkwste079ac412016-03-11 09:04:061933 // Sort the cookies by access date, from least-recent to most-recent.
1934 std::sort(cookie_its->begin(), cookie_its->end(), LRACookieSorter);
[email protected]8ad5d462013-05-02 08:45:261935
mkwste079ac412016-03-11 09:04:061936 // Remove all but the kDomainCookiesQuotaLow most-recently accessed
1937 // cookies with low-priority. Then, if cookies still need to be removed,
1938 // bump the quota and remove low- and medium-priority. Then, if cookies
1939 // _still_ need to be removed, bump the quota and remove cookies with
1940 // any priority.
jwwc00ac712016-05-05 22:21:441941 //
1942 // 1. Low-priority non-secure cookies.
1943 // 2. Low-priority secure cookies.
1944 // 3. Medium-priority non-secure cookies.
1945 // 4. High-priority non-secure cookies.
1946 // 5. Medium-priority secure cookies.
1947 // 6. High-priority secure cookies.
1948 const static struct {
1949 CookiePriority priority;
1950 bool protect_secure_cookies;
1951 } purge_rounds[] = {
1952 // 1. Low-priority non-secure cookies.
1953 {COOKIE_PRIORITY_LOW, true},
1954 // 2. Low-priority secure cookies.
1955 {COOKIE_PRIORITY_LOW, false},
1956 // 3. Medium-priority non-secure cookies.
1957 {COOKIE_PRIORITY_MEDIUM, true},
1958 // 4. High-priority non-secure cookies.
1959 {COOKIE_PRIORITY_HIGH, true},
1960 // 5. Medium-priority secure cookies.
1961 {COOKIE_PRIORITY_MEDIUM, false},
1962 // 6. High-priority secure cookies.
1963 {COOKIE_PRIORITY_HIGH, false},
1964 };
1965
mkwste079ac412016-03-11 09:04:061966 size_t quota = 0;
jwwc00ac712016-05-05 22:21:441967 for (const auto& purge_round : purge_rounds) {
mmenke645ca6772016-06-17 18:46:431968 // Adjust quota according to the priority of cookies. Each round should
1969 // protect certain number of cookies in order to avoid starvation.
1970 // For example, when each round starts to remove cookies, the number of
1971 // cookies of that priority are counted and a decision whether they
1972 // should be deleted or not is made. If yes, some number of cookies of
1973 // that priority are deleted considering the quota.
jwwc00ac712016-05-05 22:21:441974 switch (purge_round.priority) {
1975 case COOKIE_PRIORITY_LOW:
mmenke645ca6772016-06-17 18:46:431976 quota = kDomainCookiesQuotaLow;
jwwc00ac712016-05-05 22:21:441977 break;
1978 case COOKIE_PRIORITY_MEDIUM:
mmenke645ca6772016-06-17 18:46:431979 quota = kDomainCookiesQuotaMedium;
jwwc00ac712016-05-05 22:21:441980 break;
1981 case COOKIE_PRIORITY_HIGH:
mmenke645ca6772016-06-17 18:46:431982 quota = kDomainCookiesQuotaHigh;
jwwc00ac712016-05-05 22:21:441983 break;
1984 }
jwwc00ac712016-05-05 22:21:441985 size_t just_deleted = 0u;
jwwa26e439d2017-01-27 18:17:271986 // Purge up to |purge_goal| for all cookies at the given priority. This
1987 // path will be taken only if the initial non-secure purge did not evict
1988 // enough cookies.
jwwc00ac712016-05-05 22:21:441989 if (purge_goal > 0) {
1990 just_deleted = PurgeLeastRecentMatches(
1991 cookie_its, purge_round.priority, quota, purge_goal,
1992 purge_round.protect_secure_cookies);
1993 DCHECK_LE(just_deleted, purge_goal);
1994 purge_goal -= just_deleted;
1995 num_deleted += just_deleted;
1996 }
mkwst162d2712016-02-18 18:21:291997 }
mkwste079ac412016-03-11 09:04:061998
jwwc00ac712016-05-05 22:21:441999 DCHECK_EQ(0u, purge_goal);
[email protected]8807b322010-10-01 17:10:142000 }
initial.commit586acc5fe2008-07-26 22:42:522001 }
2002
[email protected]8ad5d462013-05-02 08:45:262003 // Collect garbage for everything. With firefox style we want to preserve
2004 // cookies accessed in kSafeFromGlobalPurgeDays, otherwise evict.
mkwstbe84af312015-02-20 08:52:452005 if (cookies_.size() > kMaxCookies && earliest_access_time_ < safe_date) {
[email protected]4d3ce782010-10-29 18:31:282006 VLOG(kVlogGarbageCollection) << "GarbageCollect() everything";
[email protected]8ad5d462013-05-02 08:45:262007 CookieItVector cookie_its;
jww82d99c12015-11-25 18:39:532008
[email protected]7a964a72010-09-07 19:33:262009 num_deleted += GarbageCollectExpired(
2010 current, CookieMapItPair(cookies_.begin(), cookies_.end()),
2011 &cookie_its);
jww82d99c12015-11-25 18:39:532012
[email protected]8ad5d462013-05-02 08:45:262013 if (cookie_its.size() > kMaxCookies) {
2014 VLOG(kVlogGarbageCollection) << "Deep Garbage Collect everything.";
2015 size_t purge_goal = cookie_its.size() - (kMaxCookies - kPurgeCookies);
2016 DCHECK(purge_goal > kPurgeCookies);
jww82d99c12015-11-25 18:39:532017
jwwa26e439d2017-01-27 18:17:272018 CookieItVector secure_cookie_its;
2019 CookieItVector non_secure_cookie_its;
2020 SplitCookieVectorIntoSecureAndNonSecure(cookie_its, &secure_cookie_its,
2021 &non_secure_cookie_its);
2022 size_t non_secure_purge_goal =
mmenkef4721d992017-06-07 17:13:592023 std::min<size_t>(purge_goal, non_secure_cookie_its.size());
jww82d99c12015-11-25 18:39:532024
mmenkef4721d992017-06-07 17:13:592025 base::Time earliest_non_secure_access_time;
jwwa26e439d2017-01-27 18:17:272026 size_t just_deleted = GarbageCollectLeastRecentlyAccessed(
mmenkef4721d992017-06-07 17:13:592027 current, safe_date, non_secure_purge_goal, non_secure_cookie_its,
2028 &earliest_non_secure_access_time);
jwwa26e439d2017-01-27 18:17:272029 num_deleted += just_deleted;
jww82d99c12015-11-25 18:39:532030
mmenkef4721d992017-06-07 17:13:592031 if (secure_cookie_its.size() == 0) {
2032 // This case is unlikely, but should still update
2033 // |earliest_access_time_| if only have non-secure cookies.
2034 earliest_access_time_ = earliest_non_secure_access_time;
2035 // Garbage collection can't delete all cookies.
2036 DCHECK(!earliest_access_time_.is_null());
2037 } else if (just_deleted < purge_goal) {
2038 size_t secure_purge_goal = std::min<size_t>(purge_goal - just_deleted,
2039 secure_cookie_its.size());
2040 base::Time earliest_secure_access_time;
jww82d99c12015-11-25 18:39:532041 num_deleted += GarbageCollectLeastRecentlyAccessed(
mmenkef4721d992017-06-07 17:13:592042 current, safe_date, secure_purge_goal, secure_cookie_its,
2043 &earliest_secure_access_time);
2044
2045 if (!earliest_non_secure_access_time.is_null() &&
2046 earliest_non_secure_access_time < earliest_secure_access_time) {
2047 earliest_access_time_ = earliest_non_secure_access_time;
2048 } else {
2049 earliest_access_time_ = earliest_secure_access_time;
2050 }
2051
2052 // Garbage collection can't delete all cookies.
2053 DCHECK(!earliest_access_time_.is_null());
jww82d99c12015-11-25 18:39:532054 }
mmenkef4721d992017-06-07 17:13:592055
2056 // If there are secure cookies, but deleting non-secure cookies was enough
2057 // to meet the purge goal, secure cookies are never examined, so
2058 // |earliest_access_time_| can't be determined. Leaving it alone will mean
2059 // it's no later than the real earliest last access time, so this won't
2060 // lead to any problems.
[email protected]8807b322010-10-01 17:10:142061 }
[email protected]c890ed192008-10-30 23:45:532062 }
2063
2064 return num_deleted;
2065}
2066
mkwste079ac412016-03-11 09:04:062067size_t CookieMonster::PurgeLeastRecentMatches(CookieItVector* cookies,
2068 CookiePriority priority,
2069 size_t to_protect,
jwwc00ac712016-05-05 22:21:442070 size_t purge_goal,
2071 bool protect_secure_cookies) {
mkwste079ac412016-03-11 09:04:062072 DCHECK(thread_checker_.CalledOnValidThread());
2073
mmenke645ca6772016-06-17 18:46:432074 // 1. Count number of the cookies at |priority|
2075 size_t cookies_count_possibly_to_be_deleted = CountCookiesForPossibleDeletion(
2076 priority, cookies, false /* count all cookies */);
2077
2078 // 2. If |cookies_count_possibly_to_be_deleted| at |priority| is less than or
2079 // equal |to_protect|, skip round in order to preserve the quota. This
2080 // involves secure and non-secure cookies at |priority|.
2081 if (cookies_count_possibly_to_be_deleted <= to_protect)
2082 return 0u;
2083
2084 // 3. Calculate number of secure cookies at |priority|
2085 // and number of cookies at |priority| that can possibly be deleted.
2086 // It is guaranteed we do not delete more than |purge_goal| even if
2087 // |cookies_count_possibly_to_be_deleted| is higher.
2088 size_t secure_cookies = 0u;
jwwc00ac712016-05-05 22:21:442089 if (protect_secure_cookies) {
mmenke645ca6772016-06-17 18:46:432090 secure_cookies = CountCookiesForPossibleDeletion(
2091 priority, cookies, protect_secure_cookies /* count secure cookies */);
2092 cookies_count_possibly_to_be_deleted -=
2093 std::max(secure_cookies, to_protect - secure_cookies);
2094 } else {
2095 cookies_count_possibly_to_be_deleted -= to_protect;
jwwc00ac712016-05-05 22:21:442096 }
2097
mmenke645ca6772016-06-17 18:46:432098 size_t removed = 0u;
2099 size_t current = 0u;
2100 while ((removed < purge_goal && current < cookies->size()) &&
2101 cookies_count_possibly_to_be_deleted > 0) {
avie7cd11a2016-10-11 02:00:352102 const CanonicalCookie* current_cookie = cookies->at(current)->second.get();
mmenke645ca6772016-06-17 18:46:432103 // Only delete the current cookie if the priority is equal to
2104 // the current level.
jwwc00ac712016-05-05 22:21:442105 if (IsCookieEligibleForEviction(priority, protect_secure_cookies,
2106 current_cookie)) {
mkwstaa07ee82016-03-11 15:32:142107 InternalDeleteCookie(cookies->at(current), true,
2108 DELETE_COOKIE_EVICTED_DOMAIN);
mkwste079ac412016-03-11 09:04:062109 cookies->erase(cookies->begin() + current);
2110 removed++;
mmenke645ca6772016-06-17 18:46:432111 cookies_count_possibly_to_be_deleted--;
mkwste079ac412016-03-11 09:04:062112 } else {
2113 current++;
2114 }
2115 }
2116 return removed;
2117}
2118
jww82d99c12015-11-25 18:39:532119size_t CookieMonster::GarbageCollectExpired(const Time& current,
2120 const CookieMapItPair& itpair,
2121 CookieItVector* cookie_its) {
mmenkebe0910d2016-03-01 19:09:092122 DCHECK(thread_checker_.CalledOnValidThread());
[email protected]bb8905722010-05-21 17:29:042123
[email protected]c890ed192008-10-30 23:45:532124 int num_deleted = 0;
2125 for (CookieMap::iterator it = itpair.first, end = itpair.second; it != end;) {
2126 CookieMap::iterator curit = it;
2127 ++it;
2128
2129 if (curit->second->IsExpired(current)) {
[email protected]2f3f3592010-07-07 20:11:512130 InternalDeleteCookie(curit, true, DELETE_COOKIE_EXPIRED);
[email protected]c890ed192008-10-30 23:45:532131 ++num_deleted;
2132 } else if (cookie_its) {
2133 cookie_its->push_back(curit);
2134 }
initial.commit586acc5fe2008-07-26 22:42:522135 }
2136
2137 return num_deleted;
2138}
2139
jww82d99c12015-11-25 18:39:532140size_t CookieMonster::GarbageCollectDeleteRange(
2141 const Time& current,
2142 DeletionCause cause,
2143 CookieItVector::iterator it_begin,
2144 CookieItVector::iterator it_end) {
mmenkebe0910d2016-03-01 19:09:092145 DCHECK(thread_checker_.CalledOnValidThread());
2146
[email protected]8ad5d462013-05-02 08:45:262147 for (CookieItVector::iterator it = it_begin; it != it_end; it++) {
2148 histogram_evicted_last_access_minutes_->Add(
2149 (current - (*it)->second->LastAccessDate()).InMinutes());
2150 InternalDeleteCookie((*it), true, cause);
[email protected]c10da4b02010-03-25 14:38:322151 }
[email protected]8ad5d462013-05-02 08:45:262152 return it_end - it_begin;
[email protected]c10da4b02010-03-25 14:38:322153}
2154
mmenke74bcbd52016-01-21 17:17:562155size_t CookieMonster::GarbageCollectLeastRecentlyAccessed(
2156 const base::Time& current,
2157 const base::Time& safe_date,
2158 size_t purge_goal,
mmenkef4721d992017-06-07 17:13:592159 CookieItVector cookie_its,
2160 base::Time* earliest_time) {
2161 DCHECK_LE(purge_goal, cookie_its.size());
mmenkebe0910d2016-03-01 19:09:092162 DCHECK(thread_checker_.CalledOnValidThread());
2163
mmenkef4721d992017-06-07 17:13:592164 // Sorts up to *and including* |cookie_its[purge_goal]| (if it exists), so
2165 // |earliest_time| will be properly assigned even if
mmenke74bcbd52016-01-21 17:17:562166 // |global_purge_it| == |cookie_its.begin() + purge_goal|.
mmenkef4721d992017-06-07 17:13:592167 SortLeastRecentlyAccessed(
2168 cookie_its.begin(), cookie_its.end(),
2169 cookie_its.size() < purge_goal ? purge_goal + 1 : purge_goal);
mmenke74bcbd52016-01-21 17:17:562170 // Find boundary to cookies older than safe_date.
2171 CookieItVector::iterator global_purge_it = LowerBoundAccessDate(
2172 cookie_its.begin(), cookie_its.begin() + purge_goal, safe_date);
jwwa26e439d2017-01-27 18:17:272173 // Only delete the old cookies and delete non-secure ones first.
mmenke74bcbd52016-01-21 17:17:562174 size_t num_deleted =
2175 GarbageCollectDeleteRange(current, DELETE_COOKIE_EVICTED_GLOBAL,
2176 cookie_its.begin(), global_purge_it);
mmenkef4721d992017-06-07 17:13:592177 if (global_purge_it != cookie_its.end())
2178 *earliest_time = (*global_purge_it)->second->LastAccessDate();
mmenke74bcbd52016-01-21 17:17:562179 return num_deleted;
2180}
2181
[email protected]ed32c212013-05-14 20:49:292182// A wrapper around registry_controlled_domains::GetDomainAndRegistry
[email protected]f48b9432011-01-11 07:25:402183// to make clear we're creating a key for our local map. Here and
2184// in FindCookiesForHostAndDomain() are the only two places where
2185// we need to conditionalize based on key type.
2186//
2187// Note that this key algorithm explicitly ignores the scheme. This is
2188// because when we're entering cookies into the map from the backing store,
2189// we in general won't have the scheme at that point.
2190// In practical terms, this means that file cookies will be stored
2191// in the map either by an empty string or by UNC name (and will be
2192// limited by kMaxCookiesPerHost), and extension cookies will be stored
2193// based on the single extension id, as the extension id won't have the
2194// form of a DNS host and hence GetKey() will return it unchanged.
2195//
2196// Arguably the right thing to do here is to make the key
2197// algorithm dependent on the scheme, and make sure that the scheme is
2198// available everywhere the key must be obtained (specfically at backing
2199// store load time). This would require either changing the backing store
2200// database schema to include the scheme (far more trouble than it's worth), or
2201// separating out file cookies into their own CookieMonster instance and
2202// thus restricting each scheme to a single cookie monster (which might
2203// be worth it, but is still too much trouble to solve what is currently a
2204// non-problem).
2205std::string CookieMonster::GetKey(const std::string& domain) const {
mmenkebe0910d2016-03-01 19:09:092206 DCHECK(thread_checker_.CalledOnValidThread());
2207
[email protected]f48b9432011-01-11 07:25:402208 std::string effective_domain(
[email protected]ed32c212013-05-14 20:49:292209 registry_controlled_domains::GetDomainAndRegistry(
[email protected]aabe1792014-01-30 21:37:462210 domain, registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES));
[email protected]f48b9432011-01-11 07:25:402211 if (effective_domain.empty())
2212 effective_domain = domain;
2213
2214 if (!effective_domain.empty() && effective_domain[0] == '.')
2215 return effective_domain.substr(1);
2216 return effective_domain;
2217}
2218
2219bool CookieMonster::HasCookieableScheme(const GURL& url) {
mmenkebe0910d2016-03-01 19:09:092220 DCHECK(thread_checker_.CalledOnValidThread());
[email protected]f48b9432011-01-11 07:25:402221
2222 // Make sure the request is on a cookie-able url scheme.
2223 for (size_t i = 0; i < cookieable_schemes_.size(); ++i) {
2224 // We matched a scheme.
2225 if (url.SchemeIs(cookieable_schemes_[i].c_str())) {
2226 // We've matched a supported scheme.
initial.commit586acc5fe2008-07-26 22:42:522227 return true;
2228 }
2229 }
[email protected]f48b9432011-01-11 07:25:402230
2231 // The scheme didn't match any in our whitelist.
mkwstbe84af312015-02-20 08:52:452232 VLOG(kVlogPerCookieMonster)
2233 << "WARNING: Unsupported cookie scheme: " << url.scheme();
initial.commit586acc5fe2008-07-26 22:42:522234 return false;
2235}
2236
[email protected]c4058fb2010-06-22 17:25:262237// Test to see if stats should be recorded, and record them if so.
2238// The goal here is to get sampling for the average browser-hour of
2239// activity. We won't take samples when the web isn't being surfed,
2240// and when the web is being surfed, we'll take samples about every
2241// kRecordStatisticsIntervalSeconds.
2242// last_statistic_record_time_ is initialized to Now() rather than null
2243// in the constructor so that we won't take statistics right after
2244// startup, to avoid bias from browsers that are started but not used.
2245void CookieMonster::RecordPeriodicStats(const base::Time& current_time) {
mmenkebe0910d2016-03-01 19:09:092246 DCHECK(thread_checker_.CalledOnValidThread());
2247
[email protected]c4058fb2010-06-22 17:25:262248 const base::TimeDelta kRecordStatisticsIntervalTime(
2249 base::TimeDelta::FromSeconds(kRecordStatisticsIntervalSeconds));
2250
[email protected]7a964a72010-09-07 19:33:262251 // If we've taken statistics recently, return.
2252 if (current_time - last_statistic_record_time_ <=
[email protected]c4058fb2010-06-22 17:25:262253 kRecordStatisticsIntervalTime) {
[email protected]7a964a72010-09-07 19:33:262254 return;
[email protected]c4058fb2010-06-22 17:25:262255 }
[email protected]7a964a72010-09-07 19:33:262256
2257 // See InitializeHistograms() for details.
2258 histogram_count_->Add(cookies_.size());
2259
2260 // More detailed statistics on cookie counts at different granularities.
[email protected]7a964a72010-09-07 19:33:262261 last_statistic_record_time_ = current_time;
[email protected]c4058fb2010-06-22 17:25:262262}
2263
[email protected]f48b9432011-01-11 07:25:402264// Initialize all histogram counter variables used in this class.
2265//
2266// Normal histogram usage involves using the macros defined in
2267// histogram.h, which automatically takes care of declaring these
2268// variables (as statics), initializing them, and accumulating into
2269// them, all from a single entry point. Unfortunately, that solution
2270// doesn't work for the CookieMonster, as it's vulnerable to races between
2271// separate threads executing the same functions and hence initializing the
2272// same static variables. There isn't a race danger in the histogram
2273// accumulation calls; they are written to be resilient to simultaneous
2274// calls from multiple threads.
2275//
2276// The solution taken here is to have per-CookieMonster instance
2277// variables that are constructed during CookieMonster construction.
2278// Note that these variables refer to the same underlying histogram,
2279// so we still race (but safely) with other CookieMonster instances
2280// for accumulation.
2281//
2282// To do this we've expanded out the individual histogram macros calls,
2283// with declarations of the variables in the class decl, initialization here
2284// (done from the class constructor) and direct calls to the accumulation
2285// methods where needed. The specific histogram macro calls on which the
2286// initialization is based are included in comments below.
2287void CookieMonster::InitializeHistograms() {
mmenkebe0910d2016-03-01 19:09:092288 DCHECK(thread_checker_.CalledOnValidThread());
2289
[email protected]f48b9432011-01-11 07:25:402290 // From UMA_HISTOGRAM_CUSTOM_COUNTS
2291 histogram_expiration_duration_minutes_ = base::Histogram::FactoryGet(
mkwstbe84af312015-02-20 08:52:452292 "Cookie.ExpirationDurationMinutes", 1, kMinutesInTenYears, 50,
[email protected]f48b9432011-01-11 07:25:402293 base::Histogram::kUmaTargetedHistogramFlag);
[email protected]f48b9432011-01-11 07:25:402294 histogram_evicted_last_access_minutes_ = base::Histogram::FactoryGet(
mkwstbe84af312015-02-20 08:52:452295 "Cookie.EvictedLastAccessMinutes", 1, kMinutesInTenYears, 50,
[email protected]f48b9432011-01-11 07:25:402296 base::Histogram::kUmaTargetedHistogramFlag);
2297 histogram_count_ = base::Histogram::FactoryGet(
mkwstbe84af312015-02-20 08:52:452298 "Cookie.Count", 1, 4000, 50, base::Histogram::kUmaTargetedHistogramFlag);
[email protected]f48b9432011-01-11 07:25:402299
2300 // From UMA_HISTOGRAM_ENUMERATION
2301 histogram_cookie_deletion_cause_ = base::LinearHistogram::FactoryGet(
mkwstbe84af312015-02-20 08:52:452302 "Cookie.DeletionCause", 1, DELETE_COOKIE_LAST_ENTRY - 1,
2303 DELETE_COOKIE_LAST_ENTRY, base::Histogram::kUmaTargetedHistogramFlag);
mkwstc1aa4cc2015-04-03 19:57:452304 histogram_cookie_type_ = base::LinearHistogram::FactoryGet(
mkwst87378d92015-04-10 21:22:112305 "Cookie.Type", 1, (1 << COOKIE_TYPE_LAST_ENTRY) - 1,
2306 1 << COOKIE_TYPE_LAST_ENTRY, base::Histogram::kUmaTargetedHistogramFlag);
estark7feb65c2b2015-08-21 23:38:202307 histogram_cookie_source_scheme_ = base::LinearHistogram::FactoryGet(
2308 "Cookie.CookieSourceScheme", 1, COOKIE_SOURCE_LAST_ENTRY - 1,
2309 COOKIE_SOURCE_LAST_ENTRY, base::Histogram::kUmaTargetedHistogramFlag);
jww31e32632015-12-16 23:38:342310 histogram_cookie_delete_equivalent_ = base::LinearHistogram::FactoryGet(
2311 "Cookie.CookieDeleteEquivalent", 1,
2312 COOKIE_DELETE_EQUIVALENT_LAST_ENTRY - 1,
2313 COOKIE_DELETE_EQUIVALENT_LAST_ENTRY,
2314 base::Histogram::kUmaTargetedHistogramFlag);
[email protected]f48b9432011-01-11 07:25:402315
2316 // From UMA_HISTOGRAM_{CUSTOM_,}TIMES
[email protected]c7593fb22011-11-14 23:54:272317 histogram_time_blocked_on_load_ = base::Histogram::FactoryTimeGet(
mkwstbe84af312015-02-20 08:52:452318 "Cookie.TimeBlockedOnLoad", base::TimeDelta::FromMilliseconds(1),
2319 base::TimeDelta::FromMinutes(1), 50,
2320 base::Histogram::kUmaTargetedHistogramFlag);
[email protected]f48b9432011-01-11 07:25:402321}
2322
[email protected]f48b9432011-01-11 07:25:402323// The system resolution is not high enough, so we can have multiple
2324// set cookies that result in the same system time. When this happens, we
2325// increment by one Time unit. Let's hope computers don't get too fast.
2326Time CookieMonster::CurrentTime() {
mkwstbe84af312015-02-20 08:52:452327 return std::max(Time::Now(), Time::FromInternalValue(
2328 last_time_seen_.ToInternalValue() + 1));
[email protected]f48b9432011-01-11 07:25:402329}
2330
mmenke74bcbd52016-01-21 17:17:562331void CookieMonster::DoCookieTask(
2332 const scoped_refptr<CookieMonsterTask>& task_item) {
mmenkebe0910d2016-03-01 19:09:092333 DCHECK(thread_checker_.CalledOnValidThread());
2334
2335 MarkCookieStoreAsInitialized();
2336 FetchAllCookiesIfNecessary();
mmenkef49fca0e2016-03-08 12:46:242337 seen_global_task_ = true;
mmenkebe0910d2016-03-01 19:09:092338
2339 if (!finished_fetching_all_cookies_ && store_.get()) {
mmenkef49fca0e2016-03-08 12:46:242340 tasks_pending_.push_back(task_item);
mmenkebe0910d2016-03-01 19:09:092341 return;
mmenke74bcbd52016-01-21 17:17:562342 }
2343
2344 task_item->Run();
2345}
2346
2347void CookieMonster::DoCookieTaskForURL(
2348 const scoped_refptr<CookieMonsterTask>& task_item,
2349 const GURL& url) {
mmenkebe0910d2016-03-01 19:09:092350 MarkCookieStoreAsInitialized();
2351 if (ShouldFetchAllCookiesWhenFetchingAnyCookie())
2352 FetchAllCookiesIfNecessary();
2353
2354 // If cookies for the requested domain key (eTLD+1) have been loaded from DB
2355 // then run the task, otherwise load from DB.
2356 if (!finished_fetching_all_cookies_ && store_.get()) {
mmenkef49fca0e2016-03-08 12:46:242357 // If a global task has been previously seen, queue the task as a global
2358 // task. Note that the CookieMonster may be in the middle of executing
2359 // the global queue, |tasks_pending_| may be empty, which is why another
2360 // bool is needed.
2361 if (seen_global_task_) {
2362 tasks_pending_.push_back(task_item);
2363 return;
2364 }
2365
mmenkebe0910d2016-03-01 19:09:092366 // Checks if the domain key has been loaded.
2367 std::string key(cookie_util::GetEffectiveDomain(url.scheme(), url.host()));
2368 if (keys_loaded_.find(key) == keys_loaded_.end()) {
2369 std::map<std::string,
2370 std::deque<scoped_refptr<CookieMonsterTask>>>::iterator it =
2371 tasks_pending_for_key_.find(key);
2372 if (it == tasks_pending_for_key_.end()) {
2373 store_->LoadCookiesForKey(
2374 key, base::Bind(&CookieMonster::OnKeyLoaded,
2375 weak_ptr_factory_.GetWeakPtr(), key));
2376 it = tasks_pending_for_key_
2377 .insert(std::make_pair(
2378 key, std::deque<scoped_refptr<CookieMonsterTask>>()))
2379 .first;
mmenke74bcbd52016-01-21 17:17:562380 }
mmenkebe0910d2016-03-01 19:09:092381 it->second.push_back(task_item);
2382 return;
mmenke74bcbd52016-01-21 17:17:562383 }
2384 }
mmenkebe0910d2016-03-01 19:09:092385
mmenke74bcbd52016-01-21 17:17:562386 task_item->Run();
2387}
2388
drogerd5d1278c2015-03-17 19:21:512389void CookieMonster::ComputeCookieDiff(CookieList* old_cookies,
2390 CookieList* new_cookies,
2391 CookieList* cookies_to_add,
2392 CookieList* cookies_to_delete) {
mmenkebe0910d2016-03-01 19:09:092393 DCHECK(thread_checker_.CalledOnValidThread());
2394
drogerd5d1278c2015-03-17 19:21:512395 DCHECK(old_cookies);
2396 DCHECK(new_cookies);
2397 DCHECK(cookies_to_add);
2398 DCHECK(cookies_to_delete);
2399 DCHECK(cookies_to_add->empty());
2400 DCHECK(cookies_to_delete->empty());
2401
2402 // Sort both lists.
2403 // A set ordered by FullDiffCookieSorter is also ordered by
2404 // PartialDiffCookieSorter.
2405 std::sort(old_cookies->begin(), old_cookies->end(), FullDiffCookieSorter);
2406 std::sort(new_cookies->begin(), new_cookies->end(), FullDiffCookieSorter);
2407
2408 // Select any old cookie for deletion if no new cookie has the same name,
2409 // domain, and path.
2410 std::set_difference(
2411 old_cookies->begin(), old_cookies->end(), new_cookies->begin(),
2412 new_cookies->end(),
2413 std::inserter(*cookies_to_delete, cookies_to_delete->begin()),
2414 PartialDiffCookieSorter);
2415
2416 // Select any new cookie for addition (or update) if no old cookie is exactly
2417 // equivalent.
2418 std::set_difference(new_cookies->begin(), new_cookies->end(),
2419 old_cookies->begin(), old_cookies->end(),
2420 std::inserter(*cookies_to_add, cookies_to_add->begin()),
2421 FullDiffCookieSorter);
2422}
2423
mmenkebe0910d2016-03-01 19:09:092424void CookieMonster::RunCallback(const base::Closure& callback) {
2425 DCHECK(thread_checker_.CalledOnValidThread());
2426 callback.Run();
2427}
2428
2429void CookieMonster::RunCookieChangedCallbacks(const CanonicalCookie& cookie,
nharper352933e2016-09-30 18:24:572430 ChangeCause cause) {
mmenkebe0910d2016-03-01 19:09:092431 DCHECK(thread_checker_.CalledOnValidThread());
2432
ellyjones399e35a22014-10-27 11:09:562433 CookieOptions opts;
2434 opts.set_include_httponly();
mkwstf71d0bd2016-03-21 14:15:242435 opts.set_same_site_cookie_mode(
2436 CookieOptions::SameSiteCookieMode::INCLUDE_STRICT_AND_LAX);
mmenkebe0910d2016-03-01 19:09:092437 // Note that the callbacks in hook_map_ are wrapped with RunAsync(), so they
ellyjones399e35a22014-10-27 11:09:562438 // are guaranteed to not take long - they just post a RunAsync task back to
mmenkebe0910d2016-03-01 19:09:092439 // the appropriate thread's message loop and return.
2440 // TODO(mmenke): Consider running these synchronously?
ellyjones399e35a22014-10-27 11:09:562441 for (CookieChangedHookMap::iterator it = hook_map_.begin();
2442 it != hook_map_.end(); ++it) {
2443 std::pair<GURL, std::string> key = it->first;
2444 if (cookie.IncludeForRequestURL(key.first, opts) &&
2445 cookie.Name() == key.second) {
nharper352933e2016-09-30 18:24:572446 it->second->Notify(cookie, cause);
ellyjones399e35a22014-10-27 11:09:562447 }
2448 }
2449}
2450
[email protected]63725312012-07-19 08:24:162451} // namespace net