blob: 1984bad6a962c405d90a39f9181c7deef6217b1a [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>
[email protected]09666482011-07-12 12:50:4049#include <set>
initial.commit586acc5fe2008-07-26 22:42:5250
[email protected]218aa6a12011-09-13 17:38:3851#include "base/bind.h"
[email protected]85620342011-10-17 17:35:0452#include "base/callback.h"
skyostil4891b25b2015-06-11 11:43:4553#include "base/location.h"
initial.commit586acc5fe2008-07-26 22:42:5254#include "base/logging.h"
Avi Drissman13fc8932015-12-20 04:40:4655#include "base/macros.h"
[email protected]3b63f8f42011-03-28 01:54:1556#include "base/memory/scoped_ptr.h"
erikchen1dd72a72015-05-06 20:45:0557#include "base/metrics/field_trial.h"
[email protected]835d7c82010-10-14 04:38:3858#include "base/metrics/histogram.h"
pkastingb60049a2015-02-07 03:25:2559#include "base/profiler/scoped_tracker.h"
anujk.sharmaafc45172015-05-15 00:50:3460#include "base/single_thread_task_runner.h"
[email protected]4b355212013-06-11 10:35:1961#include "base/strings/string_util.h"
62#include "base/strings/stringprintf.h"
anujk.sharmaafc45172015-05-15 00:50:3463#include "base/thread_task_runner_handle.h"
[email protected]be28b5f42012-07-20 11:31:2564#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
[email protected]4b355212013-06-11 10:35:1965#include "net/cookies/canonical_cookie.h"
[email protected]63ee33bd2012-03-15 09:29:5866#include "net/cookies/cookie_util.h"
[email protected]ebfe3172012-07-12 12:21:4167#include "net/cookies/parsed_cookie.h"
mkwst8241a122015-10-20 07:15:1068#include "url/origin.h"
initial.commit586acc5fe2008-07-26 22:42:5269
[email protected]e1acf6f2008-10-27 20:43:3370using base::Time;
71using base::TimeDelta;
[email protected]7a964a72010-09-07 19:33:2672using base::TimeTicks;
[email protected]e1acf6f2008-10-27 20:43:3373
[email protected]85620342011-10-17 17:35:0474// In steady state, most cookie requests can be satisfied by the in memory
erikchen1dd72a72015-05-06 20:45:0575// cookie monster store. If the cookie request cannot be satisfied by the in
76// memory store, the relevant cookies must be fetched from the persistent
77// store. The task is queued in CookieMonster::tasks_pending_ if it requires
78// all cookies to be loaded from the backend, or tasks_pending_for_key_ if it
79// only requires all cookies associated with an eTLD+1.
[email protected]85620342011-10-17 17:35:0480//
81// On the browser critical paths (e.g. for loading initial web pages in a
82// session restore) it may take too long to wait for the full load. If a cookie
83// request is for a specific URL, DoCookieTaskForURL is called, which triggers a
84// priority load if the key is not loaded yet by calling PersistentCookieStore
[email protected]0184df32013-05-14 00:53:5585// :: LoadCookiesForKey. The request is queued in
86// CookieMonster::tasks_pending_for_key_ and executed upon receiving
87// notification of key load completion via CookieMonster::OnKeyLoaded(). If
88// multiple requests for the same eTLD+1 are received before key load
89// completion, only the first request calls
[email protected]85620342011-10-17 17:35:0490// PersistentCookieStore::LoadCookiesForKey, all subsequent requests are queued
[email protected]0184df32013-05-14 00:53:5591// in CookieMonster::tasks_pending_for_key_ and executed upon receiving
92// notification of key load completion triggered by the first request for the
93// same eTLD+1.
[email protected]85620342011-10-17 17:35:0494
[email protected]c4058fb2010-06-22 17:25:2695static const int kMinutesInTenYears = 10 * 365 * 24 * 60;
96
erikchen1dd72a72015-05-06 20:45:0597namespace {
98
99const char kFetchWhenNecessaryName[] = "FetchWhenNecessary";
100const char kAlwaysFetchName[] = "AlwaysFetch";
101const char kCookieMonsterFetchStrategyName[] = "CookieMonsterFetchStrategy";
102
103} // namespace
104
[email protected]8ac1a752008-07-31 19:40:37105namespace net {
106
[email protected]7a964a72010-09-07 19:33:26107// See comments at declaration of these variables in cookie_monster.h
108// for details.
mkwstbe84af312015-02-20 08:52:45109const size_t CookieMonster::kDomainMaxCookies = 180;
110const size_t CookieMonster::kDomainPurgeCookies = 30;
111const size_t CookieMonster::kMaxCookies = 3300;
112const size_t CookieMonster::kPurgeCookies = 300;
[email protected]8ad5d462013-05-02 08:45:26113
mkwst87734352016-03-03 17:36:23114const size_t CookieMonster::kDomainCookiesQuotaLow = 30;
115const size_t CookieMonster::kDomainCookiesQuotaMedium = 50;
116const size_t CookieMonster::kDomainCookiesQuotaHigh =
117 kDomainMaxCookies - kDomainPurgeCookies - kDomainCookiesQuotaLow -
118 kDomainCookiesQuotaMedium;
[email protected]8ad5d462013-05-02 08:45:26119
mkwstbe84af312015-02-20 08:52:45120const int CookieMonster::kSafeFromGlobalPurgeDays = 30;
[email protected]297a4ed02010-02-12 08:12:52121
[email protected]7a964a72010-09-07 19:33:26122namespace {
[email protected]e32306c52008-11-06 16:59:05123
[email protected]6210ce52013-09-20 03:33:14124bool ContainsControlCharacter(const std::string& s) {
125 for (std::string::const_iterator i = s.begin(); i != s.end(); ++i) {
126 if ((*i >= 0) && (*i <= 31))
127 return true;
128 }
129
130 return false;
131}
132
[email protected]5b9bc352012-07-18 13:13:34133typedef std::vector<CanonicalCookie*> CanonicalCookieVector;
[email protected]34a160d2011-05-12 22:12:49134
[email protected]77e0a462008-11-01 00:43:35135// Default minimum delay after updating a cookie's LastAccessDate before we
136// will update it again.
[email protected]297a4ed02010-02-12 08:12:52137const int kDefaultAccessUpdateThresholdSeconds = 60;
138
139// Comparator to sort cookies from highest creation date to lowest
140// creation date.
141struct OrderByCreationTimeDesc {
142 bool operator()(const CookieMonster::CookieMap::iterator& a,
143 const CookieMonster::CookieMap::iterator& b) const {
144 return a->second->CreationDate() > b->second->CreationDate();
145 }
146};
147
[email protected]4d3ce782010-10-29 18:31:28148// Constants for use in VLOG
149const int kVlogPerCookieMonster = 1;
[email protected]4d3ce782010-10-29 18:31:28150const int kVlogGarbageCollection = 5;
151const int kVlogSetCookies = 7;
152const int kVlogGetCookies = 9;
153
[email protected]f48b9432011-01-11 07:25:40154// Mozilla sorts on the path length (longest first), and then it
155// sorts by creation time (oldest first).
156// The RFC says the sort order for the domain attribute is undefined.
[email protected]5b9bc352012-07-18 13:13:34157bool CookieSorter(CanonicalCookie* cc1, CanonicalCookie* cc2) {
[email protected]f48b9432011-01-11 07:25:40158 if (cc1->Path().length() == cc2->Path().length())
159 return cc1->CreationDate() < cc2->CreationDate();
160 return cc1->Path().length() > cc2->Path().length();
initial.commit586acc5fe2008-07-26 22:42:52161}
162
[email protected]8ad5d462013-05-02 08:45:26163bool LRACookieSorter(const CookieMonster::CookieMap::iterator& it1,
[email protected]f48b9432011-01-11 07:25:40164 const CookieMonster::CookieMap::iterator& it2) {
[email protected]f48b9432011-01-11 07:25:40165 if (it1->second->LastAccessDate() != it2->second->LastAccessDate())
166 return it1->second->LastAccessDate() < it2->second->LastAccessDate();
initial.commit586acc5fe2008-07-26 22:42:52167
mkwste079ac412016-03-11 09:04:06168 // Ensure stability for == last access times by falling back to creation.
[email protected]f48b9432011-01-11 07:25:40169 return it1->second->CreationDate() < it2->second->CreationDate();
[email protected]297a4ed02010-02-12 08:12:52170}
171
drogerd5d1278c2015-03-17 19:21:51172// Compare cookies using name, domain and path, so that "equivalent" cookies
173// (per RFC 2965) are equal to each other.
ttuttle859dc7a2015-04-23 19:42:29174bool PartialDiffCookieSorter(const CanonicalCookie& a,
175 const CanonicalCookie& b) {
drogerd5d1278c2015-03-17 19:21:51176 return a.PartialCompare(b);
177}
178
179// This is a stricter ordering than PartialDiffCookieOrdering, where all fields
180// are used.
ttuttle859dc7a2015-04-23 19:42:29181bool FullDiffCookieSorter(const CanonicalCookie& a, const CanonicalCookie& b) {
drogerd5d1278c2015-03-17 19:21:51182 return a.FullCompare(b);
183}
184
[email protected]297a4ed02010-02-12 08:12:52185// Our strategy to find duplicates is:
186// (1) Build a map from (cookiename, cookiepath) to
187// {list of cookies with this signature, sorted by creation time}.
188// (2) For each list with more than 1 entry, keep the cookie having the
189// most recent creation time, and delete the others.
[email protected]f48b9432011-01-11 07:25:40190//
[email protected]1655ba342010-07-14 18:17:42191// Two cookies are considered equivalent if they have the same domain,
192// name, and path.
193struct CookieSignature {
194 public:
[email protected]dedec0b2013-02-28 04:50:10195 CookieSignature(const std::string& name,
196 const std::string& domain,
[email protected]1655ba342010-07-14 18:17:42197 const std::string& path)
mkwstbe84af312015-02-20 08:52:45198 : name(name), domain(domain), path(path) {}
[email protected]1655ba342010-07-14 18:17:42199
200 // To be a key for a map this class needs to be assignable, copyable,
201 // and have an operator<. The default assignment operator
202 // and copy constructor are exactly what we want.
203
204 bool operator<(const CookieSignature& cs) const {
205 // Name compare dominates, then domain, then path.
206 int diff = name.compare(cs.name);
207 if (diff != 0)
208 return diff < 0;
209
210 diff = domain.compare(cs.domain);
211 if (diff != 0)
212 return diff < 0;
213
214 return path.compare(cs.path) < 0;
215 }
216
217 std::string name;
218 std::string domain;
219 std::string path;
220};
[email protected]f48b9432011-01-11 07:25:40221
[email protected]8ad5d462013-05-02 08:45:26222// For a CookieItVector iterator range [|it_begin|, |it_end|),
223// sorts the first |num_sort| + 1 elements by LastAccessDate().
224// The + 1 element exists so for any interval of length <= |num_sort| starting
225// from |cookies_its_begin|, a LastAccessDate() bound can be found.
mkwstbe84af312015-02-20 08:52:45226void SortLeastRecentlyAccessed(CookieMonster::CookieItVector::iterator it_begin,
227 CookieMonster::CookieItVector::iterator it_end,
228 size_t num_sort) {
[email protected]8ad5d462013-05-02 08:45:26229 DCHECK_LT(static_cast<int>(num_sort), it_end - it_begin);
230 std::partial_sort(it_begin, it_begin + num_sort + 1, it_end, LRACookieSorter);
231}
[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
[email protected]7c4b66b2014-01-04 12:28:13267// Mapping between DeletionCause and CookieMonsterDelegate::ChangeCause; the
268// 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 {
[email protected]7c4b66b2014-01-04 12:28:13271 CookieMonsterDelegate::ChangeCause cause;
[email protected]8bb846f2011-03-23 12:08:18272 bool notify;
273} ChangeCausePair;
274ChangeCausePair ChangeCauseMapping[] = {
mkwstbe84af312015-02-20 08:52:45275 // DELETE_COOKIE_EXPLICIT
276 {CookieMonsterDelegate::CHANGE_COOKIE_EXPLICIT, true},
277 // DELETE_COOKIE_OVERWRITE
278 {CookieMonsterDelegate::CHANGE_COOKIE_OVERWRITE, true},
279 // DELETE_COOKIE_EXPIRED
280 {CookieMonsterDelegate::CHANGE_COOKIE_EXPIRED, true},
281 // DELETE_COOKIE_EVICTED
282 {CookieMonsterDelegate::CHANGE_COOKIE_EVICTED, true},
283 // DELETE_COOKIE_DUPLICATE_IN_BACKING_STORE
284 {CookieMonsterDelegate::CHANGE_COOKIE_EXPLICIT, false},
285 // DELETE_COOKIE_DONT_RECORD
286 {CookieMonsterDelegate::CHANGE_COOKIE_EXPLICIT, false},
287 // DELETE_COOKIE_EVICTED_DOMAIN
288 {CookieMonsterDelegate::CHANGE_COOKIE_EVICTED, true},
289 // DELETE_COOKIE_EVICTED_GLOBAL
290 {CookieMonsterDelegate::CHANGE_COOKIE_EVICTED, true},
291 // DELETE_COOKIE_EVICTED_DOMAIN_PRE_SAFE
292 {CookieMonsterDelegate::CHANGE_COOKIE_EVICTED, true},
293 // DELETE_COOKIE_EVICTED_DOMAIN_POST_SAFE
294 {CookieMonsterDelegate::CHANGE_COOKIE_EVICTED, true},
295 // DELETE_COOKIE_EXPIRED_OVERWRITE
296 {CookieMonsterDelegate::CHANGE_COOKIE_EXPIRED_OVERWRITE, true},
297 // DELETE_COOKIE_CONTROL_CHAR
298 {CookieMonsterDelegate::CHANGE_COOKIE_EVICTED, true},
jww82d99c12015-11-25 18:39:53299 // DELETE_COOKIE_NON_SECURE
300 {CookieMonsterDelegate::CHANGE_COOKIE_EVICTED, true},
mkwstbe84af312015-02-20 08:52:45301 // DELETE_COOKIE_LAST_ENTRY
302 {CookieMonsterDelegate::CHANGE_COOKIE_EXPLICIT, false}};
[email protected]8bb846f2011-03-23 12:08:18303
ellyjones399e35a22014-10-27 11:09:56304void RunAsync(scoped_refptr<base::TaskRunner> proxy,
msarda0aad8f02014-10-30 09:22:39305 const CookieStore::CookieChangedCallback& callback,
306 const CanonicalCookie& cookie,
307 bool removed) {
308 proxy->PostTask(FROM_HERE, base::Bind(callback, cookie, removed));
ellyjones399e35a22014-10-27 11:09:56309}
310
[email protected]f48b9432011-01-11 07:25:40311} // namespace
312
[email protected]7c4b66b2014-01-04 12:28:13313CookieMonster::CookieMonster(PersistentCookieStore* store,
314 CookieMonsterDelegate* delegate)
mmenke74bcbd52016-01-21 17:17:56315 : CookieMonster(store, delegate, kDefaultAccessUpdateThresholdSeconds) {
[email protected]2d0f89a2010-12-06 12:02:23316}
317
[email protected]f48b9432011-01-11 07:25:40318CookieMonster::CookieMonster(PersistentCookieStore* store,
[email protected]7c4b66b2014-01-04 12:28:13319 CookieMonsterDelegate* delegate,
[email protected]f48b9432011-01-11 07:25:40320 int last_access_threshold_milliseconds)
321 : initialized_(false),
erikchen1dd72a72015-05-06 20:45:05322 started_fetching_all_cookies_(false),
323 finished_fetching_all_cookies_(false),
324 fetch_strategy_(kUnknownFetch),
mmenkef49fca0e2016-03-08 12:46:24325 seen_global_task_(false),
[email protected]f48b9432011-01-11 07:25:40326 store_(store),
327 last_access_threshold_(base::TimeDelta::FromMilliseconds(
328 last_access_threshold_milliseconds)),
329 delegate_(delegate),
[email protected]82388662011-03-10 21:04:06330 last_statistic_record_time_(base::Time::Now()),
mmenkebe0910d2016-03-01 19:09:09331 persist_session_cookies_(false),
332 weak_ptr_factory_(this) {
[email protected]f48b9432011-01-11 07:25:40333 InitializeHistograms();
mmenke18dd8ba2016-02-01 18:42:10334 cookieable_schemes_.insert(
335 cookieable_schemes_.begin(), kDefaultCookieableSchemes,
336 kDefaultCookieableSchemes + kDefaultCookieableSchemesCount);
initial.commit586acc5fe2008-07-26 22:42:52337}
338
[email protected]218aa6a12011-09-13 17:38:38339// Task classes for queueing the coming request.
340
341class CookieMonster::CookieMonsterTask
342 : public base::RefCountedThreadSafe<CookieMonsterTask> {
343 public:
344 // Runs the task and invokes the client callback on the thread that
345 // originally constructed the task.
346 virtual void Run() = 0;
347
348 protected:
349 explicit CookieMonsterTask(CookieMonster* cookie_monster);
350 virtual ~CookieMonsterTask();
351
mkwstbe84af312015-02-20 08:52:45352 CookieMonster* cookie_monster() { return cookie_monster_; }
[email protected]218aa6a12011-09-13 17:38:38353
[email protected]a9813302012-04-28 09:29:28354 private:
[email protected]218aa6a12011-09-13 17:38:38355 friend class base::RefCountedThreadSafe<CookieMonsterTask>;
356
[email protected]218aa6a12011-09-13 17:38:38357 CookieMonster* cookie_monster_;
[email protected]218aa6a12011-09-13 17:38:38358
359 DISALLOW_COPY_AND_ASSIGN(CookieMonsterTask);
360};
361
362CookieMonster::CookieMonsterTask::CookieMonsterTask(
363 CookieMonster* cookie_monster)
mmenkebe0910d2016-03-01 19:09:09364 : cookie_monster_(cookie_monster) {}
[email protected]218aa6a12011-09-13 17:38:38365
mkwstbe84af312015-02-20 08:52:45366CookieMonster::CookieMonsterTask::~CookieMonsterTask() {
367}
[email protected]218aa6a12011-09-13 17:38:38368
[email protected]218aa6a12011-09-13 17:38:38369// Task class for SetCookieWithDetails call.
[email protected]5fa4f9a2013-10-03 10:13:16370class CookieMonster::SetCookieWithDetailsTask : public CookieMonsterTask {
[email protected]218aa6a12011-09-13 17:38:38371 public:
[email protected]dedec0b2013-02-28 04:50:10372 SetCookieWithDetailsTask(CookieMonster* cookie_monster,
373 const GURL& url,
374 const std::string& name,
375 const std::string& value,
376 const std::string& domain,
377 const std::string& path,
mmenkefdd4fc72016-02-05 20:53:24378 base::Time creation_time,
379 base::Time expiration_time,
380 base::Time last_access_time,
[email protected]dedec0b2013-02-28 04:50:10381 bool secure,
382 bool http_only,
mkwst46549412016-02-01 10:05:37383 bool same_site,
jww601411a2015-11-20 19:46:57384 bool enforce_strict_secure,
[email protected]ab2d75c82013-04-19 18:39:04385 CookiePriority priority,
[email protected]5fa4f9a2013-10-03 10:13:16386 const SetCookiesCallback& callback)
[email protected]218aa6a12011-09-13 17:38:38387 : CookieMonsterTask(cookie_monster),
388 url_(url),
389 name_(name),
390 value_(value),
391 domain_(domain),
392 path_(path),
mmenkeea4cd402016-02-02 04:03:10393 creation_time_(creation_time),
[email protected]218aa6a12011-09-13 17:38:38394 expiration_time_(expiration_time),
mmenkefdd4fc72016-02-05 20:53:24395 last_access_time_(last_access_time),
[email protected]218aa6a12011-09-13 17:38:38396 secure_(secure),
397 http_only_(http_only),
mkwst46549412016-02-01 10:05:37398 same_site_(same_site),
jww601411a2015-11-20 19:46:57399 enforce_strict_secure_(enforce_strict_secure),
[email protected]ab2d75c82013-04-19 18:39:04400 priority_(priority),
mkwstbe84af312015-02-20 08:52:45401 callback_(callback) {}
[email protected]218aa6a12011-09-13 17:38:38402
[email protected]5fa4f9a2013-10-03 10:13:16403 // CookieMonsterTask:
dchengb03027d2014-10-21 12:00:20404 void Run() override;
[email protected]218aa6a12011-09-13 17:38:38405
[email protected]a9813302012-04-28 09:29:28406 protected:
dchengb03027d2014-10-21 12:00:20407 ~SetCookieWithDetailsTask() override {}
[email protected]a9813302012-04-28 09:29:28408
[email protected]218aa6a12011-09-13 17:38:38409 private:
410 GURL url_;
411 std::string name_;
412 std::string value_;
413 std::string domain_;
414 std::string path_;
mmenkeea4cd402016-02-02 04:03:10415 base::Time creation_time_;
[email protected]218aa6a12011-09-13 17:38:38416 base::Time expiration_time_;
mmenkefdd4fc72016-02-05 20:53:24417 base::Time last_access_time_;
[email protected]218aa6a12011-09-13 17:38:38418 bool secure_;
419 bool http_only_;
mkwst46549412016-02-01 10:05:37420 bool same_site_;
jww601411a2015-11-20 19:46:57421 bool enforce_strict_secure_;
[email protected]ab2d75c82013-04-19 18:39:04422 CookiePriority priority_;
[email protected]5fa4f9a2013-10-03 10:13:16423 SetCookiesCallback callback_;
[email protected]218aa6a12011-09-13 17:38:38424
425 DISALLOW_COPY_AND_ASSIGN(SetCookieWithDetailsTask);
426};
427
428void CookieMonster::SetCookieWithDetailsTask::Run() {
mkwstbe84af312015-02-20 08:52:45429 bool success = this->cookie_monster()->SetCookieWithDetails(
mmenkeea4cd402016-02-02 04:03:10430 url_, name_, value_, domain_, path_, creation_time_, expiration_time_,
mmenkefdd4fc72016-02-05 20:53:24431 last_access_time_, secure_, http_only_, same_site_,
432 enforce_strict_secure_, priority_);
mmenkebe0910d2016-03-01 19:09:09433 if (!callback_.is_null())
434 callback_.Run(success);
[email protected]218aa6a12011-09-13 17:38:38435}
436
437// Task class for GetAllCookies call.
[email protected]5fa4f9a2013-10-03 10:13:16438class CookieMonster::GetAllCookiesTask : public CookieMonsterTask {
[email protected]218aa6a12011-09-13 17:38:38439 public:
440 GetAllCookiesTask(CookieMonster* cookie_monster,
[email protected]5fa4f9a2013-10-03 10:13:16441 const GetCookieListCallback& callback)
mkwstbe84af312015-02-20 08:52:45442 : CookieMonsterTask(cookie_monster), callback_(callback) {}
[email protected]218aa6a12011-09-13 17:38:38443
[email protected]5fa4f9a2013-10-03 10:13:16444 // CookieMonsterTask
dchengb03027d2014-10-21 12:00:20445 void Run() override;
[email protected]218aa6a12011-09-13 17:38:38446
[email protected]a9813302012-04-28 09:29:28447 protected:
dchengb03027d2014-10-21 12:00:20448 ~GetAllCookiesTask() override {}
[email protected]a9813302012-04-28 09:29:28449
[email protected]218aa6a12011-09-13 17:38:38450 private:
[email protected]5fa4f9a2013-10-03 10:13:16451 GetCookieListCallback callback_;
[email protected]218aa6a12011-09-13 17:38:38452
453 DISALLOW_COPY_AND_ASSIGN(GetAllCookiesTask);
454};
455
456void CookieMonster::GetAllCookiesTask::Run() {
457 if (!callback_.is_null()) {
458 CookieList cookies = this->cookie_monster()->GetAllCookies();
mmenkebe0910d2016-03-01 19:09:09459 callback_.Run(cookies);
mkwstbe84af312015-02-20 08:52:45460 }
[email protected]218aa6a12011-09-13 17:38:38461}
462
mkwstc611e6d2016-02-23 15:45:55463// Task class for GetCookieListWithOptionsAsync call.
464class CookieMonster::GetCookieListWithOptionsTask : public CookieMonsterTask {
[email protected]218aa6a12011-09-13 17:38:38465 public:
mkwstc611e6d2016-02-23 15:45:55466 GetCookieListWithOptionsTask(CookieMonster* cookie_monster,
467 const GURL& url,
468 const CookieOptions& options,
469 const GetCookieListCallback& callback)
[email protected]218aa6a12011-09-13 17:38:38470 : CookieMonsterTask(cookie_monster),
471 url_(url),
472 options_(options),
mkwstbe84af312015-02-20 08:52:45473 callback_(callback) {}
[email protected]218aa6a12011-09-13 17:38:38474
[email protected]5fa4f9a2013-10-03 10:13:16475 // CookieMonsterTask:
dchengb03027d2014-10-21 12:00:20476 void Run() override;
[email protected]218aa6a12011-09-13 17:38:38477
[email protected]a9813302012-04-28 09:29:28478 protected:
mkwstc611e6d2016-02-23 15:45:55479 ~GetCookieListWithOptionsTask() override {}
[email protected]a9813302012-04-28 09:29:28480
[email protected]218aa6a12011-09-13 17:38:38481 private:
482 GURL url_;
483 CookieOptions options_;
[email protected]5fa4f9a2013-10-03 10:13:16484 GetCookieListCallback callback_;
[email protected]218aa6a12011-09-13 17:38:38485
mkwstc611e6d2016-02-23 15:45:55486 DISALLOW_COPY_AND_ASSIGN(GetCookieListWithOptionsTask);
[email protected]218aa6a12011-09-13 17:38:38487};
488
mkwstc611e6d2016-02-23 15:45:55489void CookieMonster::GetCookieListWithOptionsTask::Run() {
[email protected]218aa6a12011-09-13 17:38:38490 if (!callback_.is_null()) {
mkwstbe84af312015-02-20 08:52:45491 CookieList cookies =
mkwstc611e6d2016-02-23 15:45:55492 this->cookie_monster()->GetCookieListWithOptions(url_, options_);
mmenkebe0910d2016-03-01 19:09:09493 callback_.Run(cookies);
[email protected]218aa6a12011-09-13 17:38:38494 }
495}
496
mkwstbe84af312015-02-20 08:52:45497template <typename Result>
498struct CallbackType {
[email protected]5fa4f9a2013-10-03 10:13:16499 typedef base::Callback<void(Result)> Type;
500};
501
mkwstbe84af312015-02-20 08:52:45502template <>
503struct CallbackType<void> {
[email protected]5fa4f9a2013-10-03 10:13:16504 typedef base::Closure Type;
505};
506
507// Base task class for Delete*Task.
508template <typename Result>
509class CookieMonster::DeleteTask : public CookieMonsterTask {
[email protected]218aa6a12011-09-13 17:38:38510 public:
[email protected]5fa4f9a2013-10-03 10:13:16511 DeleteTask(CookieMonster* cookie_monster,
512 const typename CallbackType<Result>::Type& callback)
mkwstbe84af312015-02-20 08:52:45513 : CookieMonsterTask(cookie_monster), callback_(callback) {}
[email protected]218aa6a12011-09-13 17:38:38514
[email protected]5fa4f9a2013-10-03 10:13:16515 // CookieMonsterTask:
nickd3f30d022015-04-23 10:18:37516 void Run() override;
[email protected]218aa6a12011-09-13 17:38:38517
dmichaeld6e570d2014-12-18 22:30:57518 protected:
519 ~DeleteTask() override;
520
[email protected]5fa4f9a2013-10-03 10:13:16521 private:
522 // Runs the delete task and returns a result.
523 virtual Result RunDeleteTask() = 0;
mmenkebe0910d2016-03-01 19:09:09524 // Runs the delete task and then returns a callback to be called after
525 // flushing the persistent store.
526 // TODO(mmenke): This seems like a pretty ugly and needlessly confusing API.
527 // Simplify it?
[email protected]5fa4f9a2013-10-03 10:13:16528 base::Closure RunDeleteTaskAndBindCallback();
[email protected]5fa4f9a2013-10-03 10:13:16529
530 typename CallbackType<Result>::Type callback_;
531
532 DISALLOW_COPY_AND_ASSIGN(DeleteTask);
533};
534
535template <typename Result>
dmichaeld6e570d2014-12-18 22:30:57536CookieMonster::DeleteTask<Result>::~DeleteTask() {
537}
538
539template <typename Result>
540base::Closure
541CookieMonster::DeleteTask<Result>::RunDeleteTaskAndBindCallback() {
[email protected]5fa4f9a2013-10-03 10:13:16542 Result result = RunDeleteTask();
543 if (callback_.is_null())
544 return base::Closure();
545 return base::Bind(callback_, result);
546}
547
548template <>
549base::Closure CookieMonster::DeleteTask<void>::RunDeleteTaskAndBindCallback() {
550 RunDeleteTask();
551 return callback_;
552}
553
554template <typename Result>
555void CookieMonster::DeleteTask<Result>::Run() {
mmenkebe0910d2016-03-01 19:09:09556 base::Closure callback = RunDeleteTaskAndBindCallback();
[email protected]5fa4f9a2013-10-03 10:13:16557 if (!callback.is_null()) {
mmenkebe0910d2016-03-01 19:09:09558 callback = base::Bind(
559 &CookieMonster::RunCallback,
560 this->cookie_monster()->weak_ptr_factory_.GetWeakPtr(), callback);
[email protected]5fa4f9a2013-10-03 10:13:16561 }
mmenkebe0910d2016-03-01 19:09:09562 this->cookie_monster()->FlushStore(callback);
[email protected]5fa4f9a2013-10-03 10:13:16563}
564
[email protected]218aa6a12011-09-13 17:38:38565// Task class for DeleteAllCreatedBetween call.
[email protected]5fa4f9a2013-10-03 10:13:16566class CookieMonster::DeleteAllCreatedBetweenTask : public DeleteTask<int> {
[email protected]218aa6a12011-09-13 17:38:38567 public:
[email protected]dedec0b2013-02-28 04:50:10568 DeleteAllCreatedBetweenTask(CookieMonster* cookie_monster,
569 const Time& delete_begin,
570 const Time& delete_end,
[email protected]5fa4f9a2013-10-03 10:13:16571 const DeleteCallback& callback)
[email protected]151132f2013-11-18 21:37:00572 : DeleteTask<int>(cookie_monster, callback),
[email protected]218aa6a12011-09-13 17:38:38573 delete_begin_(delete_begin),
mkwstbe84af312015-02-20 08:52:45574 delete_end_(delete_end) {}
[email protected]218aa6a12011-09-13 17:38:38575
[email protected]5fa4f9a2013-10-03 10:13:16576 // DeleteTask:
dchengb03027d2014-10-21 12:00:20577 int RunDeleteTask() override;
[email protected]218aa6a12011-09-13 17:38:38578
[email protected]a9813302012-04-28 09:29:28579 protected:
dchengb03027d2014-10-21 12:00:20580 ~DeleteAllCreatedBetweenTask() override {}
[email protected]a9813302012-04-28 09:29:28581
[email protected]218aa6a12011-09-13 17:38:38582 private:
583 Time delete_begin_;
584 Time delete_end_;
[email protected]218aa6a12011-09-13 17:38:38585
586 DISALLOW_COPY_AND_ASSIGN(DeleteAllCreatedBetweenTask);
587};
588
[email protected]5fa4f9a2013-10-03 10:13:16589int CookieMonster::DeleteAllCreatedBetweenTask::RunDeleteTask() {
mkwstbe84af312015-02-20 08:52:45590 return this->cookie_monster()->DeleteAllCreatedBetween(delete_begin_,
591 delete_end_);
[email protected]218aa6a12011-09-13 17:38:38592}
593
[email protected]d8428d52013-08-07 06:58:25594// Task class for DeleteAllCreatedBetweenForHost call.
595class CookieMonster::DeleteAllCreatedBetweenForHostTask
[email protected]5fa4f9a2013-10-03 10:13:16596 : public DeleteTask<int> {
[email protected]d8428d52013-08-07 06:58:25597 public:
mkwstbe84af312015-02-20 08:52:45598 DeleteAllCreatedBetweenForHostTask(CookieMonster* cookie_monster,
599 Time delete_begin,
600 Time delete_end,
601 const GURL& url,
602 const DeleteCallback& callback)
[email protected]151132f2013-11-18 21:37:00603 : DeleteTask<int>(cookie_monster, callback),
[email protected]d8428d52013-08-07 06:58:25604 delete_begin_(delete_begin),
605 delete_end_(delete_end),
mkwstbe84af312015-02-20 08:52:45606 url_(url) {}
[email protected]d8428d52013-08-07 06:58:25607
[email protected]5fa4f9a2013-10-03 10:13:16608 // DeleteTask:
dchengb03027d2014-10-21 12:00:20609 int RunDeleteTask() override;
[email protected]d8428d52013-08-07 06:58:25610
611 protected:
dchengb03027d2014-10-21 12:00:20612 ~DeleteAllCreatedBetweenForHostTask() override {}
[email protected]d8428d52013-08-07 06:58:25613
614 private:
615 Time delete_begin_;
616 Time delete_end_;
617 GURL url_;
[email protected]d8428d52013-08-07 06:58:25618
619 DISALLOW_COPY_AND_ASSIGN(DeleteAllCreatedBetweenForHostTask);
620};
621
[email protected]5fa4f9a2013-10-03 10:13:16622int CookieMonster::DeleteAllCreatedBetweenForHostTask::RunDeleteTask() {
623 return this->cookie_monster()->DeleteAllCreatedBetweenForHost(
[email protected]d8428d52013-08-07 06:58:25624 delete_begin_, delete_end_, url_);
[email protected]d8428d52013-08-07 06:58:25625}
626
[email protected]218aa6a12011-09-13 17:38:38627// Task class for DeleteCanonicalCookie call.
mmenke24379d52016-02-05 23:50:17628class CookieMonster::DeleteCanonicalCookieTask : public DeleteTask<int> {
[email protected]218aa6a12011-09-13 17:38:38629 public:
[email protected]dedec0b2013-02-28 04:50:10630 DeleteCanonicalCookieTask(CookieMonster* cookie_monster,
631 const CanonicalCookie& cookie,
mmenke24379d52016-02-05 23:50:17632 const DeleteCallback& callback)
633 : DeleteTask<int>(cookie_monster, callback), cookie_(cookie) {}
[email protected]218aa6a12011-09-13 17:38:38634
[email protected]5fa4f9a2013-10-03 10:13:16635 // DeleteTask:
mmenke24379d52016-02-05 23:50:17636 int RunDeleteTask() override;
[email protected]218aa6a12011-09-13 17:38:38637
[email protected]a9813302012-04-28 09:29:28638 protected:
dchengb03027d2014-10-21 12:00:20639 ~DeleteCanonicalCookieTask() override {}
[email protected]a9813302012-04-28 09:29:28640
[email protected]218aa6a12011-09-13 17:38:38641 private:
[email protected]5b9bc352012-07-18 13:13:34642 CanonicalCookie cookie_;
[email protected]218aa6a12011-09-13 17:38:38643
644 DISALLOW_COPY_AND_ASSIGN(DeleteCanonicalCookieTask);
645};
646
mmenke24379d52016-02-05 23:50:17647int CookieMonster::DeleteCanonicalCookieTask::RunDeleteTask() {
[email protected]5fa4f9a2013-10-03 10:13:16648 return this->cookie_monster()->DeleteCanonicalCookie(cookie_);
[email protected]218aa6a12011-09-13 17:38:38649}
650
651// Task class for SetCookieWithOptions call.
[email protected]5fa4f9a2013-10-03 10:13:16652class CookieMonster::SetCookieWithOptionsTask : public CookieMonsterTask {
[email protected]218aa6a12011-09-13 17:38:38653 public:
654 SetCookieWithOptionsTask(CookieMonster* cookie_monster,
655 const GURL& url,
656 const std::string& cookie_line,
657 const CookieOptions& options,
[email protected]5fa4f9a2013-10-03 10:13:16658 const SetCookiesCallback& callback)
[email protected]218aa6a12011-09-13 17:38:38659 : CookieMonsterTask(cookie_monster),
660 url_(url),
661 cookie_line_(cookie_line),
662 options_(options),
mkwstbe84af312015-02-20 08:52:45663 callback_(callback) {}
[email protected]218aa6a12011-09-13 17:38:38664
[email protected]5fa4f9a2013-10-03 10:13:16665 // CookieMonsterTask:
dchengb03027d2014-10-21 12:00:20666 void Run() override;
[email protected]218aa6a12011-09-13 17:38:38667
[email protected]a9813302012-04-28 09:29:28668 protected:
dchengb03027d2014-10-21 12:00:20669 ~SetCookieWithOptionsTask() override {}
[email protected]a9813302012-04-28 09:29:28670
[email protected]218aa6a12011-09-13 17:38:38671 private:
672 GURL url_;
673 std::string cookie_line_;
674 CookieOptions options_;
[email protected]5fa4f9a2013-10-03 10:13:16675 SetCookiesCallback callback_;
[email protected]218aa6a12011-09-13 17:38:38676
677 DISALLOW_COPY_AND_ASSIGN(SetCookieWithOptionsTask);
678};
679
680void CookieMonster::SetCookieWithOptionsTask::Run() {
mkwstbe84af312015-02-20 08:52:45681 bool result = this->cookie_monster()->SetCookieWithOptions(url_, cookie_line_,
682 options_);
mmenkebe0910d2016-03-01 19:09:09683 if (!callback_.is_null())
684 callback_.Run(result);
[email protected]218aa6a12011-09-13 17:38:38685}
686
drogerd5d1278c2015-03-17 19:21:51687// Task class for SetAllCookies call.
688class CookieMonster::SetAllCookiesTask : public CookieMonsterTask {
689 public:
690 SetAllCookiesTask(CookieMonster* cookie_monster,
691 const CookieList& list,
692 const SetCookiesCallback& callback)
693 : CookieMonsterTask(cookie_monster), list_(list), callback_(callback) {}
694
695 // CookieMonsterTask:
696 void Run() override;
697
698 protected:
699 ~SetAllCookiesTask() override {}
700
701 private:
702 CookieList list_;
703 SetCookiesCallback callback_;
704
705 DISALLOW_COPY_AND_ASSIGN(SetAllCookiesTask);
706};
707
708void CookieMonster::SetAllCookiesTask::Run() {
709 CookieList positive_diff;
710 CookieList negative_diff;
711 CookieList old_cookies = this->cookie_monster()->GetAllCookies();
712 this->cookie_monster()->ComputeCookieDiff(&old_cookies, &list_,
713 &positive_diff, &negative_diff);
714
715 for (CookieList::const_iterator it = negative_diff.begin();
716 it != negative_diff.end(); ++it) {
717 this->cookie_monster()->DeleteCanonicalCookie(*it);
718 }
719
720 bool result = true;
721 if (positive_diff.size() > 0)
722 result = this->cookie_monster()->SetCanonicalCookies(list_);
723
mmenkebe0910d2016-03-01 19:09:09724 if (!callback_.is_null())
725 callback_.Run(result);
drogerd5d1278c2015-03-17 19:21:51726}
727
[email protected]218aa6a12011-09-13 17:38:38728// Task class for GetCookiesWithOptions call.
[email protected]5fa4f9a2013-10-03 10:13:16729class CookieMonster::GetCookiesWithOptionsTask : public CookieMonsterTask {
[email protected]218aa6a12011-09-13 17:38:38730 public:
731 GetCookiesWithOptionsTask(CookieMonster* cookie_monster,
[email protected]0298caf82011-12-20 23:15:46732 const GURL& url,
[email protected]218aa6a12011-09-13 17:38:38733 const CookieOptions& options,
[email protected]5fa4f9a2013-10-03 10:13:16734 const GetCookiesCallback& callback)
[email protected]218aa6a12011-09-13 17:38:38735 : CookieMonsterTask(cookie_monster),
736 url_(url),
737 options_(options),
mkwstbe84af312015-02-20 08:52:45738 callback_(callback) {}
[email protected]218aa6a12011-09-13 17:38:38739
[email protected]5fa4f9a2013-10-03 10:13:16740 // CookieMonsterTask:
dchengb03027d2014-10-21 12:00:20741 void Run() override;
[email protected]218aa6a12011-09-13 17:38:38742
[email protected]a9813302012-04-28 09:29:28743 protected:
dchengb03027d2014-10-21 12:00:20744 ~GetCookiesWithOptionsTask() override {}
[email protected]a9813302012-04-28 09:29:28745
[email protected]218aa6a12011-09-13 17:38:38746 private:
747 GURL url_;
748 CookieOptions options_;
[email protected]5fa4f9a2013-10-03 10:13:16749 GetCookiesCallback callback_;
[email protected]218aa6a12011-09-13 17:38:38750
751 DISALLOW_COPY_AND_ASSIGN(GetCookiesWithOptionsTask);
752};
753
754void CookieMonster::GetCookiesWithOptionsTask::Run() {
pkastinga9269aa42015-04-10 01:42:26755 // TODO(mkwst): Remove ScopedTracker below once crbug.com/456373 is fixed.
pkasting58e029b2015-02-21 05:17:28756 tracked_objects::ScopedTracker tracking_profile(
757 FROM_HERE_WITH_EXPLICIT_FUNCTION(
758 "456373 CookieMonster::GetCookiesWithOptionsTask::Run"));
mkwstbe84af312015-02-20 08:52:45759 std::string cookie =
760 this->cookie_monster()->GetCookiesWithOptions(url_, options_);
mmenkebe0910d2016-03-01 19:09:09761 if (!callback_.is_null())
762 callback_.Run(cookie);
[email protected]218aa6a12011-09-13 17:38:38763}
764
[email protected]218aa6a12011-09-13 17:38:38765// Task class for DeleteCookie call.
[email protected]5fa4f9a2013-10-03 10:13:16766class CookieMonster::DeleteCookieTask : public DeleteTask<void> {
[email protected]218aa6a12011-09-13 17:38:38767 public:
768 DeleteCookieTask(CookieMonster* cookie_monster,
[email protected]0298caf82011-12-20 23:15:46769 const GURL& url,
[email protected]218aa6a12011-09-13 17:38:38770 const std::string& cookie_name,
771 const base::Closure& callback)
[email protected]151132f2013-11-18 21:37:00772 : DeleteTask<void>(cookie_monster, callback),
[email protected]218aa6a12011-09-13 17:38:38773 url_(url),
mkwstbe84af312015-02-20 08:52:45774 cookie_name_(cookie_name) {}
[email protected]218aa6a12011-09-13 17:38:38775
[email protected]5fa4f9a2013-10-03 10:13:16776 // DeleteTask:
dchengb03027d2014-10-21 12:00:20777 void RunDeleteTask() override;
[email protected]218aa6a12011-09-13 17:38:38778
[email protected]a9813302012-04-28 09:29:28779 protected:
dchengb03027d2014-10-21 12:00:20780 ~DeleteCookieTask() override {}
[email protected]a9813302012-04-28 09:29:28781
[email protected]218aa6a12011-09-13 17:38:38782 private:
783 GURL url_;
784 std::string cookie_name_;
[email protected]218aa6a12011-09-13 17:38:38785
786 DISALLOW_COPY_AND_ASSIGN(DeleteCookieTask);
787};
788
[email protected]5fa4f9a2013-10-03 10:13:16789void CookieMonster::DeleteCookieTask::RunDeleteTask() {
[email protected]218aa6a12011-09-13 17:38:38790 this->cookie_monster()->DeleteCookie(url_, cookie_name_);
[email protected]218aa6a12011-09-13 17:38:38791}
792
[email protected]264807b2012-04-25 14:49:37793// Task class for DeleteSessionCookies call.
[email protected]5fa4f9a2013-10-03 10:13:16794class CookieMonster::DeleteSessionCookiesTask : public DeleteTask<int> {
[email protected]264807b2012-04-25 14:49:37795 public:
[email protected]dedec0b2013-02-28 04:50:10796 DeleteSessionCookiesTask(CookieMonster* cookie_monster,
[email protected]5fa4f9a2013-10-03 10:13:16797 const DeleteCallback& callback)
mkwstbe84af312015-02-20 08:52:45798 : DeleteTask<int>(cookie_monster, callback) {}
[email protected]264807b2012-04-25 14:49:37799
[email protected]5fa4f9a2013-10-03 10:13:16800 // DeleteTask:
dchengb03027d2014-10-21 12:00:20801 int RunDeleteTask() override;
[email protected]264807b2012-04-25 14:49:37802
[email protected]a9813302012-04-28 09:29:28803 protected:
dchengb03027d2014-10-21 12:00:20804 ~DeleteSessionCookiesTask() override {}
[email protected]a9813302012-04-28 09:29:28805
[email protected]264807b2012-04-25 14:49:37806 private:
[email protected]264807b2012-04-25 14:49:37807 DISALLOW_COPY_AND_ASSIGN(DeleteSessionCookiesTask);
808};
809
[email protected]5fa4f9a2013-10-03 10:13:16810int CookieMonster::DeleteSessionCookiesTask::RunDeleteTask() {
811 return this->cookie_monster()->DeleteSessionCookies();
[email protected]264807b2012-04-25 14:49:37812}
813
[email protected]218aa6a12011-09-13 17:38:38814// Asynchronous CookieMonster API
815
816void CookieMonster::SetCookieWithDetailsAsync(
[email protected]dedec0b2013-02-28 04:50:10817 const GURL& url,
818 const std::string& name,
819 const std::string& value,
820 const std::string& domain,
821 const std::string& path,
mmenkefdd4fc72016-02-05 20:53:24822 Time creation_time,
823 Time expiration_time,
824 Time last_access_time,
[email protected]dedec0b2013-02-28 04:50:10825 bool secure,
826 bool http_only,
mkwst46549412016-02-01 10:05:37827 bool same_site,
jww601411a2015-11-20 19:46:57828 bool enforce_strict_secure,
[email protected]ab2d75c82013-04-19 18:39:04829 CookiePriority priority,
[email protected]218aa6a12011-09-13 17:38:38830 const SetCookiesCallback& callback) {
mkwstbe84af312015-02-20 08:52:45831 scoped_refptr<SetCookieWithDetailsTask> task = new SetCookieWithDetailsTask(
mmenkeea4cd402016-02-02 04:03:10832 this, url, name, value, domain, path, creation_time, expiration_time,
mmenkefdd4fc72016-02-05 20:53:24833 last_access_time, secure, http_only, same_site, enforce_strict_secure,
834 priority, callback);
[email protected]85620342011-10-17 17:35:04835 DoCookieTaskForURL(task, url);
[email protected]218aa6a12011-09-13 17:38:38836}
837
mmenke74bcbd52016-01-21 17:17:56838void CookieMonster::FlushStore(const base::Closure& callback) {
mmenkebe0910d2016-03-01 19:09:09839 DCHECK(thread_checker_.CalledOnValidThread());
mmenke606c59c2016-03-07 18:20:55840
mmenke74bcbd52016-01-21 17:17:56841 if (initialized_ && store_.get())
842 store_->Flush(callback);
843 else if (!callback.is_null())
844 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, callback);
845}
846
mmenkeded79da2016-02-06 08:28:51847void CookieMonster::SetForceKeepSessionState() {
mmenkebe0910d2016-03-01 19:09:09848 DCHECK(thread_checker_.CalledOnValidThread());
mmenke606c59c2016-03-07 18:20:55849
mmenkeded79da2016-02-06 08:28:51850 if (store_)
851 store_->SetForceKeepSessionState();
852}
853
drogerd5d1278c2015-03-17 19:21:51854void CookieMonster::SetAllCookiesAsync(const CookieList& list,
855 const SetCookiesCallback& callback) {
856 scoped_refptr<SetAllCookiesTask> task =
857 new SetAllCookiesTask(this, list, callback);
858 DoCookieTask(task);
859}
860
[email protected]218aa6a12011-09-13 17:38:38861void CookieMonster::SetCookieWithOptionsAsync(
862 const GURL& url,
863 const std::string& cookie_line,
864 const CookieOptions& options,
865 const SetCookiesCallback& callback) {
866 scoped_refptr<SetCookieWithOptionsTask> task =
867 new SetCookieWithOptionsTask(this, url, cookie_line, options, callback);
868
[email protected]85620342011-10-17 17:35:04869 DoCookieTaskForURL(task, url);
[email protected]218aa6a12011-09-13 17:38:38870}
871
872void CookieMonster::GetCookiesWithOptionsAsync(
873 const GURL& url,
874 const CookieOptions& options,
875 const GetCookiesCallback& callback) {
876 scoped_refptr<GetCookiesWithOptionsTask> task =
877 new GetCookiesWithOptionsTask(this, url, options, callback);
878
[email protected]85620342011-10-17 17:35:04879 DoCookieTaskForURL(task, url);
[email protected]218aa6a12011-09-13 17:38:38880}
881
mkwstc611e6d2016-02-23 15:45:55882void CookieMonster::GetCookieListWithOptionsAsync(
mmenke74bcbd52016-01-21 17:17:56883 const GURL& url,
mkwstc611e6d2016-02-23 15:45:55884 const CookieOptions& options,
mmenke74bcbd52016-01-21 17:17:56885 const GetCookieListCallback& callback) {
mkwstc611e6d2016-02-23 15:45:55886 scoped_refptr<GetCookieListWithOptionsTask> task =
887 new GetCookieListWithOptionsTask(this, url, options, callback);
mmenke74bcbd52016-01-21 17:17:56888
889 DoCookieTaskForURL(task, url);
890}
891
mmenke9fa44f2d2016-01-22 23:36:39892void CookieMonster::GetAllCookiesAsync(const GetCookieListCallback& callback) {
893 scoped_refptr<GetAllCookiesTask> task = new GetAllCookiesTask(this, callback);
894
895 DoCookieTask(task);
896}
897
[email protected]218aa6a12011-09-13 17:38:38898void CookieMonster::DeleteCookieAsync(const GURL& url,
899 const std::string& cookie_name,
900 const base::Closure& callback) {
901 scoped_refptr<DeleteCookieTask> task =
902 new DeleteCookieTask(this, url, cookie_name, callback);
903
[email protected]85620342011-10-17 17:35:04904 DoCookieTaskForURL(task, url);
[email protected]218aa6a12011-09-13 17:38:38905}
906
mmenke24379d52016-02-05 23:50:17907void CookieMonster::DeleteCanonicalCookieAsync(const CanonicalCookie& cookie,
908 const DeleteCallback& callback) {
909 scoped_refptr<DeleteCanonicalCookieTask> task =
910 new DeleteCanonicalCookieTask(this, cookie, callback);
911
912 DoCookieTask(task);
913}
914
mmenke74bcbd52016-01-21 17:17:56915void CookieMonster::DeleteAllCreatedBetweenAsync(
916 const Time& delete_begin,
917 const Time& delete_end,
918 const DeleteCallback& callback) {
919 scoped_refptr<DeleteAllCreatedBetweenTask> task =
920 new DeleteAllCreatedBetweenTask(this, delete_begin, delete_end, callback);
921
922 DoCookieTask(task);
923}
924
925void CookieMonster::DeleteAllCreatedBetweenForHostAsync(
926 const Time delete_begin,
927 const Time delete_end,
928 const GURL& url,
929 const DeleteCallback& callback) {
930 scoped_refptr<DeleteAllCreatedBetweenForHostTask> task =
931 new DeleteAllCreatedBetweenForHostTask(this, delete_begin, delete_end,
932 url, callback);
933
934 DoCookieTaskForURL(task, url);
935}
936
[email protected]264807b2012-04-25 14:49:37937void CookieMonster::DeleteSessionCookiesAsync(
938 const CookieStore::DeleteCallback& callback) {
939 scoped_refptr<DeleteSessionCookiesTask> task =
940 new DeleteSessionCookiesTask(this, callback);
941
942 DoCookieTask(task);
943}
944
mmenke18dd8ba2016-02-01 18:42:10945void CookieMonster::SetCookieableSchemes(
946 const std::vector<std::string>& schemes) {
mmenkebe0910d2016-03-01 19:09:09947 DCHECK(thread_checker_.CalledOnValidThread());
mmenke74bcbd52016-01-21 17:17:56948
949 // Calls to this method will have no effect if made after a WebView or
950 // CookieManager instance has been created.
mmenke18dd8ba2016-02-01 18:42:10951 if (initialized_)
mmenke74bcbd52016-01-21 17:17:56952 return;
mmenke74bcbd52016-01-21 17:17:56953
mmenke18dd8ba2016-02-01 18:42:10954 cookieable_schemes_ = schemes;
mmenke74bcbd52016-01-21 17:17:56955}
956
mmenke74bcbd52016-01-21 17:17:56957// This function must be called before the CookieMonster is used.
958void CookieMonster::SetPersistSessionCookies(bool persist_session_cookies) {
mmenkebe0910d2016-03-01 19:09:09959 DCHECK(thread_checker_.CalledOnValidThread());
mmenke74bcbd52016-01-21 17:17:56960 DCHECK(!initialized_);
961 persist_session_cookies_ = persist_session_cookies;
962}
963
964bool CookieMonster::IsCookieableScheme(const std::string& scheme) {
mmenkebe0910d2016-03-01 19:09:09965 DCHECK(thread_checker_.CalledOnValidThread());
mmenke74bcbd52016-01-21 17:17:56966
967 return std::find(cookieable_schemes_.begin(), cookieable_schemes_.end(),
968 scheme) != cookieable_schemes_.end();
969}
970
mmenke18dd8ba2016-02-01 18:42:10971const char* const CookieMonster::kDefaultCookieableSchemes[] = {"http", "https",
972 "ws", "wss"};
mmenke74bcbd52016-01-21 17:17:56973const int CookieMonster::kDefaultCookieableSchemesCount =
974 arraysize(kDefaultCookieableSchemes);
975
976scoped_ptr<CookieStore::CookieChangedSubscription>
977CookieMonster::AddCallbackForCookie(const GURL& gurl,
978 const std::string& name,
979 const CookieChangedCallback& callback) {
mmenkebe0910d2016-03-01 19:09:09980 DCHECK(thread_checker_.CalledOnValidThread());
mmenke606c59c2016-03-07 18:20:55981
mmenke74bcbd52016-01-21 17:17:56982 std::pair<GURL, std::string> key(gurl, name);
983 if (hook_map_.count(key) == 0)
984 hook_map_[key] = make_linked_ptr(new CookieChangedCallbackList());
985 return hook_map_[key]->Add(
986 base::Bind(&RunAsync, base::ThreadTaskRunnerHandle::Get(), callback));
987}
988
nharper5babb5e62016-03-09 18:58:07989bool CookieMonster::IsEphemeral() {
990 return store_.get() == nullptr;
991}
992
mmenke74bcbd52016-01-21 17:17:56993CookieMonster::~CookieMonster() {
mmenkebe0910d2016-03-01 19:09:09994 DCHECK(thread_checker_.CalledOnValidThread());
mmenke05255cf2016-02-03 15:49:31995
mmenke606c59c2016-03-07 18:20:55996 // TODO(mmenke): Does it really make sense to run |delegate_| and
997 // CookieChanged callbacks when the CookieStore is destroyed?
mmenke05255cf2016-02-03 15:49:31998 for (CookieMap::iterator cookie_it = cookies_.begin();
999 cookie_it != cookies_.end();) {
1000 CookieMap::iterator current_cookie_it = cookie_it;
1001 ++cookie_it;
1002 InternalDeleteCookie(current_cookie_it, false /* sync_to_store */,
1003 DELETE_COOKIE_DONT_RECORD);
1004 }
[email protected]85620342011-10-17 17:35:041005}
1006
[email protected]dedec0b2013-02-28 04:50:101007bool CookieMonster::SetCookieWithDetails(const GURL& url,
1008 const std::string& name,
1009 const std::string& value,
1010 const std::string& domain,
1011 const std::string& path,
mmenkefdd4fc72016-02-05 20:53:241012 base::Time creation_time,
1013 base::Time expiration_time,
1014 base::Time last_access_time,
[email protected]dedec0b2013-02-28 04:50:101015 bool secure,
[email protected]ab2d75c82013-04-19 18:39:041016 bool http_only,
mkwst46549412016-02-01 10:05:371017 bool same_site,
jww601411a2015-11-20 19:46:571018 bool enforce_strict_secure,
[email protected]ab2d75c82013-04-19 18:39:041019 CookiePriority priority) {
mmenkebe0910d2016-03-01 19:09:091020 DCHECK(thread_checker_.CalledOnValidThread());
[email protected]69bb5872010-01-12 20:33:521021
[email protected]f48b9432011-01-11 07:25:401022 if (!HasCookieableScheme(url))
initial.commit586acc5fe2008-07-26 22:42:521023 return false;
1024
mmenkeea4cd402016-02-02 04:03:101025 // TODO(mmenke): This class assumes each cookie to have a unique creation
1026 // time. Allowing the caller to set the creation time violates that
1027 // assumption. Worth fixing? Worth noting that time changes between browser
1028 // restarts can cause the same issue.
1029 base::Time actual_creation_time = creation_time;
1030 if (creation_time.is_null()) {
1031 actual_creation_time = CurrentTime();
1032 last_time_seen_ = actual_creation_time;
1033 }
[email protected]f48b9432011-01-11 07:25:401034
tfh4623ce82016-01-21 10:37:371035 scoped_ptr<CanonicalCookie> cc(CanonicalCookie::Create(
mmenkeea4cd402016-02-02 04:03:101036 url, name, value, domain, path, actual_creation_time, expiration_time,
1037 secure, http_only, same_site, enforce_strict_secure, priority));
[email protected]f48b9432011-01-11 07:25:401038
1039 if (!cc.get())
1040 return false;
1041
mmenkefdd4fc72016-02-05 20:53:241042 if (!last_access_time.is_null())
1043 cc->SetLastAccessDate(last_access_time);
1044
[email protected]f48b9432011-01-11 07:25:401045 CookieOptions options;
1046 options.set_include_httponly();
mkwst46549412016-02-01 10:05:371047 options.set_include_same_site();
jww601411a2015-11-20 19:46:571048 if (enforce_strict_secure)
1049 options.set_enforce_strict_secure();
mmenkeea4cd402016-02-02 04:03:101050 return SetCanonicalCookie(std::move(cc), options);
initial.commit586acc5fe2008-07-26 22:42:521051}
1052
[email protected]f48b9432011-01-11 07:25:401053CookieList CookieMonster::GetAllCookies() {
mmenkebe0910d2016-03-01 19:09:091054 DCHECK(thread_checker_.CalledOnValidThread());
[email protected]f48b9432011-01-11 07:25:401055
1056 // This function is being called to scrape the cookie list for management UI
1057 // or similar. We shouldn't show expired cookies in this list since it will
1058 // just be confusing to users, and this function is called rarely enough (and
1059 // is already slow enough) that it's OK to take the time to garbage collect
1060 // the expired cookies now.
1061 //
1062 // Note that this does not prune cookies to be below our limits (if we've
1063 // exceeded them) the way that calling GarbageCollect() would.
mkwstbe84af312015-02-20 08:52:451064 GarbageCollectExpired(
1065 Time::Now(), CookieMapItPair(cookies_.begin(), cookies_.end()), NULL);
[email protected]f48b9432011-01-11 07:25:401066
1067 // Copy the CanonicalCookie pointers from the map so that we can use the same
1068 // sorter as elsewhere, then copy the result out.
1069 std::vector<CanonicalCookie*> cookie_ptrs;
1070 cookie_ptrs.reserve(cookies_.size());
1071 for (CookieMap::iterator it = cookies_.begin(); it != cookies_.end(); ++it)
1072 cookie_ptrs.push_back(it->second);
1073 std::sort(cookie_ptrs.begin(), cookie_ptrs.end(), CookieSorter);
1074
1075 CookieList cookie_list;
1076 cookie_list.reserve(cookie_ptrs.size());
1077 for (std::vector<CanonicalCookie*>::const_iterator it = cookie_ptrs.begin();
1078 it != cookie_ptrs.end(); ++it)
1079 cookie_list.push_back(**it);
1080
1081 return cookie_list;
[email protected]f325f1e12010-04-30 22:38:551082}
1083
mkwstc611e6d2016-02-23 15:45:551084CookieList CookieMonster::GetCookieListWithOptions(
[email protected]f48b9432011-01-11 07:25:401085 const GURL& url,
1086 const CookieOptions& options) {
mmenkebe0910d2016-03-01 19:09:091087 DCHECK(thread_checker_.CalledOnValidThread());
initial.commit586acc5fe2008-07-26 22:42:521088
mkwstc611e6d2016-02-23 15:45:551089 CookieList cookies;
1090 if (!HasCookieableScheme(url))
1091 return cookies;
1092
[email protected]f48b9432011-01-11 07:25:401093 std::vector<CanonicalCookie*> cookie_ptrs;
mkwst72b65162016-02-22 19:58:541094 FindCookiesForHostAndDomain(url, options, &cookie_ptrs);
[email protected]f48b9432011-01-11 07:25:401095 std::sort(cookie_ptrs.begin(), cookie_ptrs.end(), CookieSorter);
initial.commit586acc5fe2008-07-26 22:42:521096
georgesakc15df6722014-12-02 23:52:121097 cookies.reserve(cookie_ptrs.size());
[email protected]f48b9432011-01-11 07:25:401098 for (std::vector<CanonicalCookie*>::const_iterator it = cookie_ptrs.begin();
1099 it != cookie_ptrs.end(); it++)
1100 cookies.push_back(**it);
initial.commit586acc5fe2008-07-26 22:42:521101
[email protected]f48b9432011-01-11 07:25:401102 return cookies;
initial.commit586acc5fe2008-07-26 22:42:521103}
1104
[email protected]f48b9432011-01-11 07:25:401105int CookieMonster::DeleteAllCreatedBetween(const Time& delete_begin,
[email protected]218aa6a12011-09-13 17:38:381106 const Time& delete_end) {
mmenkebe0910d2016-03-01 19:09:091107 DCHECK(thread_checker_.CalledOnValidThread());
[email protected]d0980332010-11-16 17:08:531108
[email protected]f48b9432011-01-11 07:25:401109 int num_deleted = 0;
1110 for (CookieMap::iterator it = cookies_.begin(); it != cookies_.end();) {
1111 CookieMap::iterator curit = it;
1112 CanonicalCookie* cc = curit->second;
1113 ++it;
[email protected]d0980332010-11-16 17:08:531114
[email protected]f48b9432011-01-11 07:25:401115 if (cc->CreationDate() >= delete_begin &&
1116 (delete_end.is_null() || cc->CreationDate() < delete_end)) {
mkwstbe84af312015-02-20 08:52:451117 InternalDeleteCookie(curit, true, /*sync_to_store*/
[email protected]218aa6a12011-09-13 17:38:381118 DELETE_COOKIE_EXPLICIT);
[email protected]f48b9432011-01-11 07:25:401119 ++num_deleted;
initial.commit586acc5fe2008-07-26 22:42:521120 }
1121 }
1122
[email protected]f48b9432011-01-11 07:25:401123 return num_deleted;
1124}
1125
[email protected]d8428d52013-08-07 06:58:251126int CookieMonster::DeleteAllCreatedBetweenForHost(const Time delete_begin,
1127 const Time delete_end,
1128 const GURL& url) {
mmenkebe0910d2016-03-01 19:09:091129 DCHECK(thread_checker_.CalledOnValidThread());
[email protected]f48b9432011-01-11 07:25:401130
1131 if (!HasCookieableScheme(url))
1132 return 0;
1133
[email protected]f48b9432011-01-11 07:25:401134 const std::string host(url.host());
1135
1136 // We store host cookies in the store by their canonical host name;
1137 // domain cookies are stored with a leading ".". So this is a pretty
1138 // simple lookup and per-cookie delete.
1139 int num_deleted = 0;
1140 for (CookieMapItPair its = cookies_.equal_range(GetKey(host));
1141 its.first != its.second;) {
1142 CookieMap::iterator curit = its.first;
1143 ++its.first;
1144
1145 const CanonicalCookie* const cc = curit->second;
1146
1147 // Delete only on a match as a host cookie.
[email protected]d8428d52013-08-07 06:58:251148 if (cc->IsHostCookie() && cc->IsDomainMatch(host) &&
1149 cc->CreationDate() >= delete_begin &&
1150 // The assumption that null |delete_end| is equivalent to
1151 // Time::Max() is confusing.
1152 (delete_end.is_null() || cc->CreationDate() < delete_end)) {
[email protected]f48b9432011-01-11 07:25:401153 num_deleted++;
1154
1155 InternalDeleteCookie(curit, true, DELETE_COOKIE_EXPLICIT);
1156 }
1157 }
1158 return num_deleted;
1159}
1160
[email protected]d8428d52013-08-07 06:58:251161
[email protected]f48b9432011-01-11 07:25:401162bool CookieMonster::SetCookieWithOptions(const GURL& url,
1163 const std::string& cookie_line,
1164 const CookieOptions& options) {
mmenkebe0910d2016-03-01 19:09:091165 DCHECK(thread_checker_.CalledOnValidThread());
[email protected]f48b9432011-01-11 07:25:401166
1167 if (!HasCookieableScheme(url)) {
1168 return false;
1169 }
1170
[email protected]f48b9432011-01-11 07:25:401171 return SetCookieWithCreationTimeAndOptions(url, cookie_line, Time(), options);
1172}
1173
1174std::string CookieMonster::GetCookiesWithOptions(const GURL& url,
1175 const CookieOptions& options) {
mmenkebe0910d2016-03-01 19:09:091176 DCHECK(thread_checker_.CalledOnValidThread());
[email protected]f48b9432011-01-11 07:25:401177
[email protected]34a160d2011-05-12 22:12:491178 if (!HasCookieableScheme(url))
[email protected]f48b9432011-01-11 07:25:401179 return std::string();
[email protected]f48b9432011-01-11 07:25:401180
[email protected]f48b9432011-01-11 07:25:401181 std::vector<CanonicalCookie*> cookies;
mkwst72b65162016-02-22 19:58:541182 FindCookiesForHostAndDomain(url, options, &cookies);
[email protected]f48b9432011-01-11 07:25:401183 std::sort(cookies.begin(), cookies.end(), CookieSorter);
1184
[email protected]34a160d2011-05-12 22:12:491185 std::string cookie_line = BuildCookieLine(cookies);
[email protected]f48b9432011-01-11 07:25:401186
[email protected]f48b9432011-01-11 07:25:401187 VLOG(kVlogGetCookies) << "GetCookies() result: " << cookie_line;
1188
1189 return cookie_line;
1190}
1191
1192void CookieMonster::DeleteCookie(const GURL& url,
1193 const std::string& cookie_name) {
mmenkebe0910d2016-03-01 19:09:091194 DCHECK(thread_checker_.CalledOnValidThread());
[email protected]f48b9432011-01-11 07:25:401195
1196 if (!HasCookieableScheme(url))
1197 return;
1198
1199 CookieOptions options;
1200 options.set_include_httponly();
mkwst46549412016-02-01 10:05:371201 options.set_include_same_site();
[email protected]f48b9432011-01-11 07:25:401202 // Get the cookies for this host and its domain(s).
1203 std::vector<CanonicalCookie*> cookies;
mkwst72b65162016-02-22 19:58:541204 FindCookiesForHostAndDomain(url, options, &cookies);
[email protected]f48b9432011-01-11 07:25:401205 std::set<CanonicalCookie*> matching_cookies;
1206
mmenke4379aeb2016-03-05 12:22:071207 for (const auto& cookie : cookies) {
1208 if (cookie->Name() != cookie_name)
[email protected]f48b9432011-01-11 07:25:401209 continue;
mmenke4379aeb2016-03-05 12:22:071210 if (!cookie->IsOnPath(url.path()))
[email protected]f48b9432011-01-11 07:25:401211 continue;
mmenke4379aeb2016-03-05 12:22:071212 matching_cookies.insert(cookie);
[email protected]f48b9432011-01-11 07:25:401213 }
1214
1215 for (CookieMap::iterator it = cookies_.begin(); it != cookies_.end();) {
1216 CookieMap::iterator curit = it;
1217 ++it;
1218 if (matching_cookies.find(curit->second) != matching_cookies.end()) {
1219 InternalDeleteCookie(curit, true, DELETE_COOKIE_EXPLICIT);
1220 }
1221 }
1222}
1223
mmenke24379d52016-02-05 23:50:171224int CookieMonster::DeleteCanonicalCookie(const CanonicalCookie& cookie) {
mmenkebe0910d2016-03-01 19:09:091225 DCHECK(thread_checker_.CalledOnValidThread());
mmenke24379d52016-02-05 23:50:171226
1227 for (CookieMapItPair its = cookies_.equal_range(GetKey(cookie.Domain()));
1228 its.first != its.second; ++its.first) {
1229 // The creation date acts as the unique index...
1230 if (its.first->second->CreationDate() == cookie.CreationDate()) {
1231 InternalDeleteCookie(its.first, true, DELETE_COOKIE_EXPLICIT);
1232 return 1;
1233 }
1234 }
1235 return 0;
1236}
1237
mmenke74bcbd52016-01-21 17:17:561238bool CookieMonster::SetCookieWithCreationTime(const GURL& url,
1239 const std::string& cookie_line,
1240 const base::Time& creation_time) {
mmenkebe0910d2016-03-01 19:09:091241 DCHECK(thread_checker_.CalledOnValidThread());
mmenke74bcbd52016-01-21 17:17:561242 DCHECK(!store_.get()) << "This method is only to be used by unit-tests.";
mmenke74bcbd52016-01-21 17:17:561243
1244 if (!HasCookieableScheme(url)) {
1245 return false;
1246 }
1247
1248 MarkCookieStoreAsInitialized();
1249 if (ShouldFetchAllCookiesWhenFetchingAnyCookie())
1250 FetchAllCookiesIfNecessary();
1251
1252 return SetCookieWithCreationTimeAndOptions(url, cookie_line, creation_time,
1253 CookieOptions());
1254}
1255
[email protected]264807b2012-04-25 14:49:371256int CookieMonster::DeleteSessionCookies() {
mmenkebe0910d2016-03-01 19:09:091257 DCHECK(thread_checker_.CalledOnValidThread());
[email protected]264807b2012-04-25 14:49:371258
1259 int num_deleted = 0;
1260 for (CookieMap::iterator it = cookies_.begin(); it != cookies_.end();) {
1261 CookieMap::iterator curit = it;
1262 CanonicalCookie* cc = curit->second;
1263 ++it;
1264
1265 if (!cc->IsPersistent()) {
mkwstbe84af312015-02-20 08:52:451266 InternalDeleteCookie(curit, true, /*sync_to_store*/
[email protected]264807b2012-04-25 14:49:371267 DELETE_COOKIE_EXPIRED);
1268 ++num_deleted;
1269 }
1270 }
1271
1272 return num_deleted;
1273}
1274
erikchen1dd72a72015-05-06 20:45:051275void CookieMonster::MarkCookieStoreAsInitialized() {
mmenkebe0910d2016-03-01 19:09:091276 DCHECK(thread_checker_.CalledOnValidThread());
erikchen1dd72a72015-05-06 20:45:051277 initialized_ = true;
1278}
1279
1280void CookieMonster::FetchAllCookiesIfNecessary() {
mmenkebe0910d2016-03-01 19:09:091281 DCHECK(thread_checker_.CalledOnValidThread());
erikchen1dd72a72015-05-06 20:45:051282 if (store_.get() && !started_fetching_all_cookies_) {
1283 started_fetching_all_cookies_ = true;
1284 FetchAllCookies();
1285 }
1286}
1287
mmenke74bcbd52016-01-21 17:17:561288void CookieMonster::FetchAllCookies() {
mmenkebe0910d2016-03-01 19:09:091289 DCHECK(thread_checker_.CalledOnValidThread());
mmenke74bcbd52016-01-21 17:17:561290 DCHECK(store_.get()) << "Store must exist to initialize";
1291 DCHECK(!finished_fetching_all_cookies_)
1292 << "All cookies have already been fetched.";
1293
1294 // We bind in the current time so that we can report the wall-clock time for
1295 // loading cookies.
mmenkebe0910d2016-03-01 19:09:091296 store_->Load(base::Bind(&CookieMonster::OnLoaded,
1297 weak_ptr_factory_.GetWeakPtr(), TimeTicks::Now()));
mmenke74bcbd52016-01-21 17:17:561298}
1299
erikchen1dd72a72015-05-06 20:45:051300bool CookieMonster::ShouldFetchAllCookiesWhenFetchingAnyCookie() {
mmenkebe0910d2016-03-01 19:09:091301 DCHECK(thread_checker_.CalledOnValidThread());
1302
erikchen1dd72a72015-05-06 20:45:051303 if (fetch_strategy_ == kUnknownFetch) {
1304 const std::string group_name =
1305 base::FieldTrialList::FindFullName(kCookieMonsterFetchStrategyName);
1306 if (group_name == kFetchWhenNecessaryName) {
1307 fetch_strategy_ = kFetchWhenNecessary;
1308 } else if (group_name == kAlwaysFetchName) {
1309 fetch_strategy_ = kAlwaysFetch;
1310 } else {
1311 // The logic in the conditional is redundant, but it makes trials of
1312 // the Finch experiment more explicit.
1313 fetch_strategy_ = kAlwaysFetch;
1314 }
1315 }
1316
1317 return fetch_strategy_ == kAlwaysFetch;
1318}
1319
[email protected]218aa6a12011-09-13 17:38:381320void CookieMonster::OnLoaded(TimeTicks beginning_time,
1321 const std::vector<CanonicalCookie*>& cookies) {
mmenkebe0910d2016-03-01 19:09:091322 DCHECK(thread_checker_.CalledOnValidThread());
[email protected]218aa6a12011-09-13 17:38:381323 StoreLoadedCookies(cookies);
[email protected]c7593fb22011-11-14 23:54:271324 histogram_time_blocked_on_load_->AddTime(TimeTicks::Now() - beginning_time);
[email protected]218aa6a12011-09-13 17:38:381325
1326 // Invoke the task queue of cookie request.
1327 InvokeQueue();
1328}
1329
[email protected]85620342011-10-17 17:35:041330void CookieMonster::OnKeyLoaded(const std::string& key,
1331 const std::vector<CanonicalCookie*>& cookies) {
mmenkebe0910d2016-03-01 19:09:091332 DCHECK(thread_checker_.CalledOnValidThread());
1333
[email protected]85620342011-10-17 17:35:041334 StoreLoadedCookies(cookies);
1335
mmenkebe0910d2016-03-01 19:09:091336 auto tasks_pending_for_key = tasks_pending_for_key_.find(key);
[email protected]85620342011-10-17 17:35:041337
mmenkebe0910d2016-03-01 19:09:091338 // TODO(mmenke): Can this be turned into a DCHECK?
1339 if (tasks_pending_for_key == tasks_pending_for_key_.end())
1340 return;
[email protected]bab72ec2013-10-30 20:50:021341
mmenkebe0910d2016-03-01 19:09:091342 // Run all tasks for the key. Note that running a task can result in multiple
1343 // tasks being added to the back of the deque.
1344 while (!tasks_pending_for_key->second.empty()) {
1345 scoped_refptr<CookieMonsterTask> task =
1346 tasks_pending_for_key->second.front();
1347 tasks_pending_for_key->second.pop_front();
1348
1349 task->Run();
[email protected]85620342011-10-17 17:35:041350 }
mmenkebe0910d2016-03-01 19:09:091351
1352 tasks_pending_for_key_.erase(tasks_pending_for_key);
1353
1354 // This has to be done last, in case running a task queues a new task for the
1355 // key, to ensure tasks are run in the correct order.
1356 keys_loaded_.insert(key);
[email protected]85620342011-10-17 17:35:041357}
1358
[email protected]218aa6a12011-09-13 17:38:381359void CookieMonster::StoreLoadedCookies(
1360 const std::vector<CanonicalCookie*>& cookies) {
mmenkebe0910d2016-03-01 19:09:091361 DCHECK(thread_checker_.CalledOnValidThread());
1362
pkastingec2cdb52015-05-02 01:19:341363 // TODO(erikwright): Remove ScopedTracker below once crbug.com/457528 is
1364 // fixed.
1365 tracked_objects::ScopedTracker tracking_profile(
1366 FROM_HERE_WITH_EXPLICIT_FUNCTION(
1367 "457528 CookieMonster::StoreLoadedCookies"));
1368
mmenkebe0910d2016-03-01 19:09:091369 // Even if a key is expired, insert it so it can be garbage collected,
1370 // removed, and sync'd.
[email protected]6210ce52013-09-20 03:33:141371 CookieItVector cookies_with_control_chars;
1372
[email protected]f48b9432011-01-11 07:25:401373 for (std::vector<CanonicalCookie*>::const_iterator it = cookies.begin();
1374 it != cookies.end(); ++it) {
Avi Drissman13fc8932015-12-20 04:40:461375 int64_t cookie_creation_time = (*it)->CreationDate().ToInternalValue();
[email protected]f48b9432011-01-11 07:25:401376
[email protected]85620342011-10-17 17:35:041377 if (creation_times_.insert(cookie_creation_time).second) {
[email protected]6210ce52013-09-20 03:33:141378 CookieMap::iterator inserted =
1379 InternalInsertCookie(GetKey((*it)->Domain()), *it, false);
[email protected]f48b9432011-01-11 07:25:401380 const Time cookie_access_time((*it)->LastAccessDate());
[email protected]85620342011-10-17 17:35:041381 if (earliest_access_time_.is_null() ||
1382 cookie_access_time < earliest_access_time_)
1383 earliest_access_time_ = cookie_access_time;
[email protected]6210ce52013-09-20 03:33:141384
1385 if (ContainsControlCharacter((*it)->Name()) ||
1386 ContainsControlCharacter((*it)->Value())) {
mkwstbe84af312015-02-20 08:52:451387 cookies_with_control_chars.push_back(inserted);
[email protected]6210ce52013-09-20 03:33:141388 }
[email protected]f48b9432011-01-11 07:25:401389 } else {
mkwstbe84af312015-02-20 08:52:451390 LOG(ERROR) << base::StringPrintf(
1391 "Found cookies with duplicate creation "
1392 "times in backing store: "
1393 "{name='%s', domain='%s', path='%s'}",
1394 (*it)->Name().c_str(), (*it)->Domain().c_str(),
1395 (*it)->Path().c_str());
[email protected]f48b9432011-01-11 07:25:401396 // We've been given ownership of the cookie and are throwing it
1397 // away; reclaim the space.
1398 delete (*it);
1399 }
1400 }
[email protected]f48b9432011-01-11 07:25:401401
[email protected]6210ce52013-09-20 03:33:141402 // Any cookies that contain control characters that we have loaded from the
1403 // persistent store should be deleted. See http://crbug.com/238041.
1404 for (CookieItVector::iterator it = cookies_with_control_chars.begin();
1405 it != cookies_with_control_chars.end();) {
1406 CookieItVector::iterator curit = it;
1407 ++it;
1408
1409 InternalDeleteCookie(*curit, true, DELETE_COOKIE_CONTROL_CHAR);
1410 }
1411
[email protected]f48b9432011-01-11 07:25:401412 // After importing cookies from the PersistentCookieStore, verify that
1413 // none of our other constraints are violated.
[email protected]f48b9432011-01-11 07:25:401414 // In particular, the backing store might have given us duplicate cookies.
[email protected]85620342011-10-17 17:35:041415
1416 // This method could be called multiple times due to priority loading, thus
1417 // cookies loaded in previous runs will be validated again, but this is OK
1418 // since they are expected to be much fewer than total DB.
[email protected]f48b9432011-01-11 07:25:401419 EnsureCookiesMapIsValid();
[email protected]218aa6a12011-09-13 17:38:381420}
[email protected]f48b9432011-01-11 07:25:401421
[email protected]218aa6a12011-09-13 17:38:381422void CookieMonster::InvokeQueue() {
mmenkebe0910d2016-03-01 19:09:091423 DCHECK(thread_checker_.CalledOnValidThread());
1424
mmenkef49fca0e2016-03-08 12:46:241425 // Move all per-key tasks into the global queue, if there are any. This is
1426 // protection about a race where the store learns about all cookies loading
1427 // before it learned about the cookies for a key loading.
1428
1429 // Needed to prevent any recursively queued tasks from going back into the
1430 // per-key queues.
1431 seen_global_task_ = true;
1432 for (const auto& tasks_for_key : tasks_pending_for_key_) {
1433 tasks_pending_.insert(tasks_pending_.begin(), tasks_for_key.second.begin(),
1434 tasks_for_key.second.end());
1435 }
1436 tasks_pending_for_key_.clear();
1437
mmenkebe0910d2016-03-01 19:09:091438 while (!tasks_pending_.empty()) {
1439 scoped_refptr<CookieMonsterTask> request_task = tasks_pending_.front();
mmenkef49fca0e2016-03-08 12:46:241440 tasks_pending_.pop_front();
[email protected]218aa6a12011-09-13 17:38:381441 request_task->Run();
1442 }
mmenkebe0910d2016-03-01 19:09:091443
mmenkef49fca0e2016-03-08 12:46:241444 DCHECK(tasks_pending_for_key_.empty());
1445
mmenkebe0910d2016-03-01 19:09:091446 finished_fetching_all_cookies_ = true;
1447 creation_times_.clear();
1448 keys_loaded_.clear();
[email protected]f48b9432011-01-11 07:25:401449}
1450
1451void CookieMonster::EnsureCookiesMapIsValid() {
mmenkebe0910d2016-03-01 19:09:091452 DCHECK(thread_checker_.CalledOnValidThread());
[email protected]f48b9432011-01-11 07:25:401453
[email protected]f48b9432011-01-11 07:25:401454 // Iterate through all the of the cookies, grouped by host.
1455 CookieMap::iterator prev_range_end = cookies_.begin();
1456 while (prev_range_end != cookies_.end()) {
1457 CookieMap::iterator cur_range_begin = prev_range_end;
1458 const std::string key = cur_range_begin->first; // Keep a copy.
1459 CookieMap::iterator cur_range_end = cookies_.upper_bound(key);
1460 prev_range_end = cur_range_end;
1461
1462 // Ensure no equivalent cookies for this host.
ellyjonescabf57422015-08-21 18:44:511463 TrimDuplicateCookiesForKey(key, cur_range_begin, cur_range_end);
[email protected]f48b9432011-01-11 07:25:401464 }
[email protected]f48b9432011-01-11 07:25:401465}
1466
ellyjonescabf57422015-08-21 18:44:511467void CookieMonster::TrimDuplicateCookiesForKey(const std::string& key,
1468 CookieMap::iterator begin,
1469 CookieMap::iterator end) {
mmenkebe0910d2016-03-01 19:09:091470 DCHECK(thread_checker_.CalledOnValidThread());
[email protected]f48b9432011-01-11 07:25:401471
1472 // Set of cookies ordered by creation time.
1473 typedef std::set<CookieMap::iterator, OrderByCreationTimeDesc> CookieSet;
1474
1475 // Helper map we populate to find the duplicates.
1476 typedef std::map<CookieSignature, CookieSet> EquivalenceMap;
1477 EquivalenceMap equivalent_cookies;
1478
1479 // The number of duplicate cookies that have been found.
1480 int num_duplicates = 0;
1481
1482 // Iterate through all of the cookies in our range, and insert them into
1483 // the equivalence map.
1484 for (CookieMap::iterator it = begin; it != end; ++it) {
1485 DCHECK_EQ(key, it->first);
1486 CanonicalCookie* cookie = it->second;
1487
mkwstbe84af312015-02-20 08:52:451488 CookieSignature signature(cookie->Name(), cookie->Domain(), cookie->Path());
[email protected]f48b9432011-01-11 07:25:401489 CookieSet& set = equivalent_cookies[signature];
1490
1491 // We found a duplicate!
1492 if (!set.empty())
1493 num_duplicates++;
1494
1495 // We save the iterator into |cookies_| rather than the actual cookie
1496 // pointer, since we may need to delete it later.
1497 bool insert_success = set.insert(it).second;
mkwstbe84af312015-02-20 08:52:451498 DCHECK(insert_success)
1499 << "Duplicate creation times found in duplicate cookie name scan.";
[email protected]f48b9432011-01-11 07:25:401500 }
1501
1502 // If there were no duplicates, we are done!
1503 if (num_duplicates == 0)
ellyjonescabf57422015-08-21 18:44:511504 return;
[email protected]f48b9432011-01-11 07:25:401505
1506 // Make sure we find everything below that we did above.
1507 int num_duplicates_found = 0;
1508
1509 // Otherwise, delete all the duplicate cookies, both from our in-memory store
1510 // and from the backing store.
1511 for (EquivalenceMap::iterator it = equivalent_cookies.begin();
mkwstbe84af312015-02-20 08:52:451512 it != equivalent_cookies.end(); ++it) {
[email protected]f48b9432011-01-11 07:25:401513 const CookieSignature& signature = it->first;
1514 CookieSet& dupes = it->second;
1515
1516 if (dupes.size() <= 1)
1517 continue; // This cookiename/path has no duplicates.
1518 num_duplicates_found += dupes.size() - 1;
1519
1520 // Since |dups| is sorted by creation time (descending), the first cookie
1521 // is the most recent one, so we will keep it. The rest are duplicates.
1522 dupes.erase(dupes.begin());
1523
1524 LOG(ERROR) << base::StringPrintf(
1525 "Found %d duplicate cookies for host='%s', "
1526 "with {name='%s', domain='%s', path='%s'}",
mkwstbe84af312015-02-20 08:52:451527 static_cast<int>(dupes.size()), key.c_str(), signature.name.c_str(),
1528 signature.domain.c_str(), signature.path.c_str());
[email protected]f48b9432011-01-11 07:25:401529
1530 // Remove all the cookies identified by |dupes|. It is valid to delete our
1531 // list of iterators one at a time, since |cookies_| is a multimap (they
1532 // don't invalidate existing iterators following deletion).
mkwstbe84af312015-02-20 08:52:451533 for (CookieSet::iterator dupes_it = dupes.begin(); dupes_it != dupes.end();
[email protected]f48b9432011-01-11 07:25:401534 ++dupes_it) {
[email protected]218aa6a12011-09-13 17:38:381535 InternalDeleteCookie(*dupes_it, true,
[email protected]f48b9432011-01-11 07:25:401536 DELETE_COOKIE_DUPLICATE_IN_BACKING_STORE);
1537 }
1538 }
1539 DCHECK_EQ(num_duplicates, num_duplicates_found);
[email protected]f48b9432011-01-11 07:25:401540}
1541
[email protected]f48b9432011-01-11 07:25:401542void CookieMonster::FindCookiesForHostAndDomain(
1543 const GURL& url,
1544 const CookieOptions& options,
[email protected]f48b9432011-01-11 07:25:401545 std::vector<CanonicalCookie*>* cookies) {
mmenkebe0910d2016-03-01 19:09:091546 DCHECK(thread_checker_.CalledOnValidThread());
[email protected]f48b9432011-01-11 07:25:401547
1548 const Time current_time(CurrentTime());
1549
1550 // Probe to save statistics relatively frequently. We do it here rather
1551 // than in the set path as many websites won't set cookies, and we
1552 // want to collect statistics whenever the browser's being used.
1553 RecordPeriodicStats(current_time);
1554
[email protected]8e1583672012-02-11 04:39:411555 // Can just dispatch to FindCookiesForKey
1556 const std::string key(GetKey(url.host()));
mkwst72b65162016-02-22 19:58:541557 FindCookiesForKey(key, url, options, current_time, cookies);
[email protected]f48b9432011-01-11 07:25:401558}
1559
[email protected]dedec0b2013-02-28 04:50:101560void CookieMonster::FindCookiesForKey(const std::string& key,
1561 const GURL& url,
1562 const CookieOptions& options,
1563 const Time& current,
[email protected]dedec0b2013-02-28 04:50:101564 std::vector<CanonicalCookie*>* cookies) {
mmenkebe0910d2016-03-01 19:09:091565 DCHECK(thread_checker_.CalledOnValidThread());
[email protected]f48b9432011-01-11 07:25:401566
[email protected]f48b9432011-01-11 07:25:401567 for (CookieMapItPair its = cookies_.equal_range(key);
mkwstbe84af312015-02-20 08:52:451568 its.first != its.second;) {
[email protected]f48b9432011-01-11 07:25:401569 CookieMap::iterator curit = its.first;
1570 CanonicalCookie* cc = curit->second;
1571 ++its.first;
1572
1573 // If the cookie is expired, delete it.
mmenke3c79a652016-02-12 14:39:201574 if (cc->IsExpired(current)) {
[email protected]f48b9432011-01-11 07:25:401575 InternalDeleteCookie(curit, true, DELETE_COOKIE_EXPIRED);
1576 continue;
1577 }
1578
[email protected]65f4e7e2012-12-12 21:56:541579 // Filter out cookies that should not be included for a request to the
1580 // given |url|. HTTP only cookies are filtered depending on the passed
1581 // cookie |options|.
1582 if (!cc->IncludeForRequestURL(url, options))
[email protected]f48b9432011-01-11 07:25:401583 continue;
1584
[email protected]65f4e7e2012-12-12 21:56:541585 // Add this cookie to the set of matching cookies. Update the access
[email protected]f48b9432011-01-11 07:25:401586 // time if we've been requested to do so.
mkwst72b65162016-02-22 19:58:541587 if (options.update_access_time()) {
[email protected]f48b9432011-01-11 07:25:401588 InternalUpdateCookieAccessTime(cc, current);
1589 }
1590 cookies->push_back(cc);
1591 }
1592}
1593
1594bool CookieMonster::DeleteAnyEquivalentCookie(const std::string& key,
1595 const CanonicalCookie& ecc,
[email protected]e7c590e52011-03-30 08:33:551596 bool skip_httponly,
jww601411a2015-11-20 19:46:571597 bool already_expired,
1598 bool enforce_strict_secure) {
mmenkebe0910d2016-03-01 19:09:091599 DCHECK(thread_checker_.CalledOnValidThread());
[email protected]f48b9432011-01-11 07:25:401600
1601 bool found_equivalent_cookie = false;
1602 bool skipped_httponly = false;
jww601411a2015-11-20 19:46:571603 bool skipped_secure_cookie = false;
jww31e32632015-12-16 23:38:341604
1605 histogram_cookie_delete_equivalent_->Add(COOKIE_DELETE_EQUIVALENT_ATTEMPT);
1606
[email protected]f48b9432011-01-11 07:25:401607 for (CookieMapItPair its = cookies_.equal_range(key);
mkwstbe84af312015-02-20 08:52:451608 its.first != its.second;) {
[email protected]f48b9432011-01-11 07:25:401609 CookieMap::iterator curit = its.first;
1610 CanonicalCookie* cc = curit->second;
1611 ++its.first;
1612
jww601411a2015-11-20 19:46:571613 // If strict secure cookies is being enforced, then the equivalency
1614 // requirements are looser. If the cookie is being set from an insecure
1615 // scheme, then if a cookie already exists with the same name and it is
1616 // Secure, then the cookie should *not* be updated if they domain-match and
1617 // ignoring the path attribute.
1618 //
1619 // See: https://tools.ietf.org/html/draft-west-leave-secure-cookies-alone
1620 if (enforce_strict_secure && !ecc.Source().SchemeIsCryptographic() &&
1621 ecc.IsEquivalentForSecureCookieMatching(*cc) && cc->IsSecure()) {
1622 skipped_secure_cookie = true;
jww31e32632015-12-16 23:38:341623 histogram_cookie_delete_equivalent_->Add(
1624 COOKIE_DELETE_EQUIVALENT_SKIPPING_SECURE);
1625 // If the cookie is equivalent to the new cookie and wouldn't have been
1626 // skipped for being HTTP-only, record that it is a skipped secure cookie
1627 // that would have been deleted otherwise.
1628 if (ecc.IsEquivalent(*cc)) {
jwwa9a0d482015-12-16 18:19:411629 found_equivalent_cookie = true;
jww31e32632015-12-16 23:38:341630
1631 if (!skip_httponly || !cc->IsHttpOnly()) {
1632 histogram_cookie_delete_equivalent_->Add(
1633 COOKIE_DELETE_EQUIVALENT_WOULD_HAVE_DELETED);
1634 }
1635 }
jww601411a2015-11-20 19:46:571636 } else if (ecc.IsEquivalent(*cc)) {
[email protected]f48b9432011-01-11 07:25:401637 // We should never have more than one equivalent cookie, since they should
jww601411a2015-11-20 19:46:571638 // overwrite each other, unless secure cookies require secure scheme is
1639 // being enforced. In that case, cookies with different paths might exist
1640 // and be considered equivalent.
mkwstbe84af312015-02-20 08:52:451641 CHECK(!found_equivalent_cookie)
1642 << "Duplicate equivalent cookies found, cookie store is corrupted.";
[email protected]f48b9432011-01-11 07:25:401643 if (skip_httponly && cc->IsHttpOnly()) {
1644 skipped_httponly = true;
1645 } else {
jww31e32632015-12-16 23:38:341646 histogram_cookie_delete_equivalent_->Add(
1647 COOKIE_DELETE_EQUIVALENT_FOUND);
mkwstbe84af312015-02-20 08:52:451648 InternalDeleteCookie(curit, true, already_expired
1649 ? DELETE_COOKIE_EXPIRED_OVERWRITE
1650 : DELETE_COOKIE_OVERWRITE);
[email protected]f48b9432011-01-11 07:25:401651 }
1652 found_equivalent_cookie = true;
1653 }
1654 }
jww601411a2015-11-20 19:46:571655 return skipped_httponly || skipped_secure_cookie;
[email protected]f48b9432011-01-11 07:25:401656}
1657
[email protected]6210ce52013-09-20 03:33:141658CookieMonster::CookieMap::iterator CookieMonster::InternalInsertCookie(
1659 const std::string& key,
1660 CanonicalCookie* cc,
1661 bool sync_to_store) {
mmenkebe0910d2016-03-01 19:09:091662 DCHECK(thread_checker_.CalledOnValidThread());
1663
pkastinga9269aa42015-04-10 01:42:261664 // TODO(mkwst): Remove ScopedTracker below once crbug.com/456373 is fixed.
pkasting58e029b2015-02-21 05:17:281665 tracked_objects::ScopedTracker tracking_profile(
1666 FROM_HERE_WITH_EXPLICIT_FUNCTION(
1667 "456373 CookieMonster::InternalInsertCookie"));
[email protected]f48b9432011-01-11 07:25:401668
[email protected]90499482013-06-01 00:39:501669 if ((cc->IsPersistent() || persist_session_cookies_) && store_.get() &&
1670 sync_to_store)
[email protected]f48b9432011-01-11 07:25:401671 store_->AddCookie(*cc);
[email protected]6210ce52013-09-20 03:33:141672 CookieMap::iterator inserted =
1673 cookies_.insert(CookieMap::value_type(key, cc));
[email protected]8bb846f2011-03-23 12:08:181674 if (delegate_.get()) {
mkwstbe84af312015-02-20 08:52:451675 delegate_->OnCookieChanged(*cc, false,
1676 CookieMonsterDelegate::CHANGE_COOKIE_EXPLICIT);
[email protected]8bb846f2011-03-23 12:08:181677 }
mkwstc1aa4cc2015-04-03 19:57:451678
1679 // See InitializeHistograms() for details.
mkwst46549412016-02-01 10:05:371680 int32_t type_sample = cc->IsSameSite() ? 1 << COOKIE_TYPE_SAME_SITE : 0;
1681 type_sample |= cc->IsHttpOnly() ? 1 << COOKIE_TYPE_HTTPONLY : 0;
1682 type_sample |= cc->IsSecure() ? 1 << COOKIE_TYPE_SECURE : 0;
1683 histogram_cookie_type_->Add(type_sample);
estark7feb65c2b2015-08-21 23:38:201684
1685 // Histogram the type of scheme used on URLs that set cookies. This
1686 // intentionally includes cookies that are set or overwritten by
1687 // http:// URLs, but not cookies that are cleared by http:// URLs, to
1688 // understand if the former behavior can be deprecated for Secure
1689 // cookies.
1690 if (!cc->Source().is_empty()) {
1691 CookieSource cookie_source_sample;
1692 if (cc->Source().SchemeIsCryptographic()) {
1693 cookie_source_sample =
1694 cc->IsSecure() ? COOKIE_SOURCE_SECURE_COOKIE_CRYPTOGRAPHIC_SCHEME
1695 : COOKIE_SOURCE_NONSECURE_COOKIE_CRYPTOGRAPHIC_SCHEME;
1696 } else {
1697 cookie_source_sample =
1698 cc->IsSecure()
1699 ? COOKIE_SOURCE_SECURE_COOKIE_NONCRYPTOGRAPHIC_SCHEME
1700 : COOKIE_SOURCE_NONSECURE_COOKIE_NONCRYPTOGRAPHIC_SCHEME;
1701 }
1702 histogram_cookie_source_scheme_->Add(cookie_source_sample);
1703 }
mkwstc1aa4cc2015-04-03 19:57:451704
mmenkebe0910d2016-03-01 19:09:091705 RunCookieChangedCallbacks(*cc, false);
[email protected]6210ce52013-09-20 03:33:141706
1707 return inserted;
[email protected]f48b9432011-01-11 07:25:401708}
1709
[email protected]34602282010-02-03 22:14:151710bool CookieMonster::SetCookieWithCreationTimeAndOptions(
1711 const GURL& url,
1712 const std::string& cookie_line,
1713 const Time& creation_time_or_null,
1714 const CookieOptions& options) {
mmenkebe0910d2016-03-01 19:09:091715 DCHECK(thread_checker_.CalledOnValidThread());
initial.commit586acc5fe2008-07-26 22:42:521716
[email protected]4d3ce782010-10-29 18:31:281717 VLOG(kVlogSetCookies) << "SetCookie() line: " << cookie_line;
initial.commit586acc5fe2008-07-26 22:42:521718
[email protected]34602282010-02-03 22:14:151719 Time creation_time = creation_time_or_null;
1720 if (creation_time.is_null()) {
1721 creation_time = CurrentTime();
1722 last_time_seen_ = creation_time;
1723 }
1724
[email protected]abbd13b2012-11-15 17:54:201725 scoped_ptr<CanonicalCookie> cc(
1726 CanonicalCookie::Create(url, cookie_line, creation_time, options));
initial.commit586acc5fe2008-07-26 22:42:521727
1728 if (!cc.get()) {
[email protected]4d3ce782010-10-29 18:31:281729 VLOG(kVlogSetCookies) << "WARNING: Failed to allocate CanonicalCookie";
initial.commit586acc5fe2008-07-26 22:42:521730 return false;
1731 }
mmenkeea4cd402016-02-02 04:03:101732 return SetCanonicalCookie(std::move(cc), options);
[email protected]f325f1e12010-04-30 22:38:551733}
initial.commit586acc5fe2008-07-26 22:42:521734
mmenkeea4cd402016-02-02 04:03:101735bool CookieMonster::SetCanonicalCookie(scoped_ptr<CanonicalCookie> cc,
[email protected]f325f1e12010-04-30 22:38:551736 const CookieOptions& options) {
mmenkebe0910d2016-03-01 19:09:091737 DCHECK(thread_checker_.CalledOnValidThread());
1738
mmenkeea4cd402016-02-02 04:03:101739 Time creation_time = cc->CreationDate();
1740 const std::string key(GetKey(cc->Domain()));
1741 bool already_expired = cc->IsExpired(creation_time);
ellyjones399e35a22014-10-27 11:09:561742
mmenkeea4cd402016-02-02 04:03:101743 if (DeleteAnyEquivalentCookie(key, *cc, options.exclude_httponly(),
jww601411a2015-11-20 19:46:571744 already_expired,
1745 options.enforce_strict_secure())) {
1746 std::string error;
1747 if (options.enforce_strict_secure()) {
1748 error =
1749 "SetCookie() not clobbering httponly cookie or secure cookie for "
1750 "insecure scheme";
1751 } else {
1752 error = "SetCookie() not clobbering httponly cookie";
1753 }
1754
1755 VLOG(kVlogSetCookies) << error;
[email protected]3a96c742008-11-19 19:46:271756 return false;
1757 }
initial.commit586acc5fe2008-07-26 22:42:521758
mkwstbe84af312015-02-20 08:52:451759 VLOG(kVlogSetCookies) << "SetCookie() key: " << key
mmenkeea4cd402016-02-02 04:03:101760 << " cc: " << cc->DebugString();
initial.commit586acc5fe2008-07-26 22:42:521761
1762 // Realize that we might be setting an expired cookie, and the only point
1763 // was to delete the cookie which we've already done.
mmenke3c79a652016-02-12 14:39:201764 if (!already_expired) {
[email protected]374f58b2010-07-20 15:29:261765 // See InitializeHistograms() for details.
mmenkeea4cd402016-02-02 04:03:101766 if (cc->IsPersistent()) {
[email protected]8475bee2011-03-17 18:40:241767 histogram_expiration_duration_minutes_->Add(
mmenkeea4cd402016-02-02 04:03:101768 (cc->ExpiryDate() - creation_time).InMinutes());
[email protected]8475bee2011-03-17 18:40:241769 }
1770
mmenkeea4cd402016-02-02 04:03:101771 InternalInsertCookie(key, cc.release(), true);
[email protected]348dd662013-03-13 20:25:071772 } else {
1773 VLOG(kVlogSetCookies) << "SetCookie() not storing already expired cookie.";
[email protected]c4058fb2010-06-22 17:25:261774 }
initial.commit586acc5fe2008-07-26 22:42:521775
1776 // We assume that hopefully setting a cookie will be less common than
1777 // querying a cookie. Since setting a cookie can put us over our limits,
1778 // make sure that we garbage collect... We can also make the assumption that
1779 // if a cookie was set, in the common case it will be used soon after,
1780 // and we will purge the expired cookies in GetCookies().
jww82d99c12015-11-25 18:39:531781 GarbageCollect(creation_time, key, options.enforce_strict_secure());
initial.commit586acc5fe2008-07-26 22:42:521782
1783 return true;
1784}
1785
drogerd5d1278c2015-03-17 19:21:511786bool CookieMonster::SetCanonicalCookies(const CookieList& list) {
mmenkebe0910d2016-03-01 19:09:091787 DCHECK(thread_checker_.CalledOnValidThread());
drogerd5d1278c2015-03-17 19:21:511788
ttuttle859dc7a2015-04-23 19:42:291789 CookieOptions options;
drogerd5d1278c2015-03-17 19:21:511790 options.set_include_httponly();
1791
mmenkeea4cd402016-02-02 04:03:101792 for (const auto& cookie : list) {
1793 if (!SetCanonicalCookie(make_scoped_ptr(new CanonicalCookie(cookie)),
1794 options)) {
drogerd5d1278c2015-03-17 19:21:511795 return false;
mmenkeea4cd402016-02-02 04:03:101796 }
drogerd5d1278c2015-03-17 19:21:511797 }
1798
1799 return true;
1800}
1801
[email protected]7a964a72010-09-07 19:33:261802void CookieMonster::InternalUpdateCookieAccessTime(CanonicalCookie* cc,
1803 const Time& current) {
mmenkebe0910d2016-03-01 19:09:091804 DCHECK(thread_checker_.CalledOnValidThread());
[email protected]bb8905722010-05-21 17:29:041805
[email protected]77e0a462008-11-01 00:43:351806 // Based off the Mozilla code. When a cookie has been accessed recently,
1807 // don't bother updating its access time again. This reduces the number of
1808 // updates we do during pageload, which in turn reduces the chance our storage
1809 // backend will hit its batch thresholds and be forced to update.
[email protected]77e0a462008-11-01 00:43:351810 if ((current - cc->LastAccessDate()) < last_access_threshold_)
1811 return;
1812
1813 cc->SetLastAccessDate(current);
[email protected]90499482013-06-01 00:39:501814 if ((cc->IsPersistent() || persist_session_cookies_) && store_.get())
[email protected]77e0a462008-11-01 00:43:351815 store_->UpdateCookieAccessTime(*cc);
1816}
1817
[email protected]6210ce52013-09-20 03:33:141818// InternalDeleteCookies must not invalidate iterators other than the one being
1819// deleted.
initial.commit586acc5fe2008-07-26 22:42:521820void CookieMonster::InternalDeleteCookie(CookieMap::iterator it,
[email protected]c4058fb2010-06-22 17:25:261821 bool sync_to_store,
1822 DeletionCause deletion_cause) {
mmenkebe0910d2016-03-01 19:09:091823 DCHECK(thread_checker_.CalledOnValidThread());
[email protected]bb8905722010-05-21 17:29:041824
[email protected]8bb846f2011-03-23 12:08:181825 // Ideally, this would be asserted up where we define ChangeCauseMapping,
1826 // but DeletionCause's visibility (or lack thereof) forces us to make
1827 // this check here.
mostynb91e0da982015-01-20 19:17:271828 static_assert(arraysize(ChangeCauseMapping) == DELETE_COOKIE_LAST_ENTRY + 1,
1829 "ChangeCauseMapping size should match DeletionCause size");
[email protected]8bb846f2011-03-23 12:08:181830
[email protected]374f58b2010-07-20 15:29:261831 // See InitializeHistograms() for details.
[email protected]7a964a72010-09-07 19:33:261832 if (deletion_cause != DELETE_COOKIE_DONT_RECORD)
1833 histogram_cookie_deletion_cause_->Add(deletion_cause);
[email protected]c4058fb2010-06-22 17:25:261834
initial.commit586acc5fe2008-07-26 22:42:521835 CanonicalCookie* cc = it->second;
xiyuan8dbb89892015-04-13 17:04:301836 VLOG(kVlogSetCookies) << "InternalDeleteCookie()"
1837 << ", cause:" << deletion_cause
1838 << ", cc: " << cc->DebugString();
[email protected]7a964a72010-09-07 19:33:261839
[email protected]90499482013-06-01 00:39:501840 if ((cc->IsPersistent() || persist_session_cookies_) && store_.get() &&
1841 sync_to_store)
initial.commit586acc5fe2008-07-26 22:42:521842 store_->DeleteCookie(*cc);
[email protected]8bb846f2011-03-23 12:08:181843 if (delegate_.get()) {
1844 ChangeCausePair mapping = ChangeCauseMapping[deletion_cause];
1845
1846 if (mapping.notify)
1847 delegate_->OnCookieChanged(*cc, true, mapping.cause);
1848 }
mmenkebe0910d2016-03-01 19:09:091849 RunCookieChangedCallbacks(*cc, true);
initial.commit586acc5fe2008-07-26 22:42:521850 cookies_.erase(it);
1851 delete cc;
1852}
1853
[email protected]8807b322010-10-01 17:10:141854// Domain expiry behavior is unchanged by key/expiry scheme (the
[email protected]8ad5d462013-05-02 08:45:261855// meaning of the key is different, but that's not visible to this routine).
jww82d99c12015-11-25 18:39:531856size_t CookieMonster::GarbageCollect(const Time& current,
1857 const std::string& key,
1858 bool enforce_strict_secure) {
mmenkebe0910d2016-03-01 19:09:091859 DCHECK(thread_checker_.CalledOnValidThread());
[email protected]bb8905722010-05-21 17:29:041860
jww82d99c12015-11-25 18:39:531861 size_t num_deleted = 0;
mkwstbe84af312015-02-20 08:52:451862 Time safe_date(Time::Now() - TimeDelta::FromDays(kSafeFromGlobalPurgeDays));
initial.commit586acc5fe2008-07-26 22:42:521863
[email protected]8ad5d462013-05-02 08:45:261864 // Collect garbage for this key, minding cookie priorities.
[email protected]7a964a72010-09-07 19:33:261865 if (cookies_.count(key) > kDomainMaxCookies) {
[email protected]4d3ce782010-10-29 18:31:281866 VLOG(kVlogGarbageCollection) << "GarbageCollect() key: " << key;
[email protected]7a964a72010-09-07 19:33:261867
mkwst87734352016-03-03 17:36:231868 CookieItVector* cookie_its;
jww601411a2015-11-20 19:46:571869
mkwst87734352016-03-03 17:36:231870 CookieItVector non_expired_cookie_its;
1871 cookie_its = &non_expired_cookie_its;
jww82d99c12015-11-25 18:39:531872 num_deleted +=
mkwst87734352016-03-03 17:36:231873 GarbageCollectExpired(current, cookies_.equal_range(key), cookie_its);
jww82d99c12015-11-25 18:39:531874
mkwste079ac412016-03-11 09:04:061875 // TODO(mkwst): Soften this.
mkwst87734352016-03-03 17:36:231876 CookieItVector secure_cookie_its;
1877 if (enforce_strict_secure && cookie_its->size() > kDomainMaxCookies) {
1878 VLOG(kVlogGarbageCollection) << "Garbage collecting non-Secure cookies.";
1879 num_deleted +=
1880 GarbageCollectNonSecure(non_expired_cookie_its, &secure_cookie_its);
1881 cookie_its = &secure_cookie_its;
1882 }
jww82d99c12015-11-25 18:39:531883
mkwst87734352016-03-03 17:36:231884 if (cookie_its->size() > kDomainMaxCookies) {
[email protected]8ad5d462013-05-02 08:45:261885 VLOG(kVlogGarbageCollection) << "Deep Garbage Collect domain.";
1886 size_t purge_goal =
mkwst87734352016-03-03 17:36:231887 cookie_its->size() - (kDomainMaxCookies - kDomainPurgeCookies);
[email protected]8ad5d462013-05-02 08:45:261888 DCHECK(purge_goal > kDomainPurgeCookies);
1889
mkwste079ac412016-03-11 09:04:061890 // Sort the cookies by access date, from least-recent to most-recent.
1891 std::sort(cookie_its->begin(), cookie_its->end(), LRACookieSorter);
[email protected]8ad5d462013-05-02 08:45:261892
mkwste079ac412016-03-11 09:04:061893 // Remove all but the kDomainCookiesQuotaLow most-recently accessed
1894 // cookies with low-priority. Then, if cookies still need to be removed,
1895 // bump the quota and remove low- and medium-priority. Then, if cookies
1896 // _still_ need to be removed, bump the quota and remove cookies with
1897 // any priority.
1898 const size_t kQuotas[3] = {kDomainCookiesQuotaLow,
1899 kDomainCookiesQuotaMedium,
1900 kDomainCookiesQuotaHigh};
1901 size_t quota = 0;
1902 for (size_t i = 0; i < arraysize(kQuotas) && purge_goal > 0; i++) {
1903 quota += kQuotas[i];
mkwstaa07ee82016-03-11 15:32:141904 size_t just_deleted = PurgeLeastRecentMatches(
1905 cookie_its, static_cast<CookiePriority>(i), quota, purge_goal);
mkwste079ac412016-03-11 09:04:061906 DCHECK_LE(just_deleted, purge_goal);
1907 purge_goal -= just_deleted;
1908 num_deleted += just_deleted;
mkwst162d2712016-02-18 18:21:291909 }
mkwste079ac412016-03-11 09:04:061910
[email protected]8ad5d462013-05-02 08:45:261911 DCHECK_EQ(0U, purge_goal);
[email protected]8807b322010-10-01 17:10:141912 }
initial.commit586acc5fe2008-07-26 22:42:521913 }
1914
[email protected]8ad5d462013-05-02 08:45:261915 // Collect garbage for everything. With firefox style we want to preserve
1916 // cookies accessed in kSafeFromGlobalPurgeDays, otherwise evict.
mkwstbe84af312015-02-20 08:52:451917 if (cookies_.size() > kMaxCookies && earliest_access_time_ < safe_date) {
[email protected]4d3ce782010-10-29 18:31:281918 VLOG(kVlogGarbageCollection) << "GarbageCollect() everything";
[email protected]8ad5d462013-05-02 08:45:261919 CookieItVector cookie_its;
jww82d99c12015-11-25 18:39:531920
[email protected]7a964a72010-09-07 19:33:261921 num_deleted += GarbageCollectExpired(
1922 current, CookieMapItPair(cookies_.begin(), cookies_.end()),
1923 &cookie_its);
jww82d99c12015-11-25 18:39:531924
[email protected]8ad5d462013-05-02 08:45:261925 if (cookie_its.size() > kMaxCookies) {
1926 VLOG(kVlogGarbageCollection) << "Deep Garbage Collect everything.";
1927 size_t purge_goal = cookie_its.size() - (kMaxCookies - kPurgeCookies);
1928 DCHECK(purge_goal > kPurgeCookies);
jww82d99c12015-11-25 18:39:531929
1930 if (enforce_strict_secure) {
1931 CookieItVector secure_cookie_its;
1932 CookieItVector non_secure_cookie_its;
1933 SplitCookieVectorIntoSecureAndNonSecure(cookie_its, &secure_cookie_its,
1934 &non_secure_cookie_its);
1935 size_t non_secure_purge_goal =
1936 std::min<size_t>(purge_goal, non_secure_cookie_its.size() - 1);
1937
1938 size_t just_deleted = GarbageCollectLeastRecentlyAccessed(
1939 current, safe_date, non_secure_purge_goal, non_secure_cookie_its);
1940 num_deleted += just_deleted;
1941
1942 if (just_deleted < purge_goal) {
1943 size_t secure_purge_goal = std::min<size_t>(
1944 purge_goal - just_deleted, secure_cookie_its.size() - 1);
1945 num_deleted += GarbageCollectLeastRecentlyAccessed(
1946 current, safe_date, secure_purge_goal, secure_cookie_its);
1947 }
1948 } else {
1949 num_deleted += GarbageCollectLeastRecentlyAccessed(
1950 current, safe_date, purge_goal, cookie_its);
1951 }
[email protected]8807b322010-10-01 17:10:141952 }
[email protected]c890ed192008-10-30 23:45:531953 }
1954
1955 return num_deleted;
1956}
1957
mkwste079ac412016-03-11 09:04:061958size_t CookieMonster::PurgeLeastRecentMatches(CookieItVector* cookies,
1959 CookiePriority priority,
1960 size_t to_protect,
mkwstaa07ee82016-03-11 15:32:141961 size_t purge_goal) {
mkwste079ac412016-03-11 09:04:061962 DCHECK(thread_checker_.CalledOnValidThread());
1963
1964 // Find the first protected cookie by walking down from the end of the list
1965 // cookie list (most-recently accessed) until |to_protect| cookies that match
1966 // |priority| are found.
1967 size_t protection_boundary = cookies->size();
1968 while (to_protect > 0 && protection_boundary > 0) {
1969 protection_boundary--;
1970 if (cookies->at(protection_boundary)->second->Priority() <= priority)
1971 to_protect--;
1972 }
1973
1974 // Now, walk up from the beginning of the list (least-recently accessed) until
1975 // |purge_goal| cookies are removed, or the iterator hits
1976 // |protection_boundary|.
1977 size_t removed = 0;
1978 size_t current = 0;
1979 while (removed < purge_goal && current < protection_boundary) {
1980 if (cookies->at(current)->second->Priority() <= priority) {
mkwstaa07ee82016-03-11 15:32:141981 InternalDeleteCookie(cookies->at(current), true,
1982 DELETE_COOKIE_EVICTED_DOMAIN);
mkwste079ac412016-03-11 09:04:061983 cookies->erase(cookies->begin() + current);
1984 removed++;
1985
1986 // The call to 'erase' above shifts the contents of the vector, but
1987 // doesn't shift |protection_boundary|. Decrement that here to ensure that
1988 // the correct set of cookies is protected.
1989 protection_boundary--;
1990 } else {
1991 current++;
1992 }
1993 }
1994 return removed;
1995}
1996
jww82d99c12015-11-25 18:39:531997size_t CookieMonster::GarbageCollectExpired(const Time& current,
1998 const CookieMapItPair& itpair,
1999 CookieItVector* cookie_its) {
mmenkebe0910d2016-03-01 19:09:092000 DCHECK(thread_checker_.CalledOnValidThread());
[email protected]bb8905722010-05-21 17:29:042001
[email protected]c890ed192008-10-30 23:45:532002 int num_deleted = 0;
2003 for (CookieMap::iterator it = itpair.first, end = itpair.second; it != end;) {
2004 CookieMap::iterator curit = it;
2005 ++it;
2006
2007 if (curit->second->IsExpired(current)) {
[email protected]2f3f3592010-07-07 20:11:512008 InternalDeleteCookie(curit, true, DELETE_COOKIE_EXPIRED);
[email protected]c890ed192008-10-30 23:45:532009 ++num_deleted;
2010 } else if (cookie_its) {
2011 cookie_its->push_back(curit);
2012 }
initial.commit586acc5fe2008-07-26 22:42:522013 }
2014
2015 return num_deleted;
2016}
2017
jww82d99c12015-11-25 18:39:532018size_t CookieMonster::GarbageCollectNonSecure(
2019 const CookieItVector& valid_cookies,
2020 CookieItVector* cookie_its) {
mmenkebe0910d2016-03-01 19:09:092021 DCHECK(thread_checker_.CalledOnValidThread());
jww82d99c12015-11-25 18:39:532022
2023 size_t num_deleted = 0;
2024 for (const auto& curr_cookie_it : valid_cookies) {
2025 if (!curr_cookie_it->second->IsSecure()) {
2026 InternalDeleteCookie(curr_cookie_it, true, DELETE_COOKIE_NON_SECURE);
2027 ++num_deleted;
2028 } else if (cookie_its) {
2029 cookie_its->push_back(curr_cookie_it);
2030 }
2031 }
2032
2033 return num_deleted;
2034}
2035
2036size_t CookieMonster::GarbageCollectDeleteRange(
2037 const Time& current,
2038 DeletionCause cause,
2039 CookieItVector::iterator it_begin,
2040 CookieItVector::iterator it_end) {
mmenkebe0910d2016-03-01 19:09:092041 DCHECK(thread_checker_.CalledOnValidThread());
2042
[email protected]8ad5d462013-05-02 08:45:262043 for (CookieItVector::iterator it = it_begin; it != it_end; it++) {
2044 histogram_evicted_last_access_minutes_->Add(
2045 (current - (*it)->second->LastAccessDate()).InMinutes());
2046 InternalDeleteCookie((*it), true, cause);
[email protected]c10da4b02010-03-25 14:38:322047 }
[email protected]8ad5d462013-05-02 08:45:262048 return it_end - it_begin;
[email protected]c10da4b02010-03-25 14:38:322049}
2050
mmenke74bcbd52016-01-21 17:17:562051size_t CookieMonster::GarbageCollectLeastRecentlyAccessed(
2052 const base::Time& current,
2053 const base::Time& safe_date,
2054 size_t purge_goal,
2055 CookieItVector cookie_its) {
mmenkebe0910d2016-03-01 19:09:092056 DCHECK(thread_checker_.CalledOnValidThread());
2057
mmenke74bcbd52016-01-21 17:17:562058 // Sorts up to *and including* |cookie_its[purge_goal]|, so
2059 // |earliest_access_time| will be properly assigned even if
2060 // |global_purge_it| == |cookie_its.begin() + purge_goal|.
2061 SortLeastRecentlyAccessed(cookie_its.begin(), cookie_its.end(), purge_goal);
2062 // Find boundary to cookies older than safe_date.
2063 CookieItVector::iterator global_purge_it = LowerBoundAccessDate(
2064 cookie_its.begin(), cookie_its.begin() + purge_goal, safe_date);
2065 // Only delete the old cookies, and if strict secure is enabled, delete
2066 // non-secure ones first.
2067 size_t num_deleted =
2068 GarbageCollectDeleteRange(current, DELETE_COOKIE_EVICTED_GLOBAL,
2069 cookie_its.begin(), global_purge_it);
2070 // Set access day to the oldest cookie that wasn't deleted.
2071 earliest_access_time_ = (*global_purge_it)->second->LastAccessDate();
2072 return num_deleted;
2073}
2074
[email protected]ed32c212013-05-14 20:49:292075// A wrapper around registry_controlled_domains::GetDomainAndRegistry
[email protected]f48b9432011-01-11 07:25:402076// to make clear we're creating a key for our local map. Here and
2077// in FindCookiesForHostAndDomain() are the only two places where
2078// we need to conditionalize based on key type.
2079//
2080// Note that this key algorithm explicitly ignores the scheme. This is
2081// because when we're entering cookies into the map from the backing store,
2082// we in general won't have the scheme at that point.
2083// In practical terms, this means that file cookies will be stored
2084// in the map either by an empty string or by UNC name (and will be
2085// limited by kMaxCookiesPerHost), and extension cookies will be stored
2086// based on the single extension id, as the extension id won't have the
2087// form of a DNS host and hence GetKey() will return it unchanged.
2088//
2089// Arguably the right thing to do here is to make the key
2090// algorithm dependent on the scheme, and make sure that the scheme is
2091// available everywhere the key must be obtained (specfically at backing
2092// store load time). This would require either changing the backing store
2093// database schema to include the scheme (far more trouble than it's worth), or
2094// separating out file cookies into their own CookieMonster instance and
2095// thus restricting each scheme to a single cookie monster (which might
2096// be worth it, but is still too much trouble to solve what is currently a
2097// non-problem).
2098std::string CookieMonster::GetKey(const std::string& domain) const {
mmenkebe0910d2016-03-01 19:09:092099 DCHECK(thread_checker_.CalledOnValidThread());
2100
[email protected]f48b9432011-01-11 07:25:402101 std::string effective_domain(
[email protected]ed32c212013-05-14 20:49:292102 registry_controlled_domains::GetDomainAndRegistry(
[email protected]aabe1792014-01-30 21:37:462103 domain, registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES));
[email protected]f48b9432011-01-11 07:25:402104 if (effective_domain.empty())
2105 effective_domain = domain;
2106
2107 if (!effective_domain.empty() && effective_domain[0] == '.')
2108 return effective_domain.substr(1);
2109 return effective_domain;
2110}
2111
2112bool CookieMonster::HasCookieableScheme(const GURL& url) {
mmenkebe0910d2016-03-01 19:09:092113 DCHECK(thread_checker_.CalledOnValidThread());
[email protected]f48b9432011-01-11 07:25:402114
2115 // Make sure the request is on a cookie-able url scheme.
2116 for (size_t i = 0; i < cookieable_schemes_.size(); ++i) {
2117 // We matched a scheme.
2118 if (url.SchemeIs(cookieable_schemes_[i].c_str())) {
2119 // We've matched a supported scheme.
initial.commit586acc5fe2008-07-26 22:42:522120 return true;
2121 }
2122 }
[email protected]f48b9432011-01-11 07:25:402123
2124 // The scheme didn't match any in our whitelist.
mkwstbe84af312015-02-20 08:52:452125 VLOG(kVlogPerCookieMonster)
2126 << "WARNING: Unsupported cookie scheme: " << url.scheme();
initial.commit586acc5fe2008-07-26 22:42:522127 return false;
2128}
2129
[email protected]c4058fb2010-06-22 17:25:262130// Test to see if stats should be recorded, and record them if so.
2131// The goal here is to get sampling for the average browser-hour of
2132// activity. We won't take samples when the web isn't being surfed,
2133// and when the web is being surfed, we'll take samples about every
2134// kRecordStatisticsIntervalSeconds.
2135// last_statistic_record_time_ is initialized to Now() rather than null
2136// in the constructor so that we won't take statistics right after
2137// startup, to avoid bias from browsers that are started but not used.
2138void CookieMonster::RecordPeriodicStats(const base::Time& current_time) {
mmenkebe0910d2016-03-01 19:09:092139 DCHECK(thread_checker_.CalledOnValidThread());
2140
[email protected]c4058fb2010-06-22 17:25:262141 const base::TimeDelta kRecordStatisticsIntervalTime(
2142 base::TimeDelta::FromSeconds(kRecordStatisticsIntervalSeconds));
2143
[email protected]7a964a72010-09-07 19:33:262144 // If we've taken statistics recently, return.
2145 if (current_time - last_statistic_record_time_ <=
[email protected]c4058fb2010-06-22 17:25:262146 kRecordStatisticsIntervalTime) {
[email protected]7a964a72010-09-07 19:33:262147 return;
[email protected]c4058fb2010-06-22 17:25:262148 }
[email protected]7a964a72010-09-07 19:33:262149
2150 // See InitializeHistograms() for details.
2151 histogram_count_->Add(cookies_.size());
2152
2153 // More detailed statistics on cookie counts at different granularities.
[email protected]7a964a72010-09-07 19:33:262154 last_statistic_record_time_ = current_time;
[email protected]c4058fb2010-06-22 17:25:262155}
2156
[email protected]f48b9432011-01-11 07:25:402157// Initialize all histogram counter variables used in this class.
2158//
2159// Normal histogram usage involves using the macros defined in
2160// histogram.h, which automatically takes care of declaring these
2161// variables (as statics), initializing them, and accumulating into
2162// them, all from a single entry point. Unfortunately, that solution
2163// doesn't work for the CookieMonster, as it's vulnerable to races between
2164// separate threads executing the same functions and hence initializing the
2165// same static variables. There isn't a race danger in the histogram
2166// accumulation calls; they are written to be resilient to simultaneous
2167// calls from multiple threads.
2168//
2169// The solution taken here is to have per-CookieMonster instance
2170// variables that are constructed during CookieMonster construction.
2171// Note that these variables refer to the same underlying histogram,
2172// so we still race (but safely) with other CookieMonster instances
2173// for accumulation.
2174//
2175// To do this we've expanded out the individual histogram macros calls,
2176// with declarations of the variables in the class decl, initialization here
2177// (done from the class constructor) and direct calls to the accumulation
2178// methods where needed. The specific histogram macro calls on which the
2179// initialization is based are included in comments below.
2180void CookieMonster::InitializeHistograms() {
mmenkebe0910d2016-03-01 19:09:092181 DCHECK(thread_checker_.CalledOnValidThread());
2182
[email protected]f48b9432011-01-11 07:25:402183 // From UMA_HISTOGRAM_CUSTOM_COUNTS
2184 histogram_expiration_duration_minutes_ = base::Histogram::FactoryGet(
mkwstbe84af312015-02-20 08:52:452185 "Cookie.ExpirationDurationMinutes", 1, kMinutesInTenYears, 50,
[email protected]f48b9432011-01-11 07:25:402186 base::Histogram::kUmaTargetedHistogramFlag);
[email protected]f48b9432011-01-11 07:25:402187 histogram_evicted_last_access_minutes_ = base::Histogram::FactoryGet(
mkwstbe84af312015-02-20 08:52:452188 "Cookie.EvictedLastAccessMinutes", 1, kMinutesInTenYears, 50,
[email protected]f48b9432011-01-11 07:25:402189 base::Histogram::kUmaTargetedHistogramFlag);
2190 histogram_count_ = base::Histogram::FactoryGet(
mkwstbe84af312015-02-20 08:52:452191 "Cookie.Count", 1, 4000, 50, base::Histogram::kUmaTargetedHistogramFlag);
[email protected]f48b9432011-01-11 07:25:402192
2193 // From UMA_HISTOGRAM_ENUMERATION
2194 histogram_cookie_deletion_cause_ = base::LinearHistogram::FactoryGet(
mkwstbe84af312015-02-20 08:52:452195 "Cookie.DeletionCause", 1, DELETE_COOKIE_LAST_ENTRY - 1,
2196 DELETE_COOKIE_LAST_ENTRY, base::Histogram::kUmaTargetedHistogramFlag);
mkwstc1aa4cc2015-04-03 19:57:452197 histogram_cookie_type_ = base::LinearHistogram::FactoryGet(
mkwst87378d92015-04-10 21:22:112198 "Cookie.Type", 1, (1 << COOKIE_TYPE_LAST_ENTRY) - 1,
2199 1 << COOKIE_TYPE_LAST_ENTRY, base::Histogram::kUmaTargetedHistogramFlag);
estark7feb65c2b2015-08-21 23:38:202200 histogram_cookie_source_scheme_ = base::LinearHistogram::FactoryGet(
2201 "Cookie.CookieSourceScheme", 1, COOKIE_SOURCE_LAST_ENTRY - 1,
2202 COOKIE_SOURCE_LAST_ENTRY, base::Histogram::kUmaTargetedHistogramFlag);
jww31e32632015-12-16 23:38:342203 histogram_cookie_delete_equivalent_ = base::LinearHistogram::FactoryGet(
2204 "Cookie.CookieDeleteEquivalent", 1,
2205 COOKIE_DELETE_EQUIVALENT_LAST_ENTRY - 1,
2206 COOKIE_DELETE_EQUIVALENT_LAST_ENTRY,
2207 base::Histogram::kUmaTargetedHistogramFlag);
[email protected]f48b9432011-01-11 07:25:402208
2209 // From UMA_HISTOGRAM_{CUSTOM_,}TIMES
[email protected]c7593fb22011-11-14 23:54:272210 histogram_time_blocked_on_load_ = base::Histogram::FactoryTimeGet(
mkwstbe84af312015-02-20 08:52:452211 "Cookie.TimeBlockedOnLoad", base::TimeDelta::FromMilliseconds(1),
2212 base::TimeDelta::FromMinutes(1), 50,
2213 base::Histogram::kUmaTargetedHistogramFlag);
[email protected]f48b9432011-01-11 07:25:402214}
2215
[email protected]f48b9432011-01-11 07:25:402216// The system resolution is not high enough, so we can have multiple
2217// set cookies that result in the same system time. When this happens, we
2218// increment by one Time unit. Let's hope computers don't get too fast.
2219Time CookieMonster::CurrentTime() {
mkwstbe84af312015-02-20 08:52:452220 return std::max(Time::Now(), Time::FromInternalValue(
2221 last_time_seen_.ToInternalValue() + 1));
[email protected]f48b9432011-01-11 07:25:402222}
2223
mmenke74bcbd52016-01-21 17:17:562224void CookieMonster::DoCookieTask(
2225 const scoped_refptr<CookieMonsterTask>& task_item) {
mmenkebe0910d2016-03-01 19:09:092226 DCHECK(thread_checker_.CalledOnValidThread());
2227
2228 MarkCookieStoreAsInitialized();
2229 FetchAllCookiesIfNecessary();
mmenkef49fca0e2016-03-08 12:46:242230 seen_global_task_ = true;
mmenkebe0910d2016-03-01 19:09:092231
2232 if (!finished_fetching_all_cookies_ && store_.get()) {
mmenkef49fca0e2016-03-08 12:46:242233 tasks_pending_.push_back(task_item);
mmenkebe0910d2016-03-01 19:09:092234 return;
mmenke74bcbd52016-01-21 17:17:562235 }
2236
2237 task_item->Run();
2238}
2239
2240void CookieMonster::DoCookieTaskForURL(
2241 const scoped_refptr<CookieMonsterTask>& task_item,
2242 const GURL& url) {
mmenkebe0910d2016-03-01 19:09:092243 MarkCookieStoreAsInitialized();
2244 if (ShouldFetchAllCookiesWhenFetchingAnyCookie())
2245 FetchAllCookiesIfNecessary();
2246
2247 // If cookies for the requested domain key (eTLD+1) have been loaded from DB
2248 // then run the task, otherwise load from DB.
2249 if (!finished_fetching_all_cookies_ && store_.get()) {
mmenkef49fca0e2016-03-08 12:46:242250 // If a global task has been previously seen, queue the task as a global
2251 // task. Note that the CookieMonster may be in the middle of executing
2252 // the global queue, |tasks_pending_| may be empty, which is why another
2253 // bool is needed.
2254 if (seen_global_task_) {
2255 tasks_pending_.push_back(task_item);
2256 return;
2257 }
2258
mmenkebe0910d2016-03-01 19:09:092259 // Checks if the domain key has been loaded.
2260 std::string key(cookie_util::GetEffectiveDomain(url.scheme(), url.host()));
2261 if (keys_loaded_.find(key) == keys_loaded_.end()) {
2262 std::map<std::string,
2263 std::deque<scoped_refptr<CookieMonsterTask>>>::iterator it =
2264 tasks_pending_for_key_.find(key);
2265 if (it == tasks_pending_for_key_.end()) {
2266 store_->LoadCookiesForKey(
2267 key, base::Bind(&CookieMonster::OnKeyLoaded,
2268 weak_ptr_factory_.GetWeakPtr(), key));
2269 it = tasks_pending_for_key_
2270 .insert(std::make_pair(
2271 key, std::deque<scoped_refptr<CookieMonsterTask>>()))
2272 .first;
mmenke74bcbd52016-01-21 17:17:562273 }
mmenkebe0910d2016-03-01 19:09:092274 it->second.push_back(task_item);
2275 return;
mmenke74bcbd52016-01-21 17:17:562276 }
2277 }
mmenkebe0910d2016-03-01 19:09:092278
mmenke74bcbd52016-01-21 17:17:562279 task_item->Run();
2280}
2281
drogerd5d1278c2015-03-17 19:21:512282void CookieMonster::ComputeCookieDiff(CookieList* old_cookies,
2283 CookieList* new_cookies,
2284 CookieList* cookies_to_add,
2285 CookieList* cookies_to_delete) {
mmenkebe0910d2016-03-01 19:09:092286 DCHECK(thread_checker_.CalledOnValidThread());
2287
drogerd5d1278c2015-03-17 19:21:512288 DCHECK(old_cookies);
2289 DCHECK(new_cookies);
2290 DCHECK(cookies_to_add);
2291 DCHECK(cookies_to_delete);
2292 DCHECK(cookies_to_add->empty());
2293 DCHECK(cookies_to_delete->empty());
2294
2295 // Sort both lists.
2296 // A set ordered by FullDiffCookieSorter is also ordered by
2297 // PartialDiffCookieSorter.
2298 std::sort(old_cookies->begin(), old_cookies->end(), FullDiffCookieSorter);
2299 std::sort(new_cookies->begin(), new_cookies->end(), FullDiffCookieSorter);
2300
2301 // Select any old cookie for deletion if no new cookie has the same name,
2302 // domain, and path.
2303 std::set_difference(
2304 old_cookies->begin(), old_cookies->end(), new_cookies->begin(),
2305 new_cookies->end(),
2306 std::inserter(*cookies_to_delete, cookies_to_delete->begin()),
2307 PartialDiffCookieSorter);
2308
2309 // Select any new cookie for addition (or update) if no old cookie is exactly
2310 // equivalent.
2311 std::set_difference(new_cookies->begin(), new_cookies->end(),
2312 old_cookies->begin(), old_cookies->end(),
2313 std::inserter(*cookies_to_add, cookies_to_add->begin()),
2314 FullDiffCookieSorter);
2315}
2316
mmenkebe0910d2016-03-01 19:09:092317void CookieMonster::RunCallback(const base::Closure& callback) {
2318 DCHECK(thread_checker_.CalledOnValidThread());
2319 callback.Run();
2320}
2321
2322void CookieMonster::RunCookieChangedCallbacks(const CanonicalCookie& cookie,
2323 bool removed) {
2324 DCHECK(thread_checker_.CalledOnValidThread());
2325
ellyjones399e35a22014-10-27 11:09:562326 CookieOptions opts;
2327 opts.set_include_httponly();
mkwst46549412016-02-01 10:05:372328 opts.set_include_same_site();
mmenkebe0910d2016-03-01 19:09:092329 // Note that the callbacks in hook_map_ are wrapped with RunAsync(), so they
ellyjones399e35a22014-10-27 11:09:562330 // are guaranteed to not take long - they just post a RunAsync task back to
mmenkebe0910d2016-03-01 19:09:092331 // the appropriate thread's message loop and return.
2332 // TODO(mmenke): Consider running these synchronously?
ellyjones399e35a22014-10-27 11:09:562333 for (CookieChangedHookMap::iterator it = hook_map_.begin();
2334 it != hook_map_.end(); ++it) {
2335 std::pair<GURL, std::string> key = it->first;
2336 if (cookie.IncludeForRequestURL(key.first, opts) &&
2337 cookie.Name() == key.second) {
msarda0aad8f02014-10-30 09:22:392338 it->second->Notify(cookie, removed);
ellyjones399e35a22014-10-27 11:09:562339 }
2340 }
2341}
2342
[email protected]63725312012-07-19 08:24:162343} // namespace net