blob: 0dd52ef802d0568bf466d82dc39f626a7296e267 [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]8562034e2011-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]8562034e2011-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]8562034e2011-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]8562034e2011-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]8562034e2011-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
mkwstbe84af312015-02-20 08:52:45114const size_t CookieMonster::kDomainCookiesQuotaLow = 30;
[email protected]8ad5d462013-05-02 08:45:26115const size_t CookieMonster::kDomainCookiesQuotaMedium = 50;
mkwstbe84af312015-02-20 08:52:45116const 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) {
165 // Cookies accessed less recently should be deleted first.
166 if (it1->second->LastAccessDate() != it2->second->LastAccessDate())
167 return it1->second->LastAccessDate() < it2->second->LastAccessDate();
initial.commit586acc5fe2008-07-26 22:42:52168
[email protected]f48b9432011-01-11 07:25:40169 // In rare cases we might have two cookies with identical last access times.
170 // To preserve the stability of the sort, in these cases prefer to delete
171 // older cookies over newer ones. CreationDate() is guaranteed to be unique.
172 return it1->second->CreationDate() < it2->second->CreationDate();
[email protected]297a4ed02010-02-12 08:12:52173}
174
drogerd5d1278c2015-03-17 19:21:51175// Compare cookies using name, domain and path, so that "equivalent" cookies
176// (per RFC 2965) are equal to each other.
ttuttle859dc7a2015-04-23 19:42:29177bool PartialDiffCookieSorter(const CanonicalCookie& a,
178 const CanonicalCookie& b) {
drogerd5d1278c2015-03-17 19:21:51179 return a.PartialCompare(b);
180}
181
182// This is a stricter ordering than PartialDiffCookieOrdering, where all fields
183// are used.
ttuttle859dc7a2015-04-23 19:42:29184bool FullDiffCookieSorter(const CanonicalCookie& a, const CanonicalCookie& b) {
drogerd5d1278c2015-03-17 19:21:51185 return a.FullCompare(b);
186}
187
[email protected]297a4ed02010-02-12 08:12:52188// Our strategy to find duplicates is:
189// (1) Build a map from (cookiename, cookiepath) to
190// {list of cookies with this signature, sorted by creation time}.
191// (2) For each list with more than 1 entry, keep the cookie having the
192// most recent creation time, and delete the others.
[email protected]f48b9432011-01-11 07:25:40193//
[email protected]1655ba342010-07-14 18:17:42194// Two cookies are considered equivalent if they have the same domain,
195// name, and path.
196struct CookieSignature {
197 public:
[email protected]dedec0b2013-02-28 04:50:10198 CookieSignature(const std::string& name,
199 const std::string& domain,
[email protected]1655ba342010-07-14 18:17:42200 const std::string& path)
mkwstbe84af312015-02-20 08:52:45201 : name(name), domain(domain), path(path) {}
[email protected]1655ba342010-07-14 18:17:42202
203 // To be a key for a map this class needs to be assignable, copyable,
204 // and have an operator<. The default assignment operator
205 // and copy constructor are exactly what we want.
206
207 bool operator<(const CookieSignature& cs) const {
208 // Name compare dominates, then domain, then path.
209 int diff = name.compare(cs.name);
210 if (diff != 0)
211 return diff < 0;
212
213 diff = domain.compare(cs.domain);
214 if (diff != 0)
215 return diff < 0;
216
217 return path.compare(cs.path) < 0;
218 }
219
220 std::string name;
221 std::string domain;
222 std::string path;
223};
[email protected]f48b9432011-01-11 07:25:40224
[email protected]8ad5d462013-05-02 08:45:26225// For a CookieItVector iterator range [|it_begin|, |it_end|),
226// sorts the first |num_sort| + 1 elements by LastAccessDate().
227// The + 1 element exists so for any interval of length <= |num_sort| starting
228// from |cookies_its_begin|, a LastAccessDate() bound can be found.
mkwstbe84af312015-02-20 08:52:45229void SortLeastRecentlyAccessed(CookieMonster::CookieItVector::iterator it_begin,
230 CookieMonster::CookieItVector::iterator it_end,
231 size_t num_sort) {
[email protected]8ad5d462013-05-02 08:45:26232 DCHECK_LT(static_cast<int>(num_sort), it_end - it_begin);
233 std::partial_sort(it_begin, it_begin + num_sort + 1, it_end, LRACookieSorter);
234}
[email protected]f48b9432011-01-11 07:25:40235
jww82d99c12015-11-25 18:39:53236// Given a single cookie vector |cookie_its|, pushs all of the secure cookies in
237// |cookie_its| into |secure_cookie_its| and all of the non-secure cookies into
238// |non_secure_cookie_its|. Both |secure_cookie_its| and |non_secure_cookie_its|
239// must be non-NULL.
240void SplitCookieVectorIntoSecureAndNonSecure(
241 const CookieMonster::CookieItVector& cookie_its,
242 CookieMonster::CookieItVector* secure_cookie_its,
243 CookieMonster::CookieItVector* non_secure_cookie_its) {
244 DCHECK(secure_cookie_its && non_secure_cookie_its);
245 for (const auto& curit : cookie_its) {
246 if (curit->second->IsSecure())
247 secure_cookie_its->push_back(curit);
248 else
249 non_secure_cookie_its->push_back(curit);
250 }
251}
252
[email protected]8ad5d462013-05-02 08:45:26253// Predicate to support PartitionCookieByPriority().
254struct CookiePriorityEqualsTo
255 : std::unary_function<const CookieMonster::CookieMap::iterator, bool> {
[email protected]5edff3c52014-06-23 20:27:48256 explicit CookiePriorityEqualsTo(CookiePriority priority)
mkwstbe84af312015-02-20 08:52:45257 : priority_(priority) {}
[email protected]8ad5d462013-05-02 08:45:26258
259 bool operator()(const CookieMonster::CookieMap::iterator it) const {
260 return it->second->Priority() == priority_;
[email protected]f48b9432011-01-11 07:25:40261 }
[email protected]8ad5d462013-05-02 08:45:26262
263 const CookiePriority priority_;
264};
265
266// For a CookieItVector iterator range [|it_begin|, |it_end|),
267// moves all cookies with a given |priority| to the beginning of the list.
268// Returns: An iterator in [it_begin, it_end) to the first element with
269// priority != |priority|, or |it_end| if all have priority == |priority|.
270CookieMonster::CookieItVector::iterator PartitionCookieByPriority(
271 CookieMonster::CookieItVector::iterator it_begin,
272 CookieMonster::CookieItVector::iterator it_end,
273 CookiePriority priority) {
274 return std::partition(it_begin, it_end, CookiePriorityEqualsTo(priority));
275}
276
mkwstbe84af312015-02-20 08:52:45277bool LowerBoundAccessDateComparator(const CookieMonster::CookieMap::iterator it,
278 const Time& access_date) {
[email protected]8ad5d462013-05-02 08:45:26279 return it->second->LastAccessDate() < access_date;
280}
281
282// For a CookieItVector iterator range [|it_begin|, |it_end|)
283// from a CookieItVector sorted by LastAccessDate(), returns the
284// first iterator with access date >= |access_date|, or cookie_its_end if this
285// holds for all.
286CookieMonster::CookieItVector::iterator LowerBoundAccessDate(
287 const CookieMonster::CookieItVector::iterator its_begin,
288 const CookieMonster::CookieItVector::iterator its_end,
289 const Time& access_date) {
290 return std::lower_bound(its_begin, its_end, access_date,
291 LowerBoundAccessDateComparator);
[email protected]7a964a72010-09-07 19:33:26292}
293
[email protected]7c4b66b2014-01-04 12:28:13294// Mapping between DeletionCause and CookieMonsterDelegate::ChangeCause; the
295// mapping also provides a boolean that specifies whether or not an
296// OnCookieChanged notification ought to be generated.
[email protected]8bb846f2011-03-23 12:08:18297typedef struct ChangeCausePair_struct {
[email protected]7c4b66b2014-01-04 12:28:13298 CookieMonsterDelegate::ChangeCause cause;
[email protected]8bb846f2011-03-23 12:08:18299 bool notify;
300} ChangeCausePair;
301ChangeCausePair ChangeCauseMapping[] = {
mkwstbe84af312015-02-20 08:52:45302 // DELETE_COOKIE_EXPLICIT
303 {CookieMonsterDelegate::CHANGE_COOKIE_EXPLICIT, true},
304 // DELETE_COOKIE_OVERWRITE
305 {CookieMonsterDelegate::CHANGE_COOKIE_OVERWRITE, true},
306 // DELETE_COOKIE_EXPIRED
307 {CookieMonsterDelegate::CHANGE_COOKIE_EXPIRED, true},
308 // DELETE_COOKIE_EVICTED
309 {CookieMonsterDelegate::CHANGE_COOKIE_EVICTED, true},
310 // DELETE_COOKIE_DUPLICATE_IN_BACKING_STORE
311 {CookieMonsterDelegate::CHANGE_COOKIE_EXPLICIT, false},
312 // DELETE_COOKIE_DONT_RECORD
313 {CookieMonsterDelegate::CHANGE_COOKIE_EXPLICIT, false},
314 // DELETE_COOKIE_EVICTED_DOMAIN
315 {CookieMonsterDelegate::CHANGE_COOKIE_EVICTED, true},
316 // DELETE_COOKIE_EVICTED_GLOBAL
317 {CookieMonsterDelegate::CHANGE_COOKIE_EVICTED, true},
318 // DELETE_COOKIE_EVICTED_DOMAIN_PRE_SAFE
319 {CookieMonsterDelegate::CHANGE_COOKIE_EVICTED, true},
320 // DELETE_COOKIE_EVICTED_DOMAIN_POST_SAFE
321 {CookieMonsterDelegate::CHANGE_COOKIE_EVICTED, true},
322 // DELETE_COOKIE_EXPIRED_OVERWRITE
323 {CookieMonsterDelegate::CHANGE_COOKIE_EXPIRED_OVERWRITE, true},
324 // DELETE_COOKIE_CONTROL_CHAR
325 {CookieMonsterDelegate::CHANGE_COOKIE_EVICTED, true},
jww82d99c12015-11-25 18:39:53326 // DELETE_COOKIE_NON_SECURE
327 {CookieMonsterDelegate::CHANGE_COOKIE_EVICTED, true},
mkwstbe84af312015-02-20 08:52:45328 // DELETE_COOKIE_LAST_ENTRY
329 {CookieMonsterDelegate::CHANGE_COOKIE_EXPLICIT, false}};
[email protected]8bb846f2011-03-23 12:08:18330
[email protected]34a160d2011-05-12 22:12:49331std::string BuildCookieLine(const CanonicalCookieVector& cookies) {
332 std::string cookie_line;
333 for (CanonicalCookieVector::const_iterator it = cookies.begin();
334 it != cookies.end(); ++it) {
335 if (it != cookies.begin())
336 cookie_line += "; ";
337 // In Mozilla if you set a cookie like AAAA, it will have an empty token
338 // and a value of AAAA. When it sends the cookie back, it will send AAAA,
339 // so we need to avoid sending =AAAA for a blank token value.
340 if (!(*it)->Name().empty())
341 cookie_line += (*it)->Name() + "=";
342 cookie_line += (*it)->Value();
343 }
344 return cookie_line;
345}
346
ellyjones399e35a22014-10-27 11:09:56347void RunAsync(scoped_refptr<base::TaskRunner> proxy,
msarda0aad8f02014-10-30 09:22:39348 const CookieStore::CookieChangedCallback& callback,
349 const CanonicalCookie& cookie,
350 bool removed) {
351 proxy->PostTask(FROM_HERE, base::Bind(callback, cookie, removed));
ellyjones399e35a22014-10-27 11:09:56352}
353
[email protected]f48b9432011-01-11 07:25:40354} // namespace
355
[email protected]7c4b66b2014-01-04 12:28:13356CookieMonster::CookieMonster(PersistentCookieStore* store,
357 CookieMonsterDelegate* delegate)
mmenke74bcbd52016-01-21 17:17:56358 : CookieMonster(store, delegate, kDefaultAccessUpdateThresholdSeconds) {
[email protected]f48b9432011-01-11 07:25:40359 InitializeHistograms();
360 SetDefaultCookieableSchemes();
[email protected]2d0f89a2010-12-06 12:02:23361}
362
[email protected]f48b9432011-01-11 07:25:40363CookieMonster::CookieMonster(PersistentCookieStore* store,
[email protected]7c4b66b2014-01-04 12:28:13364 CookieMonsterDelegate* delegate,
[email protected]f48b9432011-01-11 07:25:40365 int last_access_threshold_milliseconds)
366 : initialized_(false),
erikchen1dd72a72015-05-06 20:45:05367 started_fetching_all_cookies_(false),
368 finished_fetching_all_cookies_(false),
369 fetch_strategy_(kUnknownFetch),
[email protected]f48b9432011-01-11 07:25:40370 store_(store),
371 last_access_threshold_(base::TimeDelta::FromMilliseconds(
372 last_access_threshold_milliseconds)),
373 delegate_(delegate),
[email protected]82388662011-03-10 21:04:06374 last_statistic_record_time_(base::Time::Now()),
[email protected]93c53a32011-12-05 10:40:35375 keep_expired_cookies_(false),
[email protected]8976e292013-11-02 13:38:57376 persist_session_cookies_(false) {
[email protected]f48b9432011-01-11 07:25:40377 InitializeHistograms();
378 SetDefaultCookieableSchemes();
initial.commit586acc5fe2008-07-26 22:42:52379}
380
mmenke74bcbd52016-01-21 17:17:56381bool CookieMonster::ImportCookies(const CookieList& list) {
382 base::AutoLock autolock(lock_);
383 MarkCookieStoreAsInitialized();
384 if (ShouldFetchAllCookiesWhenFetchingAnyCookie())
385 FetchAllCookiesIfNecessary();
386 for (CookieList::const_iterator iter = list.begin(); iter != list.end();
387 ++iter) {
388 scoped_ptr<CanonicalCookie> cookie(new CanonicalCookie(*iter));
389 CookieOptions options;
390 options.set_include_httponly();
391 options.set_include_first_party_only_cookies();
392 if (!SetCanonicalCookie(&cookie, cookie->CreationDate(), options))
393 return false;
394 }
395 return true;
396}
397
[email protected]218aa6a12011-09-13 17:38:38398// Task classes for queueing the coming request.
399
400class CookieMonster::CookieMonsterTask
401 : public base::RefCountedThreadSafe<CookieMonsterTask> {
402 public:
403 // Runs the task and invokes the client callback on the thread that
404 // originally constructed the task.
405 virtual void Run() = 0;
406
407 protected:
408 explicit CookieMonsterTask(CookieMonster* cookie_monster);
409 virtual ~CookieMonsterTask();
410
411 // Invokes the callback immediately, if the current thread is the one
412 // that originated the task, or queues the callback for execution on the
413 // appropriate thread. Maintains a reference to this CookieMonsterTask
414 // instance until the callback completes.
415 void InvokeCallback(base::Closure callback);
416
mkwstbe84af312015-02-20 08:52:45417 CookieMonster* cookie_monster() { return cookie_monster_; }
[email protected]218aa6a12011-09-13 17:38:38418
[email protected]a9813302012-04-28 09:29:28419 private:
[email protected]218aa6a12011-09-13 17:38:38420 friend class base::RefCountedThreadSafe<CookieMonsterTask>;
421
[email protected]218aa6a12011-09-13 17:38:38422 CookieMonster* cookie_monster_;
anujk.sharmaafc45172015-05-15 00:50:34423 scoped_refptr<base::SingleThreadTaskRunner> thread_;
[email protected]218aa6a12011-09-13 17:38:38424
425 DISALLOW_COPY_AND_ASSIGN(CookieMonsterTask);
426};
427
428CookieMonster::CookieMonsterTask::CookieMonsterTask(
429 CookieMonster* cookie_monster)
430 : cookie_monster_(cookie_monster),
anujk.sharmaafc45172015-05-15 00:50:34431 thread_(base::ThreadTaskRunnerHandle::Get()) {
[email protected]a9813302012-04-28 09:29:28432}
[email protected]218aa6a12011-09-13 17:38:38433
mkwstbe84af312015-02-20 08:52:45434CookieMonster::CookieMonsterTask::~CookieMonsterTask() {
435}
[email protected]218aa6a12011-09-13 17:38:38436
437// Unfortunately, one cannot re-bind a Callback with parameters into a closure.
438// Therefore, the closure passed to InvokeCallback is a clumsy binding of
439// Callback::Run on a wrapped Callback instance. Since Callback is not
440// reference counted, we bind to an instance that is a member of the
441// CookieMonsterTask subclass. Then, we cannot simply post the callback to a
442// message loop because the underlying instance may be destroyed (along with the
443// CookieMonsterTask instance) in the interim. Therefore, we post a callback
444// bound to the CookieMonsterTask, which *is* reference counted (thus preventing
445// destruction of the original callback), and which invokes the closure (which
446// invokes the original callback with the returned data).
447void CookieMonster::CookieMonsterTask::InvokeCallback(base::Closure callback) {
448 if (thread_->BelongsToCurrentThread()) {
449 callback.Run();
450 } else {
mkwstbe84af312015-02-20 08:52:45451 thread_->PostTask(FROM_HERE, base::Bind(&CookieMonsterTask::InvokeCallback,
452 this, callback));
[email protected]218aa6a12011-09-13 17:38:38453 }
454}
455
456// Task class for SetCookieWithDetails call.
[email protected]5fa4f9a2013-10-03 10:13:16457class CookieMonster::SetCookieWithDetailsTask : public CookieMonsterTask {
[email protected]218aa6a12011-09-13 17:38:38458 public:
[email protected]dedec0b2013-02-28 04:50:10459 SetCookieWithDetailsTask(CookieMonster* cookie_monster,
460 const GURL& url,
461 const std::string& name,
462 const std::string& value,
463 const std::string& domain,
464 const std::string& path,
465 const base::Time& expiration_time,
466 bool secure,
467 bool http_only,
mkwstae819bb2015-02-23 05:10:31468 bool first_party_only,
estarkcd39c11f2015-10-19 19:46:36469 bool enforce_prefixes,
jww601411a2015-11-20 19:46:57470 bool enforce_strict_secure,
[email protected]ab2d75c82013-04-19 18:39:04471 CookiePriority priority,
[email protected]5fa4f9a2013-10-03 10:13:16472 const SetCookiesCallback& callback)
[email protected]218aa6a12011-09-13 17:38:38473 : CookieMonsterTask(cookie_monster),
474 url_(url),
475 name_(name),
476 value_(value),
477 domain_(domain),
478 path_(path),
479 expiration_time_(expiration_time),
480 secure_(secure),
481 http_only_(http_only),
mkwstae819bb2015-02-23 05:10:31482 first_party_only_(first_party_only),
estarkcd39c11f2015-10-19 19:46:36483 enforce_prefixes_(enforce_prefixes),
jww601411a2015-11-20 19:46:57484 enforce_strict_secure_(enforce_strict_secure),
[email protected]ab2d75c82013-04-19 18:39:04485 priority_(priority),
mkwstbe84af312015-02-20 08:52:45486 callback_(callback) {}
[email protected]218aa6a12011-09-13 17:38:38487
[email protected]5fa4f9a2013-10-03 10:13:16488 // CookieMonsterTask:
dchengb03027d2014-10-21 12:00:20489 void Run() override;
[email protected]218aa6a12011-09-13 17:38:38490
[email protected]a9813302012-04-28 09:29:28491 protected:
dchengb03027d2014-10-21 12:00:20492 ~SetCookieWithDetailsTask() override {}
[email protected]a9813302012-04-28 09:29:28493
[email protected]218aa6a12011-09-13 17:38:38494 private:
495 GURL url_;
496 std::string name_;
497 std::string value_;
498 std::string domain_;
499 std::string path_;
500 base::Time expiration_time_;
501 bool secure_;
502 bool http_only_;
mkwstae819bb2015-02-23 05:10:31503 bool first_party_only_;
estarkcd39c11f2015-10-19 19:46:36504 bool enforce_prefixes_;
jww601411a2015-11-20 19:46:57505 bool enforce_strict_secure_;
[email protected]ab2d75c82013-04-19 18:39:04506 CookiePriority priority_;
[email protected]5fa4f9a2013-10-03 10:13:16507 SetCookiesCallback callback_;
[email protected]218aa6a12011-09-13 17:38:38508
509 DISALLOW_COPY_AND_ASSIGN(SetCookieWithDetailsTask);
510};
511
512void CookieMonster::SetCookieWithDetailsTask::Run() {
mkwstbe84af312015-02-20 08:52:45513 bool success = this->cookie_monster()->SetCookieWithDetails(
514 url_, name_, value_, domain_, path_, expiration_time_, secure_,
jww601411a2015-11-20 19:46:57515 http_only_, first_party_only_, enforce_prefixes_, enforce_strict_secure_,
516 priority_);
[email protected]218aa6a12011-09-13 17:38:38517 if (!callback_.is_null()) {
[email protected]5fa4f9a2013-10-03 10:13:16518 this->InvokeCallback(base::Bind(&SetCookiesCallback::Run,
[email protected]218aa6a12011-09-13 17:38:38519 base::Unretained(&callback_), success));
520 }
521}
522
523// Task class for GetAllCookies call.
[email protected]5fa4f9a2013-10-03 10:13:16524class CookieMonster::GetAllCookiesTask : public CookieMonsterTask {
[email protected]218aa6a12011-09-13 17:38:38525 public:
526 GetAllCookiesTask(CookieMonster* cookie_monster,
[email protected]5fa4f9a2013-10-03 10:13:16527 const GetCookieListCallback& callback)
mkwstbe84af312015-02-20 08:52:45528 : CookieMonsterTask(cookie_monster), callback_(callback) {}
[email protected]218aa6a12011-09-13 17:38:38529
[email protected]5fa4f9a2013-10-03 10:13:16530 // CookieMonsterTask
dchengb03027d2014-10-21 12:00:20531 void Run() override;
[email protected]218aa6a12011-09-13 17:38:38532
[email protected]a9813302012-04-28 09:29:28533 protected:
dchengb03027d2014-10-21 12:00:20534 ~GetAllCookiesTask() override {}
[email protected]a9813302012-04-28 09:29:28535
[email protected]218aa6a12011-09-13 17:38:38536 private:
[email protected]5fa4f9a2013-10-03 10:13:16537 GetCookieListCallback callback_;
[email protected]218aa6a12011-09-13 17:38:38538
539 DISALLOW_COPY_AND_ASSIGN(GetAllCookiesTask);
540};
541
542void CookieMonster::GetAllCookiesTask::Run() {
543 if (!callback_.is_null()) {
544 CookieList cookies = this->cookie_monster()->GetAllCookies();
[email protected]5fa4f9a2013-10-03 10:13:16545 this->InvokeCallback(base::Bind(&GetCookieListCallback::Run,
[email protected]218aa6a12011-09-13 17:38:38546 base::Unretained(&callback_), cookies));
mkwstbe84af312015-02-20 08:52:45547 }
[email protected]218aa6a12011-09-13 17:38:38548}
549
550// Task class for GetAllCookiesForURLWithOptions call.
551class CookieMonster::GetAllCookiesForURLWithOptionsTask
[email protected]5fa4f9a2013-10-03 10:13:16552 : public CookieMonsterTask {
[email protected]218aa6a12011-09-13 17:38:38553 public:
mkwstbe84af312015-02-20 08:52:45554 GetAllCookiesForURLWithOptionsTask(CookieMonster* cookie_monster,
555 const GURL& url,
556 const CookieOptions& options,
557 const GetCookieListCallback& callback)
[email protected]218aa6a12011-09-13 17:38:38558 : CookieMonsterTask(cookie_monster),
559 url_(url),
560 options_(options),
mkwstbe84af312015-02-20 08:52:45561 callback_(callback) {}
[email protected]218aa6a12011-09-13 17:38:38562
[email protected]5fa4f9a2013-10-03 10:13:16563 // CookieMonsterTask:
dchengb03027d2014-10-21 12:00:20564 void Run() override;
[email protected]218aa6a12011-09-13 17:38:38565
[email protected]a9813302012-04-28 09:29:28566 protected:
dchengb03027d2014-10-21 12:00:20567 ~GetAllCookiesForURLWithOptionsTask() override {}
[email protected]a9813302012-04-28 09:29:28568
[email protected]218aa6a12011-09-13 17:38:38569 private:
570 GURL url_;
571 CookieOptions options_;
[email protected]5fa4f9a2013-10-03 10:13:16572 GetCookieListCallback callback_;
[email protected]218aa6a12011-09-13 17:38:38573
574 DISALLOW_COPY_AND_ASSIGN(GetAllCookiesForURLWithOptionsTask);
575};
576
577void CookieMonster::GetAllCookiesForURLWithOptionsTask::Run() {
578 if (!callback_.is_null()) {
mkwstbe84af312015-02-20 08:52:45579 CookieList cookies =
580 this->cookie_monster()->GetAllCookiesForURLWithOptions(url_, options_);
[email protected]5fa4f9a2013-10-03 10:13:16581 this->InvokeCallback(base::Bind(&GetCookieListCallback::Run,
[email protected]218aa6a12011-09-13 17:38:38582 base::Unretained(&callback_), cookies));
583 }
584}
585
mkwstbe84af312015-02-20 08:52:45586template <typename Result>
587struct CallbackType {
[email protected]5fa4f9a2013-10-03 10:13:16588 typedef base::Callback<void(Result)> Type;
589};
590
mkwstbe84af312015-02-20 08:52:45591template <>
592struct CallbackType<void> {
[email protected]5fa4f9a2013-10-03 10:13:16593 typedef base::Closure Type;
594};
595
596// Base task class for Delete*Task.
597template <typename Result>
598class CookieMonster::DeleteTask : public CookieMonsterTask {
[email protected]218aa6a12011-09-13 17:38:38599 public:
[email protected]5fa4f9a2013-10-03 10:13:16600 DeleteTask(CookieMonster* cookie_monster,
601 const typename CallbackType<Result>::Type& callback)
mkwstbe84af312015-02-20 08:52:45602 : CookieMonsterTask(cookie_monster), callback_(callback) {}
[email protected]218aa6a12011-09-13 17:38:38603
[email protected]5fa4f9a2013-10-03 10:13:16604 // CookieMonsterTask:
nickd3f30d022015-04-23 10:18:37605 void Run() override;
[email protected]218aa6a12011-09-13 17:38:38606
dmichaeld6e570d2014-12-18 22:30:57607 protected:
608 ~DeleteTask() override;
609
[email protected]5fa4f9a2013-10-03 10:13:16610 private:
611 // Runs the delete task and returns a result.
612 virtual Result RunDeleteTask() = 0;
613 base::Closure RunDeleteTaskAndBindCallback();
614 void FlushDone(const base::Closure& callback);
615
616 typename CallbackType<Result>::Type callback_;
617
618 DISALLOW_COPY_AND_ASSIGN(DeleteTask);
619};
620
621template <typename Result>
dmichaeld6e570d2014-12-18 22:30:57622CookieMonster::DeleteTask<Result>::~DeleteTask() {
623}
624
625template <typename Result>
626base::Closure
627CookieMonster::DeleteTask<Result>::RunDeleteTaskAndBindCallback() {
[email protected]5fa4f9a2013-10-03 10:13:16628 Result result = RunDeleteTask();
629 if (callback_.is_null())
630 return base::Closure();
631 return base::Bind(callback_, result);
632}
633
634template <>
635base::Closure CookieMonster::DeleteTask<void>::RunDeleteTaskAndBindCallback() {
636 RunDeleteTask();
637 return callback_;
638}
639
640template <typename Result>
641void CookieMonster::DeleteTask<Result>::Run() {
mkwstbe84af312015-02-20 08:52:45642 this->cookie_monster()->FlushStore(base::Bind(
643 &DeleteTask<Result>::FlushDone, this, RunDeleteTaskAndBindCallback()));
[email protected]5fa4f9a2013-10-03 10:13:16644}
645
646template <typename Result>
647void CookieMonster::DeleteTask<Result>::FlushDone(
648 const base::Closure& callback) {
649 if (!callback.is_null()) {
650 this->InvokeCallback(callback);
651 }
652}
653
654// Task class for DeleteAll call.
655class CookieMonster::DeleteAllTask : public DeleteTask<int> {
656 public:
mkwstbe84af312015-02-20 08:52:45657 DeleteAllTask(CookieMonster* cookie_monster, const DeleteCallback& callback)
658 : DeleteTask<int>(cookie_monster, callback) {}
[email protected]5fa4f9a2013-10-03 10:13:16659
660 // DeleteTask:
dchengb03027d2014-10-21 12:00:20661 int RunDeleteTask() override;
[email protected]5fa4f9a2013-10-03 10:13:16662
[email protected]a9813302012-04-28 09:29:28663 protected:
dchengb03027d2014-10-21 12:00:20664 ~DeleteAllTask() override {}
[email protected]a9813302012-04-28 09:29:28665
[email protected]218aa6a12011-09-13 17:38:38666 private:
[email protected]218aa6a12011-09-13 17:38:38667 DISALLOW_COPY_AND_ASSIGN(DeleteAllTask);
668};
669
[email protected]5fa4f9a2013-10-03 10:13:16670int CookieMonster::DeleteAllTask::RunDeleteTask() {
671 return this->cookie_monster()->DeleteAll(true);
[email protected]218aa6a12011-09-13 17:38:38672}
673
674// Task class for DeleteAllCreatedBetween call.
[email protected]5fa4f9a2013-10-03 10:13:16675class CookieMonster::DeleteAllCreatedBetweenTask : public DeleteTask<int> {
[email protected]218aa6a12011-09-13 17:38:38676 public:
[email protected]dedec0b2013-02-28 04:50:10677 DeleteAllCreatedBetweenTask(CookieMonster* cookie_monster,
678 const Time& delete_begin,
679 const Time& delete_end,
[email protected]5fa4f9a2013-10-03 10:13:16680 const DeleteCallback& callback)
[email protected]151132f2013-11-18 21:37:00681 : DeleteTask<int>(cookie_monster, callback),
[email protected]218aa6a12011-09-13 17:38:38682 delete_begin_(delete_begin),
mkwstbe84af312015-02-20 08:52:45683 delete_end_(delete_end) {}
[email protected]218aa6a12011-09-13 17:38:38684
[email protected]5fa4f9a2013-10-03 10:13:16685 // DeleteTask:
dchengb03027d2014-10-21 12:00:20686 int RunDeleteTask() override;
[email protected]218aa6a12011-09-13 17:38:38687
[email protected]a9813302012-04-28 09:29:28688 protected:
dchengb03027d2014-10-21 12:00:20689 ~DeleteAllCreatedBetweenTask() override {}
[email protected]a9813302012-04-28 09:29:28690
[email protected]218aa6a12011-09-13 17:38:38691 private:
692 Time delete_begin_;
693 Time delete_end_;
[email protected]218aa6a12011-09-13 17:38:38694
695 DISALLOW_COPY_AND_ASSIGN(DeleteAllCreatedBetweenTask);
696};
697
[email protected]5fa4f9a2013-10-03 10:13:16698int CookieMonster::DeleteAllCreatedBetweenTask::RunDeleteTask() {
mkwstbe84af312015-02-20 08:52:45699 return this->cookie_monster()->DeleteAllCreatedBetween(delete_begin_,
700 delete_end_);
[email protected]218aa6a12011-09-13 17:38:38701}
702
703// Task class for DeleteAllForHost call.
[email protected]5fa4f9a2013-10-03 10:13:16704class CookieMonster::DeleteAllForHostTask : public DeleteTask<int> {
[email protected]218aa6a12011-09-13 17:38:38705 public:
706 DeleteAllForHostTask(CookieMonster* cookie_monster,
707 const GURL& url,
[email protected]5fa4f9a2013-10-03 10:13:16708 const DeleteCallback& callback)
mkwstbe84af312015-02-20 08:52:45709 : DeleteTask<int>(cookie_monster, callback), url_(url) {}
[email protected]218aa6a12011-09-13 17:38:38710
[email protected]5fa4f9a2013-10-03 10:13:16711 // DeleteTask:
dchengb03027d2014-10-21 12:00:20712 int RunDeleteTask() override;
[email protected]218aa6a12011-09-13 17:38:38713
[email protected]a9813302012-04-28 09:29:28714 protected:
dchengb03027d2014-10-21 12:00:20715 ~DeleteAllForHostTask() override {}
[email protected]a9813302012-04-28 09:29:28716
[email protected]218aa6a12011-09-13 17:38:38717 private:
718 GURL url_;
[email protected]218aa6a12011-09-13 17:38:38719
720 DISALLOW_COPY_AND_ASSIGN(DeleteAllForHostTask);
721};
722
[email protected]5fa4f9a2013-10-03 10:13:16723int CookieMonster::DeleteAllForHostTask::RunDeleteTask() {
724 return this->cookie_monster()->DeleteAllForHost(url_);
[email protected]218aa6a12011-09-13 17:38:38725}
726
[email protected]d8428d52013-08-07 06:58:25727// Task class for DeleteAllCreatedBetweenForHost call.
728class CookieMonster::DeleteAllCreatedBetweenForHostTask
[email protected]5fa4f9a2013-10-03 10:13:16729 : public DeleteTask<int> {
[email protected]d8428d52013-08-07 06:58:25730 public:
mkwstbe84af312015-02-20 08:52:45731 DeleteAllCreatedBetweenForHostTask(CookieMonster* cookie_monster,
732 Time delete_begin,
733 Time delete_end,
734 const GURL& url,
735 const DeleteCallback& callback)
[email protected]151132f2013-11-18 21:37:00736 : DeleteTask<int>(cookie_monster, callback),
[email protected]d8428d52013-08-07 06:58:25737 delete_begin_(delete_begin),
738 delete_end_(delete_end),
mkwstbe84af312015-02-20 08:52:45739 url_(url) {}
[email protected]d8428d52013-08-07 06:58:25740
[email protected]5fa4f9a2013-10-03 10:13:16741 // DeleteTask:
dchengb03027d2014-10-21 12:00:20742 int RunDeleteTask() override;
[email protected]d8428d52013-08-07 06:58:25743
744 protected:
dchengb03027d2014-10-21 12:00:20745 ~DeleteAllCreatedBetweenForHostTask() override {}
[email protected]d8428d52013-08-07 06:58:25746
747 private:
748 Time delete_begin_;
749 Time delete_end_;
750 GURL url_;
[email protected]d8428d52013-08-07 06:58:25751
752 DISALLOW_COPY_AND_ASSIGN(DeleteAllCreatedBetweenForHostTask);
753};
754
[email protected]5fa4f9a2013-10-03 10:13:16755int CookieMonster::DeleteAllCreatedBetweenForHostTask::RunDeleteTask() {
756 return this->cookie_monster()->DeleteAllCreatedBetweenForHost(
[email protected]d8428d52013-08-07 06:58:25757 delete_begin_, delete_end_, url_);
[email protected]d8428d52013-08-07 06:58:25758}
759
[email protected]218aa6a12011-09-13 17:38:38760// Task class for DeleteCanonicalCookie call.
[email protected]5fa4f9a2013-10-03 10:13:16761class CookieMonster::DeleteCanonicalCookieTask : public DeleteTask<bool> {
[email protected]218aa6a12011-09-13 17:38:38762 public:
[email protected]dedec0b2013-02-28 04:50:10763 DeleteCanonicalCookieTask(CookieMonster* cookie_monster,
764 const CanonicalCookie& cookie,
[email protected]5fa4f9a2013-10-03 10:13:16765 const DeleteCookieCallback& callback)
mkwstbe84af312015-02-20 08:52:45766 : DeleteTask<bool>(cookie_monster, callback), cookie_(cookie) {}
[email protected]218aa6a12011-09-13 17:38:38767
[email protected]5fa4f9a2013-10-03 10:13:16768 // DeleteTask:
dchengb03027d2014-10-21 12:00:20769 bool RunDeleteTask() override;
[email protected]218aa6a12011-09-13 17:38:38770
[email protected]a9813302012-04-28 09:29:28771 protected:
dchengb03027d2014-10-21 12:00:20772 ~DeleteCanonicalCookieTask() override {}
[email protected]a9813302012-04-28 09:29:28773
[email protected]218aa6a12011-09-13 17:38:38774 private:
[email protected]5b9bc352012-07-18 13:13:34775 CanonicalCookie cookie_;
[email protected]218aa6a12011-09-13 17:38:38776
777 DISALLOW_COPY_AND_ASSIGN(DeleteCanonicalCookieTask);
778};
779
[email protected]5fa4f9a2013-10-03 10:13:16780bool CookieMonster::DeleteCanonicalCookieTask::RunDeleteTask() {
781 return this->cookie_monster()->DeleteCanonicalCookie(cookie_);
[email protected]218aa6a12011-09-13 17:38:38782}
783
784// Task class for SetCookieWithOptions call.
[email protected]5fa4f9a2013-10-03 10:13:16785class CookieMonster::SetCookieWithOptionsTask : public CookieMonsterTask {
[email protected]218aa6a12011-09-13 17:38:38786 public:
787 SetCookieWithOptionsTask(CookieMonster* cookie_monster,
788 const GURL& url,
789 const std::string& cookie_line,
790 const CookieOptions& options,
[email protected]5fa4f9a2013-10-03 10:13:16791 const SetCookiesCallback& callback)
[email protected]218aa6a12011-09-13 17:38:38792 : CookieMonsterTask(cookie_monster),
793 url_(url),
794 cookie_line_(cookie_line),
795 options_(options),
mkwstbe84af312015-02-20 08:52:45796 callback_(callback) {}
[email protected]218aa6a12011-09-13 17:38:38797
[email protected]5fa4f9a2013-10-03 10:13:16798 // CookieMonsterTask:
dchengb03027d2014-10-21 12:00:20799 void Run() override;
[email protected]218aa6a12011-09-13 17:38:38800
[email protected]a9813302012-04-28 09:29:28801 protected:
dchengb03027d2014-10-21 12:00:20802 ~SetCookieWithOptionsTask() override {}
[email protected]a9813302012-04-28 09:29:28803
[email protected]218aa6a12011-09-13 17:38:38804 private:
805 GURL url_;
806 std::string cookie_line_;
807 CookieOptions options_;
[email protected]5fa4f9a2013-10-03 10:13:16808 SetCookiesCallback callback_;
[email protected]218aa6a12011-09-13 17:38:38809
810 DISALLOW_COPY_AND_ASSIGN(SetCookieWithOptionsTask);
811};
812
813void CookieMonster::SetCookieWithOptionsTask::Run() {
mkwstbe84af312015-02-20 08:52:45814 bool result = this->cookie_monster()->SetCookieWithOptions(url_, cookie_line_,
815 options_);
[email protected]218aa6a12011-09-13 17:38:38816 if (!callback_.is_null()) {
[email protected]5fa4f9a2013-10-03 10:13:16817 this->InvokeCallback(base::Bind(&SetCookiesCallback::Run,
[email protected]218aa6a12011-09-13 17:38:38818 base::Unretained(&callback_), result));
819 }
820}
821
drogerd5d1278c2015-03-17 19:21:51822// Task class for SetAllCookies call.
823class CookieMonster::SetAllCookiesTask : public CookieMonsterTask {
824 public:
825 SetAllCookiesTask(CookieMonster* cookie_monster,
826 const CookieList& list,
827 const SetCookiesCallback& callback)
828 : CookieMonsterTask(cookie_monster), list_(list), callback_(callback) {}
829
830 // CookieMonsterTask:
831 void Run() override;
832
833 protected:
834 ~SetAllCookiesTask() override {}
835
836 private:
837 CookieList list_;
838 SetCookiesCallback callback_;
839
840 DISALLOW_COPY_AND_ASSIGN(SetAllCookiesTask);
841};
842
843void CookieMonster::SetAllCookiesTask::Run() {
844 CookieList positive_diff;
845 CookieList negative_diff;
846 CookieList old_cookies = this->cookie_monster()->GetAllCookies();
847 this->cookie_monster()->ComputeCookieDiff(&old_cookies, &list_,
848 &positive_diff, &negative_diff);
849
850 for (CookieList::const_iterator it = negative_diff.begin();
851 it != negative_diff.end(); ++it) {
852 this->cookie_monster()->DeleteCanonicalCookie(*it);
853 }
854
855 bool result = true;
856 if (positive_diff.size() > 0)
857 result = this->cookie_monster()->SetCanonicalCookies(list_);
858
859 if (!callback_.is_null()) {
860 this->InvokeCallback(base::Bind(&SetCookiesCallback::Run,
861 base::Unretained(&callback_), result));
862 }
863}
864
[email protected]218aa6a12011-09-13 17:38:38865// Task class for GetCookiesWithOptions call.
[email protected]5fa4f9a2013-10-03 10:13:16866class CookieMonster::GetCookiesWithOptionsTask : public CookieMonsterTask {
[email protected]218aa6a12011-09-13 17:38:38867 public:
868 GetCookiesWithOptionsTask(CookieMonster* cookie_monster,
[email protected]0298caf82011-12-20 23:15:46869 const GURL& url,
[email protected]218aa6a12011-09-13 17:38:38870 const CookieOptions& options,
[email protected]5fa4f9a2013-10-03 10:13:16871 const GetCookiesCallback& callback)
[email protected]218aa6a12011-09-13 17:38:38872 : CookieMonsterTask(cookie_monster),
873 url_(url),
874 options_(options),
mkwstbe84af312015-02-20 08:52:45875 callback_(callback) {}
[email protected]218aa6a12011-09-13 17:38:38876
[email protected]5fa4f9a2013-10-03 10:13:16877 // CookieMonsterTask:
dchengb03027d2014-10-21 12:00:20878 void Run() override;
[email protected]218aa6a12011-09-13 17:38:38879
[email protected]a9813302012-04-28 09:29:28880 protected:
dchengb03027d2014-10-21 12:00:20881 ~GetCookiesWithOptionsTask() override {}
[email protected]a9813302012-04-28 09:29:28882
[email protected]218aa6a12011-09-13 17:38:38883 private:
884 GURL url_;
885 CookieOptions options_;
[email protected]5fa4f9a2013-10-03 10:13:16886 GetCookiesCallback callback_;
[email protected]218aa6a12011-09-13 17:38:38887
888 DISALLOW_COPY_AND_ASSIGN(GetCookiesWithOptionsTask);
889};
890
891void CookieMonster::GetCookiesWithOptionsTask::Run() {
pkastinga9269aa42015-04-10 01:42:26892 // TODO(mkwst): Remove ScopedTracker below once crbug.com/456373 is fixed.
pkasting58e029b2015-02-21 05:17:28893 tracked_objects::ScopedTracker tracking_profile(
894 FROM_HERE_WITH_EXPLICIT_FUNCTION(
895 "456373 CookieMonster::GetCookiesWithOptionsTask::Run"));
mkwstbe84af312015-02-20 08:52:45896 std::string cookie =
897 this->cookie_monster()->GetCookiesWithOptions(url_, options_);
[email protected]218aa6a12011-09-13 17:38:38898 if (!callback_.is_null()) {
[email protected]5fa4f9a2013-10-03 10:13:16899 this->InvokeCallback(base::Bind(&GetCookiesCallback::Run,
[email protected]218aa6a12011-09-13 17:38:38900 base::Unretained(&callback_), cookie));
901 }
902}
903
[email protected]218aa6a12011-09-13 17:38:38904// Task class for DeleteCookie call.
[email protected]5fa4f9a2013-10-03 10:13:16905class CookieMonster::DeleteCookieTask : public DeleteTask<void> {
[email protected]218aa6a12011-09-13 17:38:38906 public:
907 DeleteCookieTask(CookieMonster* cookie_monster,
[email protected]0298caf82011-12-20 23:15:46908 const GURL& url,
[email protected]218aa6a12011-09-13 17:38:38909 const std::string& cookie_name,
910 const base::Closure& callback)
[email protected]151132f2013-11-18 21:37:00911 : DeleteTask<void>(cookie_monster, callback),
[email protected]218aa6a12011-09-13 17:38:38912 url_(url),
mkwstbe84af312015-02-20 08:52:45913 cookie_name_(cookie_name) {}
[email protected]218aa6a12011-09-13 17:38:38914
[email protected]5fa4f9a2013-10-03 10:13:16915 // DeleteTask:
dchengb03027d2014-10-21 12:00:20916 void RunDeleteTask() override;
[email protected]218aa6a12011-09-13 17:38:38917
[email protected]a9813302012-04-28 09:29:28918 protected:
dchengb03027d2014-10-21 12:00:20919 ~DeleteCookieTask() override {}
[email protected]a9813302012-04-28 09:29:28920
[email protected]218aa6a12011-09-13 17:38:38921 private:
922 GURL url_;
923 std::string cookie_name_;
[email protected]218aa6a12011-09-13 17:38:38924
925 DISALLOW_COPY_AND_ASSIGN(DeleteCookieTask);
926};
927
[email protected]5fa4f9a2013-10-03 10:13:16928void CookieMonster::DeleteCookieTask::RunDeleteTask() {
[email protected]218aa6a12011-09-13 17:38:38929 this->cookie_monster()->DeleteCookie(url_, cookie_name_);
[email protected]218aa6a12011-09-13 17:38:38930}
931
[email protected]264807b2012-04-25 14:49:37932// Task class for DeleteSessionCookies call.
[email protected]5fa4f9a2013-10-03 10:13:16933class CookieMonster::DeleteSessionCookiesTask : public DeleteTask<int> {
[email protected]264807b2012-04-25 14:49:37934 public:
[email protected]dedec0b2013-02-28 04:50:10935 DeleteSessionCookiesTask(CookieMonster* cookie_monster,
[email protected]5fa4f9a2013-10-03 10:13:16936 const DeleteCallback& callback)
mkwstbe84af312015-02-20 08:52:45937 : DeleteTask<int>(cookie_monster, callback) {}
[email protected]264807b2012-04-25 14:49:37938
[email protected]5fa4f9a2013-10-03 10:13:16939 // DeleteTask:
dchengb03027d2014-10-21 12:00:20940 int RunDeleteTask() override;
[email protected]264807b2012-04-25 14:49:37941
[email protected]a9813302012-04-28 09:29:28942 protected:
dchengb03027d2014-10-21 12:00:20943 ~DeleteSessionCookiesTask() override {}
[email protected]a9813302012-04-28 09:29:28944
[email protected]264807b2012-04-25 14:49:37945 private:
[email protected]264807b2012-04-25 14:49:37946 DISALLOW_COPY_AND_ASSIGN(DeleteSessionCookiesTask);
947};
948
[email protected]5fa4f9a2013-10-03 10:13:16949int CookieMonster::DeleteSessionCookiesTask::RunDeleteTask() {
950 return this->cookie_monster()->DeleteSessionCookies();
[email protected]264807b2012-04-25 14:49:37951}
952
[email protected]218aa6a12011-09-13 17:38:38953// Asynchronous CookieMonster API
954
955void CookieMonster::SetCookieWithDetailsAsync(
[email protected]dedec0b2013-02-28 04:50:10956 const GURL& url,
957 const std::string& name,
958 const std::string& value,
959 const std::string& domain,
960 const std::string& path,
[email protected]d8428d52013-08-07 06:58:25961 const Time& expiration_time,
[email protected]dedec0b2013-02-28 04:50:10962 bool secure,
963 bool http_only,
mkwstae819bb2015-02-23 05:10:31964 bool first_party_only,
estarkcd39c11f2015-10-19 19:46:36965 bool enforce_prefixes,
jww601411a2015-11-20 19:46:57966 bool enforce_strict_secure,
[email protected]ab2d75c82013-04-19 18:39:04967 CookiePriority priority,
[email protected]218aa6a12011-09-13 17:38:38968 const SetCookiesCallback& callback) {
mkwstbe84af312015-02-20 08:52:45969 scoped_refptr<SetCookieWithDetailsTask> task = new SetCookieWithDetailsTask(
970 this, url, name, value, domain, path, expiration_time, secure, http_only,
jww601411a2015-11-20 19:46:57971 first_party_only, enforce_prefixes, enforce_strict_secure, priority,
972 callback);
[email protected]8562034e2011-10-17 17:35:04973 DoCookieTaskForURL(task, url);
[email protected]218aa6a12011-09-13 17:38:38974}
975
976void CookieMonster::GetAllCookiesAsync(const GetCookieListCallback& callback) {
mkwstbe84af312015-02-20 08:52:45977 scoped_refptr<GetAllCookiesTask> task = new GetAllCookiesTask(this, callback);
[email protected]218aa6a12011-09-13 17:38:38978
979 DoCookieTask(task);
980}
981
[email protected]218aa6a12011-09-13 17:38:38982void CookieMonster::GetAllCookiesForURLWithOptionsAsync(
983 const GURL& url,
984 const CookieOptions& options,
985 const GetCookieListCallback& callback) {
986 scoped_refptr<GetAllCookiesForURLWithOptionsTask> task =
987 new GetAllCookiesForURLWithOptionsTask(this, url, options, callback);
988
[email protected]8562034e2011-10-17 17:35:04989 DoCookieTaskForURL(task, url);
[email protected]218aa6a12011-09-13 17:38:38990}
991
[email protected]218aa6a12011-09-13 17:38:38992void CookieMonster::DeleteAllAsync(const DeleteCallback& callback) {
mkwstbe84af312015-02-20 08:52:45993 scoped_refptr<DeleteAllTask> task = new DeleteAllTask(this, callback);
[email protected]218aa6a12011-09-13 17:38:38994
995 DoCookieTask(task);
996}
997
mkwstbe84af312015-02-20 08:52:45998void CookieMonster::DeleteAllForHostAsync(const GURL& url,
999 const DeleteCallback& callback) {
[email protected]218aa6a12011-09-13 17:38:381000 scoped_refptr<DeleteAllForHostTask> task =
1001 new DeleteAllForHostTask(this, url, callback);
1002
[email protected]8562034e2011-10-17 17:35:041003 DoCookieTaskForURL(task, url);
[email protected]218aa6a12011-09-13 17:38:381004}
1005
1006void CookieMonster::DeleteCanonicalCookieAsync(
1007 const CanonicalCookie& cookie,
1008 const DeleteCookieCallback& callback) {
1009 scoped_refptr<DeleteCanonicalCookieTask> task =
1010 new DeleteCanonicalCookieTask(this, cookie, callback);
1011
1012 DoCookieTask(task);
1013}
1014
mmenke74bcbd52016-01-21 17:17:561015void CookieMonster::FlushStore(const base::Closure& callback) {
1016 base::AutoLock autolock(lock_);
1017 if (initialized_ && store_.get())
1018 store_->Flush(callback);
1019 else if (!callback.is_null())
1020 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, callback);
1021}
1022
drogerd5d1278c2015-03-17 19:21:511023void CookieMonster::SetAllCookiesAsync(const CookieList& list,
1024 const SetCookiesCallback& callback) {
1025 scoped_refptr<SetAllCookiesTask> task =
1026 new SetAllCookiesTask(this, list, callback);
1027 DoCookieTask(task);
1028}
1029
[email protected]218aa6a12011-09-13 17:38:381030void CookieMonster::SetCookieWithOptionsAsync(
1031 const GURL& url,
1032 const std::string& cookie_line,
1033 const CookieOptions& options,
1034 const SetCookiesCallback& callback) {
1035 scoped_refptr<SetCookieWithOptionsTask> task =
1036 new SetCookieWithOptionsTask(this, url, cookie_line, options, callback);
1037
[email protected]8562034e2011-10-17 17:35:041038 DoCookieTaskForURL(task, url);
[email protected]218aa6a12011-09-13 17:38:381039}
1040
1041void CookieMonster::GetCookiesWithOptionsAsync(
1042 const GURL& url,
1043 const CookieOptions& options,
1044 const GetCookiesCallback& callback) {
1045 scoped_refptr<GetCookiesWithOptionsTask> task =
1046 new GetCookiesWithOptionsTask(this, url, options, callback);
1047
[email protected]8562034e2011-10-17 17:35:041048 DoCookieTaskForURL(task, url);
[email protected]218aa6a12011-09-13 17:38:381049}
1050
mmenke74bcbd52016-01-21 17:17:561051void CookieMonster::GetAllCookiesForURLAsync(
1052 const GURL& url,
1053 const GetCookieListCallback& callback) {
1054 CookieOptions options;
1055 options.set_include_httponly();
1056 options.set_include_first_party_only_cookies();
1057 scoped_refptr<GetAllCookiesForURLWithOptionsTask> task =
1058 new GetAllCookiesForURLWithOptionsTask(this, url, options, callback);
1059
1060 DoCookieTaskForURL(task, url);
1061}
1062
[email protected]218aa6a12011-09-13 17:38:381063void CookieMonster::DeleteCookieAsync(const GURL& url,
1064 const std::string& cookie_name,
1065 const base::Closure& callback) {
1066 scoped_refptr<DeleteCookieTask> task =
1067 new DeleteCookieTask(this, url, cookie_name, callback);
1068
[email protected]8562034e2011-10-17 17:35:041069 DoCookieTaskForURL(task, url);
[email protected]218aa6a12011-09-13 17:38:381070}
1071
mmenke74bcbd52016-01-21 17:17:561072void CookieMonster::DeleteAllCreatedBetweenAsync(
1073 const Time& delete_begin,
1074 const Time& delete_end,
1075 const DeleteCallback& callback) {
1076 scoped_refptr<DeleteAllCreatedBetweenTask> task =
1077 new DeleteAllCreatedBetweenTask(this, delete_begin, delete_end, callback);
1078
1079 DoCookieTask(task);
1080}
1081
1082void CookieMonster::DeleteAllCreatedBetweenForHostAsync(
1083 const Time delete_begin,
1084 const Time delete_end,
1085 const GURL& url,
1086 const DeleteCallback& callback) {
1087 scoped_refptr<DeleteAllCreatedBetweenForHostTask> task =
1088 new DeleteAllCreatedBetweenForHostTask(this, delete_begin, delete_end,
1089 url, callback);
1090
1091 DoCookieTaskForURL(task, url);
1092}
1093
[email protected]264807b2012-04-25 14:49:371094void CookieMonster::DeleteSessionCookiesAsync(
1095 const CookieStore::DeleteCallback& callback) {
1096 scoped_refptr<DeleteSessionCookiesTask> task =
1097 new DeleteSessionCookiesTask(this, callback);
1098
1099 DoCookieTask(task);
1100}
1101
mmenke74bcbd52016-01-21 17:17:561102CookieMonster* CookieMonster::GetCookieMonster() {
1103 return this;
[email protected]218aa6a12011-09-13 17:38:381104}
1105
mmenke74bcbd52016-01-21 17:17:561106void CookieMonster::SetCookieableSchemes(const char* const schemes[],
1107 size_t num_schemes) {
1108 base::AutoLock autolock(lock_);
1109
1110 // Calls to this method will have no effect if made after a WebView or
1111 // CookieManager instance has been created.
1112 if (initialized_) {
1113 return;
[email protected]8562034e2011-10-17 17:35:041114 }
mmenke74bcbd52016-01-21 17:17:561115
1116 cookieable_schemes_.clear();
1117 cookieable_schemes_.insert(cookieable_schemes_.end(), schemes,
1118 schemes + num_schemes);
1119}
1120
1121void CookieMonster::SetKeepExpiredCookies() {
1122 keep_expired_cookies_ = true;
1123}
1124
1125void CookieMonster::SetForceKeepSessionState() {
1126 if (store_.get()) {
1127 store_->SetForceKeepSessionState();
1128 }
1129}
1130
1131// This function must be called before the CookieMonster is used.
1132void CookieMonster::SetPersistSessionCookies(bool persist_session_cookies) {
1133 DCHECK(!initialized_);
1134 persist_session_cookies_ = persist_session_cookies;
1135}
1136
1137bool CookieMonster::IsCookieableScheme(const std::string& scheme) {
1138 base::AutoLock autolock(lock_);
1139
1140 return std::find(cookieable_schemes_.begin(), cookieable_schemes_.end(),
1141 scheme) != cookieable_schemes_.end();
1142}
1143
1144// Note: file must be the last scheme.
1145const char* const CookieMonster::kDefaultCookieableSchemes[] = {"http",
1146 "https",
1147 "ws",
1148 "wss",
1149 "file"};
1150const int CookieMonster::kDefaultCookieableSchemesCount =
1151 arraysize(kDefaultCookieableSchemes);
1152
1153scoped_ptr<CookieStore::CookieChangedSubscription>
1154CookieMonster::AddCallbackForCookie(const GURL& gurl,
1155 const std::string& name,
1156 const CookieChangedCallback& callback) {
1157 base::AutoLock autolock(lock_);
1158 std::pair<GURL, std::string> key(gurl, name);
1159 if (hook_map_.count(key) == 0)
1160 hook_map_[key] = make_linked_ptr(new CookieChangedCallbackList());
1161 return hook_map_[key]->Add(
1162 base::Bind(&RunAsync, base::ThreadTaskRunnerHandle::Get(), callback));
1163}
1164
1165#if defined(OS_ANDROID)
1166void CookieMonster::SetEnableFileScheme(bool accept) {
1167 // This assumes "file" is always at the end of the array. See the comment
1168 // above kDefaultCookieableSchemes.
1169 //
1170 // TODO(mkwst): We're keeping this method around to support the
1171 // 'CookieManager::setAcceptFileSchemeCookies' method on Android's WebView;
1172 // if/when we can deprecate and remove that method, we can remove this one
1173 // as well. Until then, we'll just ensure that the method has no effect on
1174 // non-android systems.
1175 int num_schemes = accept ? kDefaultCookieableSchemesCount
1176 : kDefaultCookieableSchemesCount - 1;
1177
1178 SetCookieableSchemes(kDefaultCookieableSchemes, num_schemes);
1179}
1180#endif
1181
1182CookieMonster::~CookieMonster() {
1183 DeleteAll(false);
[email protected]8562034e2011-10-17 17:35:041184}
1185
[email protected]dedec0b2013-02-28 04:50:101186bool CookieMonster::SetCookieWithDetails(const GURL& url,
1187 const std::string& name,
1188 const std::string& value,
1189 const std::string& domain,
1190 const std::string& path,
1191 const base::Time& expiration_time,
1192 bool secure,
[email protected]ab2d75c82013-04-19 18:39:041193 bool http_only,
mkwstae819bb2015-02-23 05:10:311194 bool first_party_only,
estarkcd39c11f2015-10-19 19:46:361195 bool enforce_prefixes,
jww601411a2015-11-20 19:46:571196 bool enforce_strict_secure,
[email protected]ab2d75c82013-04-19 18:39:041197 CookiePriority priority) {
[email protected]20305ec2011-01-21 04:55:521198 base::AutoLock autolock(lock_);
[email protected]69bb5872010-01-12 20:33:521199
[email protected]f48b9432011-01-11 07:25:401200 if (!HasCookieableScheme(url))
initial.commit586acc5fe2008-07-26 22:42:521201 return false;
1202
[email protected]f48b9432011-01-11 07:25:401203 Time creation_time = CurrentTime();
1204 last_time_seen_ = creation_time;
1205
tfh4623ce82016-01-21 10:37:371206 scoped_ptr<CanonicalCookie> cc(CanonicalCookie::Create(
jww601411a2015-11-20 19:46:571207 url, name, value, domain, path, creation_time, expiration_time, secure,
1208 http_only, first_party_only, enforce_strict_secure, priority));
[email protected]f48b9432011-01-11 07:25:401209
1210 if (!cc.get())
1211 return false;
1212
1213 CookieOptions options;
1214 options.set_include_httponly();
mkwst202534e32016-01-15 16:07:151215 options.set_include_first_party_only_cookies();
jww601411a2015-11-20 19:46:571216 if (enforce_strict_secure)
1217 options.set_enforce_strict_secure();
[email protected]f48b9432011-01-11 07:25:401218 return SetCanonicalCookie(&cc, creation_time, options);
initial.commit586acc5fe2008-07-26 22:42:521219}
1220
[email protected]f48b9432011-01-11 07:25:401221CookieList CookieMonster::GetAllCookies() {
[email protected]20305ec2011-01-21 04:55:521222 base::AutoLock autolock(lock_);
[email protected]f48b9432011-01-11 07:25:401223
1224 // This function is being called to scrape the cookie list for management UI
1225 // or similar. We shouldn't show expired cookies in this list since it will
1226 // just be confusing to users, and this function is called rarely enough (and
1227 // is already slow enough) that it's OK to take the time to garbage collect
1228 // the expired cookies now.
1229 //
1230 // Note that this does not prune cookies to be below our limits (if we've
1231 // exceeded them) the way that calling GarbageCollect() would.
mkwstbe84af312015-02-20 08:52:451232 GarbageCollectExpired(
1233 Time::Now(), CookieMapItPair(cookies_.begin(), cookies_.end()), NULL);
[email protected]f48b9432011-01-11 07:25:401234
1235 // Copy the CanonicalCookie pointers from the map so that we can use the same
1236 // sorter as elsewhere, then copy the result out.
1237 std::vector<CanonicalCookie*> cookie_ptrs;
1238 cookie_ptrs.reserve(cookies_.size());
1239 for (CookieMap::iterator it = cookies_.begin(); it != cookies_.end(); ++it)
1240 cookie_ptrs.push_back(it->second);
1241 std::sort(cookie_ptrs.begin(), cookie_ptrs.end(), CookieSorter);
1242
1243 CookieList cookie_list;
1244 cookie_list.reserve(cookie_ptrs.size());
1245 for (std::vector<CanonicalCookie*>::const_iterator it = cookie_ptrs.begin();
1246 it != cookie_ptrs.end(); ++it)
1247 cookie_list.push_back(**it);
1248
1249 return cookie_list;
[email protected]f325f1e12010-04-30 22:38:551250}
1251
[email protected]f48b9432011-01-11 07:25:401252CookieList CookieMonster::GetAllCookiesForURLWithOptions(
1253 const GURL& url,
1254 const CookieOptions& options) {
[email protected]20305ec2011-01-21 04:55:521255 base::AutoLock autolock(lock_);
initial.commit586acc5fe2008-07-26 22:42:521256
[email protected]f48b9432011-01-11 07:25:401257 std::vector<CanonicalCookie*> cookie_ptrs;
1258 FindCookiesForHostAndDomain(url, options, false, &cookie_ptrs);
1259 std::sort(cookie_ptrs.begin(), cookie_ptrs.end(), CookieSorter);
initial.commit586acc5fe2008-07-26 22:42:521260
[email protected]f48b9432011-01-11 07:25:401261 CookieList cookies;
georgesakc15df6722014-12-02 23:52:121262 cookies.reserve(cookie_ptrs.size());
[email protected]f48b9432011-01-11 07:25:401263 for (std::vector<CanonicalCookie*>::const_iterator it = cookie_ptrs.begin();
1264 it != cookie_ptrs.end(); it++)
1265 cookies.push_back(**it);
initial.commit586acc5fe2008-07-26 22:42:521266
[email protected]f48b9432011-01-11 07:25:401267 return cookies;
initial.commit586acc5fe2008-07-26 22:42:521268}
1269
[email protected]f48b9432011-01-11 07:25:401270int CookieMonster::DeleteAll(bool sync_to_store) {
[email protected]20305ec2011-01-21 04:55:521271 base::AutoLock autolock(lock_);
[email protected]f48b9432011-01-11 07:25:401272
1273 int num_deleted = 0;
1274 for (CookieMap::iterator it = cookies_.begin(); it != cookies_.end();) {
1275 CookieMap::iterator curit = it;
1276 ++it;
1277 InternalDeleteCookie(curit, sync_to_store,
mkwstbe84af312015-02-20 08:52:451278 sync_to_store
1279 ? DELETE_COOKIE_EXPLICIT
1280 : DELETE_COOKIE_DONT_RECORD /* Destruction. */);
[email protected]f48b9432011-01-11 07:25:401281 ++num_deleted;
initial.commit586acc5fe2008-07-26 22:42:521282 }
1283
[email protected]f48b9432011-01-11 07:25:401284 return num_deleted;
initial.commit586acc5fe2008-07-26 22:42:521285}
1286
[email protected]f48b9432011-01-11 07:25:401287int CookieMonster::DeleteAllCreatedBetween(const Time& delete_begin,
[email protected]218aa6a12011-09-13 17:38:381288 const Time& delete_end) {
[email protected]20305ec2011-01-21 04:55:521289 base::AutoLock autolock(lock_);
[email protected]d0980332010-11-16 17:08:531290
[email protected]f48b9432011-01-11 07:25:401291 int num_deleted = 0;
1292 for (CookieMap::iterator it = cookies_.begin(); it != cookies_.end();) {
1293 CookieMap::iterator curit = it;
1294 CanonicalCookie* cc = curit->second;
1295 ++it;
[email protected]d0980332010-11-16 17:08:531296
[email protected]f48b9432011-01-11 07:25:401297 if (cc->CreationDate() >= delete_begin &&
1298 (delete_end.is_null() || cc->CreationDate() < delete_end)) {
mkwstbe84af312015-02-20 08:52:451299 InternalDeleteCookie(curit, true, /*sync_to_store*/
[email protected]218aa6a12011-09-13 17:38:381300 DELETE_COOKIE_EXPLICIT);
[email protected]f48b9432011-01-11 07:25:401301 ++num_deleted;
initial.commit586acc5fe2008-07-26 22:42:521302 }
1303 }
1304
[email protected]f48b9432011-01-11 07:25:401305 return num_deleted;
1306}
1307
mmenke74bcbd52016-01-21 17:17:561308int CookieMonster::DeleteAllForHost(const GURL& url) {
1309 return DeleteAllCreatedBetweenForHost(Time(), Time::Max(), url);
1310}
1311
[email protected]d8428d52013-08-07 06:58:251312int CookieMonster::DeleteAllCreatedBetweenForHost(const Time delete_begin,
1313 const Time delete_end,
1314 const GURL& url) {
[email protected]20305ec2011-01-21 04:55:521315 base::AutoLock autolock(lock_);
[email protected]f48b9432011-01-11 07:25:401316
1317 if (!HasCookieableScheme(url))
1318 return 0;
1319
[email protected]f48b9432011-01-11 07:25:401320 const std::string host(url.host());
1321
1322 // We store host cookies in the store by their canonical host name;
1323 // domain cookies are stored with a leading ".". So this is a pretty
1324 // simple lookup and per-cookie delete.
1325 int num_deleted = 0;
1326 for (CookieMapItPair its = cookies_.equal_range(GetKey(host));
1327 its.first != its.second;) {
1328 CookieMap::iterator curit = its.first;
1329 ++its.first;
1330
1331 const CanonicalCookie* const cc = curit->second;
1332
1333 // Delete only on a match as a host cookie.
[email protected]d8428d52013-08-07 06:58:251334 if (cc->IsHostCookie() && cc->IsDomainMatch(host) &&
1335 cc->CreationDate() >= delete_begin &&
1336 // The assumption that null |delete_end| is equivalent to
1337 // Time::Max() is confusing.
1338 (delete_end.is_null() || cc->CreationDate() < delete_end)) {
[email protected]f48b9432011-01-11 07:25:401339 num_deleted++;
1340
1341 InternalDeleteCookie(curit, true, DELETE_COOKIE_EXPLICIT);
1342 }
1343 }
1344 return num_deleted;
1345}
1346
[email protected]d8428d52013-08-07 06:58:251347
[email protected]f48b9432011-01-11 07:25:401348bool CookieMonster::DeleteCanonicalCookie(const CanonicalCookie& cookie) {
[email protected]20305ec2011-01-21 04:55:521349 base::AutoLock autolock(lock_);
[email protected]f48b9432011-01-11 07:25:401350
1351 for (CookieMapItPair its = cookies_.equal_range(GetKey(cookie.Domain()));
1352 its.first != its.second; ++its.first) {
1353 // The creation date acts as our unique index...
1354 if (its.first->second->CreationDate() == cookie.CreationDate()) {
1355 InternalDeleteCookie(its.first, true, DELETE_COOKIE_EXPLICIT);
1356 return true;
1357 }
1358 }
initial.commit586acc5fe2008-07-26 22:42:521359 return false;
1360}
1361
[email protected]f48b9432011-01-11 07:25:401362bool CookieMonster::SetCookieWithOptions(const GURL& url,
1363 const std::string& cookie_line,
1364 const CookieOptions& options) {
[email protected]20305ec2011-01-21 04:55:521365 base::AutoLock autolock(lock_);
[email protected]f48b9432011-01-11 07:25:401366
1367 if (!HasCookieableScheme(url)) {
1368 return false;
1369 }
1370
[email protected]f48b9432011-01-11 07:25:401371 return SetCookieWithCreationTimeAndOptions(url, cookie_line, Time(), options);
1372}
1373
1374std::string CookieMonster::GetCookiesWithOptions(const GURL& url,
1375 const CookieOptions& options) {
[email protected]20305ec2011-01-21 04:55:521376 base::AutoLock autolock(lock_);
[email protected]f48b9432011-01-11 07:25:401377
[email protected]34a160d2011-05-12 22:12:491378 if (!HasCookieableScheme(url))
[email protected]f48b9432011-01-11 07:25:401379 return std::string();
[email protected]f48b9432011-01-11 07:25:401380
[email protected]f48b9432011-01-11 07:25:401381 std::vector<CanonicalCookie*> cookies;
1382 FindCookiesForHostAndDomain(url, options, true, &cookies);
1383 std::sort(cookies.begin(), cookies.end(), CookieSorter);
1384
[email protected]34a160d2011-05-12 22:12:491385 std::string cookie_line = BuildCookieLine(cookies);
[email protected]f48b9432011-01-11 07:25:401386
[email protected]f48b9432011-01-11 07:25:401387 VLOG(kVlogGetCookies) << "GetCookies() result: " << cookie_line;
1388
1389 return cookie_line;
1390}
1391
1392void CookieMonster::DeleteCookie(const GURL& url,
1393 const std::string& cookie_name) {
[email protected]20305ec2011-01-21 04:55:521394 base::AutoLock autolock(lock_);
[email protected]f48b9432011-01-11 07:25:401395
1396 if (!HasCookieableScheme(url))
1397 return;
1398
1399 CookieOptions options;
1400 options.set_include_httponly();
mkwst202534e32016-01-15 16:07:151401 options.set_include_first_party_only_cookies();
[email protected]f48b9432011-01-11 07:25:401402 // Get the cookies for this host and its domain(s).
1403 std::vector<CanonicalCookie*> cookies;
1404 FindCookiesForHostAndDomain(url, options, true, &cookies);
1405 std::set<CanonicalCookie*> matching_cookies;
1406
1407 for (std::vector<CanonicalCookie*>::const_iterator it = cookies.begin();
1408 it != cookies.end(); ++it) {
1409 if ((*it)->Name() != cookie_name)
1410 continue;
1411 if (url.path().find((*it)->Path()))
1412 continue;
1413 matching_cookies.insert(*it);
1414 }
1415
1416 for (CookieMap::iterator it = cookies_.begin(); it != cookies_.end();) {
1417 CookieMap::iterator curit = it;
1418 ++it;
1419 if (matching_cookies.find(curit->second) != matching_cookies.end()) {
1420 InternalDeleteCookie(curit, true, DELETE_COOKIE_EXPLICIT);
1421 }
1422 }
1423}
1424
mmenke74bcbd52016-01-21 17:17:561425bool CookieMonster::SetCookieWithCreationTime(const GURL& url,
1426 const std::string& cookie_line,
1427 const base::Time& creation_time) {
1428 DCHECK(!store_.get()) << "This method is only to be used by unit-tests.";
1429 base::AutoLock autolock(lock_);
1430
1431 if (!HasCookieableScheme(url)) {
1432 return false;
1433 }
1434
1435 MarkCookieStoreAsInitialized();
1436 if (ShouldFetchAllCookiesWhenFetchingAnyCookie())
1437 FetchAllCookiesIfNecessary();
1438
1439 return SetCookieWithCreationTimeAndOptions(url, cookie_line, creation_time,
1440 CookieOptions());
1441}
1442
[email protected]264807b2012-04-25 14:49:371443int CookieMonster::DeleteSessionCookies() {
1444 base::AutoLock autolock(lock_);
1445
1446 int num_deleted = 0;
1447 for (CookieMap::iterator it = cookies_.begin(); it != cookies_.end();) {
1448 CookieMap::iterator curit = it;
1449 CanonicalCookie* cc = curit->second;
1450 ++it;
1451
1452 if (!cc->IsPersistent()) {
mkwstbe84af312015-02-20 08:52:451453 InternalDeleteCookie(curit, true, /*sync_to_store*/
[email protected]264807b2012-04-25 14:49:371454 DELETE_COOKIE_EXPIRED);
1455 ++num_deleted;
1456 }
1457 }
1458
1459 return num_deleted;
1460}
1461
erikchen1dd72a72015-05-06 20:45:051462void CookieMonster::MarkCookieStoreAsInitialized() {
1463 initialized_ = true;
1464}
1465
1466void CookieMonster::FetchAllCookiesIfNecessary() {
1467 if (store_.get() && !started_fetching_all_cookies_) {
1468 started_fetching_all_cookies_ = true;
1469 FetchAllCookies();
1470 }
1471}
1472
mmenke74bcbd52016-01-21 17:17:561473void CookieMonster::FetchAllCookies() {
1474 DCHECK(store_.get()) << "Store must exist to initialize";
1475 DCHECK(!finished_fetching_all_cookies_)
1476 << "All cookies have already been fetched.";
1477
1478 // We bind in the current time so that we can report the wall-clock time for
1479 // loading cookies.
1480 store_->Load(base::Bind(&CookieMonster::OnLoaded, this, TimeTicks::Now()));
1481}
1482
erikchen1dd72a72015-05-06 20:45:051483bool CookieMonster::ShouldFetchAllCookiesWhenFetchingAnyCookie() {
1484 if (fetch_strategy_ == kUnknownFetch) {
1485 const std::string group_name =
1486 base::FieldTrialList::FindFullName(kCookieMonsterFetchStrategyName);
1487 if (group_name == kFetchWhenNecessaryName) {
1488 fetch_strategy_ = kFetchWhenNecessary;
1489 } else if (group_name == kAlwaysFetchName) {
1490 fetch_strategy_ = kAlwaysFetch;
1491 } else {
1492 // The logic in the conditional is redundant, but it makes trials of
1493 // the Finch experiment more explicit.
1494 fetch_strategy_ = kAlwaysFetch;
1495 }
1496 }
1497
1498 return fetch_strategy_ == kAlwaysFetch;
1499}
1500
[email protected]218aa6a12011-09-13 17:38:381501void CookieMonster::OnLoaded(TimeTicks beginning_time,
1502 const std::vector<CanonicalCookie*>& cookies) {
1503 StoreLoadedCookies(cookies);
[email protected]c7593fb22011-11-14 23:54:271504 histogram_time_blocked_on_load_->AddTime(TimeTicks::Now() - beginning_time);
[email protected]218aa6a12011-09-13 17:38:381505
1506 // Invoke the task queue of cookie request.
1507 InvokeQueue();
1508}
1509
[email protected]8562034e2011-10-17 17:35:041510void CookieMonster::OnKeyLoaded(const std::string& key,
1511 const std::vector<CanonicalCookie*>& cookies) {
1512 // This function does its own separate locking.
1513 StoreLoadedCookies(cookies);
1514
mkwstbe84af312015-02-20 08:52:451515 std::deque<scoped_refptr<CookieMonsterTask>> tasks_pending_for_key;
[email protected]8562034e2011-10-17 17:35:041516
[email protected]bab72ec2013-10-30 20:50:021517 // We need to do this repeatedly until no more tasks were added to the queue
1518 // during the period where we release the lock.
1519 while (true) {
1520 {
1521 base::AutoLock autolock(lock_);
mkwstbe84af312015-02-20 08:52:451522 std::map<std::string,
1523 std::deque<scoped_refptr<CookieMonsterTask>>>::iterator it =
1524 tasks_pending_for_key_.find(key);
[email protected]bab72ec2013-10-30 20:50:021525 if (it == tasks_pending_for_key_.end()) {
1526 keys_loaded_.insert(key);
1527 return;
1528 }
1529 if (it->second.empty()) {
1530 keys_loaded_.insert(key);
1531 tasks_pending_for_key_.erase(it);
1532 return;
1533 }
1534 it->second.swap(tasks_pending_for_key);
1535 }
1536
1537 while (!tasks_pending_for_key.empty()) {
1538 scoped_refptr<CookieMonsterTask> task = tasks_pending_for_key.front();
1539 task->Run();
1540 tasks_pending_for_key.pop_front();
1541 }
[email protected]8562034e2011-10-17 17:35:041542 }
1543}
1544
[email protected]218aa6a12011-09-13 17:38:381545void CookieMonster::StoreLoadedCookies(
1546 const std::vector<CanonicalCookie*>& cookies) {
pkastingec2cdb52015-05-02 01:19:341547 // TODO(erikwright): Remove ScopedTracker below once crbug.com/457528 is
1548 // fixed.
1549 tracked_objects::ScopedTracker tracking_profile(
1550 FROM_HERE_WITH_EXPLICIT_FUNCTION(
1551 "457528 CookieMonster::StoreLoadedCookies"));
1552
[email protected]f48b9432011-01-11 07:25:401553 // Initialize the store and sync in any saved persistent cookies. We don't
1554 // care if it's expired, insert it so it can be garbage collected, removed,
1555 // and sync'd.
[email protected]218aa6a12011-09-13 17:38:381556 base::AutoLock autolock(lock_);
[email protected]f48b9432011-01-11 07:25:401557
[email protected]6210ce52013-09-20 03:33:141558 CookieItVector cookies_with_control_chars;
1559
[email protected]f48b9432011-01-11 07:25:401560 for (std::vector<CanonicalCookie*>::const_iterator it = cookies.begin();
1561 it != cookies.end(); ++it) {
Avi Drissman13fc8932015-12-20 04:40:461562 int64_t cookie_creation_time = (*it)->CreationDate().ToInternalValue();
[email protected]f48b9432011-01-11 07:25:401563
[email protected]8562034e2011-10-17 17:35:041564 if (creation_times_.insert(cookie_creation_time).second) {
[email protected]6210ce52013-09-20 03:33:141565 CookieMap::iterator inserted =
1566 InternalInsertCookie(GetKey((*it)->Domain()), *it, false);
[email protected]f48b9432011-01-11 07:25:401567 const Time cookie_access_time((*it)->LastAccessDate());
[email protected]8562034e2011-10-17 17:35:041568 if (earliest_access_time_.is_null() ||
1569 cookie_access_time < earliest_access_time_)
1570 earliest_access_time_ = cookie_access_time;
[email protected]6210ce52013-09-20 03:33:141571
1572 if (ContainsControlCharacter((*it)->Name()) ||
1573 ContainsControlCharacter((*it)->Value())) {
mkwstbe84af312015-02-20 08:52:451574 cookies_with_control_chars.push_back(inserted);
[email protected]6210ce52013-09-20 03:33:141575 }
[email protected]f48b9432011-01-11 07:25:401576 } else {
mkwstbe84af312015-02-20 08:52:451577 LOG(ERROR) << base::StringPrintf(
1578 "Found cookies with duplicate creation "
1579 "times in backing store: "
1580 "{name='%s', domain='%s', path='%s'}",
1581 (*it)->Name().c_str(), (*it)->Domain().c_str(),
1582 (*it)->Path().c_str());
[email protected]f48b9432011-01-11 07:25:401583 // We've been given ownership of the cookie and are throwing it
1584 // away; reclaim the space.
1585 delete (*it);
1586 }
1587 }
[email protected]f48b9432011-01-11 07:25:401588
[email protected]6210ce52013-09-20 03:33:141589 // Any cookies that contain control characters that we have loaded from the
1590 // persistent store should be deleted. See http://crbug.com/238041.
1591 for (CookieItVector::iterator it = cookies_with_control_chars.begin();
1592 it != cookies_with_control_chars.end();) {
1593 CookieItVector::iterator curit = it;
1594 ++it;
1595
1596 InternalDeleteCookie(*curit, true, DELETE_COOKIE_CONTROL_CHAR);
1597 }
1598
[email protected]f48b9432011-01-11 07:25:401599 // After importing cookies from the PersistentCookieStore, verify that
1600 // none of our other constraints are violated.
[email protected]f48b9432011-01-11 07:25:401601 // In particular, the backing store might have given us duplicate cookies.
[email protected]8562034e2011-10-17 17:35:041602
1603 // This method could be called multiple times due to priority loading, thus
1604 // cookies loaded in previous runs will be validated again, but this is OK
1605 // since they are expected to be much fewer than total DB.
[email protected]f48b9432011-01-11 07:25:401606 EnsureCookiesMapIsValid();
[email protected]218aa6a12011-09-13 17:38:381607}
[email protected]f48b9432011-01-11 07:25:401608
[email protected]218aa6a12011-09-13 17:38:381609void CookieMonster::InvokeQueue() {
1610 while (true) {
1611 scoped_refptr<CookieMonsterTask> request_task;
1612 {
1613 base::AutoLock autolock(lock_);
[email protected]0184df32013-05-14 00:53:551614 if (tasks_pending_.empty()) {
erikchen1dd72a72015-05-06 20:45:051615 finished_fetching_all_cookies_ = true;
[email protected]8562034e2011-10-17 17:35:041616 creation_times_.clear();
1617 keys_loaded_.clear();
[email protected]218aa6a12011-09-13 17:38:381618 break;
1619 }
[email protected]0184df32013-05-14 00:53:551620 request_task = tasks_pending_.front();
1621 tasks_pending_.pop();
[email protected]218aa6a12011-09-13 17:38:381622 }
1623 request_task->Run();
1624 }
[email protected]f48b9432011-01-11 07:25:401625}
1626
1627void CookieMonster::EnsureCookiesMapIsValid() {
1628 lock_.AssertAcquired();
1629
[email protected]f48b9432011-01-11 07:25:401630 // Iterate through all the of the cookies, grouped by host.
1631 CookieMap::iterator prev_range_end = cookies_.begin();
1632 while (prev_range_end != cookies_.end()) {
1633 CookieMap::iterator cur_range_begin = prev_range_end;
1634 const std::string key = cur_range_begin->first; // Keep a copy.
1635 CookieMap::iterator cur_range_end = cookies_.upper_bound(key);
1636 prev_range_end = cur_range_end;
1637
1638 // Ensure no equivalent cookies for this host.
ellyjonescabf57422015-08-21 18:44:511639 TrimDuplicateCookiesForKey(key, cur_range_begin, cur_range_end);
[email protected]f48b9432011-01-11 07:25:401640 }
[email protected]f48b9432011-01-11 07:25:401641}
1642
ellyjonescabf57422015-08-21 18:44:511643void CookieMonster::TrimDuplicateCookiesForKey(const std::string& key,
1644 CookieMap::iterator begin,
1645 CookieMap::iterator end) {
[email protected]f48b9432011-01-11 07:25:401646 lock_.AssertAcquired();
1647
1648 // Set of cookies ordered by creation time.
1649 typedef std::set<CookieMap::iterator, OrderByCreationTimeDesc> CookieSet;
1650
1651 // Helper map we populate to find the duplicates.
1652 typedef std::map<CookieSignature, CookieSet> EquivalenceMap;
1653 EquivalenceMap equivalent_cookies;
1654
1655 // The number of duplicate cookies that have been found.
1656 int num_duplicates = 0;
1657
1658 // Iterate through all of the cookies in our range, and insert them into
1659 // the equivalence map.
1660 for (CookieMap::iterator it = begin; it != end; ++it) {
1661 DCHECK_EQ(key, it->first);
1662 CanonicalCookie* cookie = it->second;
1663
mkwstbe84af312015-02-20 08:52:451664 CookieSignature signature(cookie->Name(), cookie->Domain(), cookie->Path());
[email protected]f48b9432011-01-11 07:25:401665 CookieSet& set = equivalent_cookies[signature];
1666
1667 // We found a duplicate!
1668 if (!set.empty())
1669 num_duplicates++;
1670
1671 // We save the iterator into |cookies_| rather than the actual cookie
1672 // pointer, since we may need to delete it later.
1673 bool insert_success = set.insert(it).second;
mkwstbe84af312015-02-20 08:52:451674 DCHECK(insert_success)
1675 << "Duplicate creation times found in duplicate cookie name scan.";
[email protected]f48b9432011-01-11 07:25:401676 }
1677
1678 // If there were no duplicates, we are done!
1679 if (num_duplicates == 0)
ellyjonescabf57422015-08-21 18:44:511680 return;
[email protected]f48b9432011-01-11 07:25:401681
1682 // Make sure we find everything below that we did above.
1683 int num_duplicates_found = 0;
1684
1685 // Otherwise, delete all the duplicate cookies, both from our in-memory store
1686 // and from the backing store.
1687 for (EquivalenceMap::iterator it = equivalent_cookies.begin();
mkwstbe84af312015-02-20 08:52:451688 it != equivalent_cookies.end(); ++it) {
[email protected]f48b9432011-01-11 07:25:401689 const CookieSignature& signature = it->first;
1690 CookieSet& dupes = it->second;
1691
1692 if (dupes.size() <= 1)
1693 continue; // This cookiename/path has no duplicates.
1694 num_duplicates_found += dupes.size() - 1;
1695
1696 // Since |dups| is sorted by creation time (descending), the first cookie
1697 // is the most recent one, so we will keep it. The rest are duplicates.
1698 dupes.erase(dupes.begin());
1699
1700 LOG(ERROR) << base::StringPrintf(
1701 "Found %d duplicate cookies for host='%s', "
1702 "with {name='%s', domain='%s', path='%s'}",
mkwstbe84af312015-02-20 08:52:451703 static_cast<int>(dupes.size()), key.c_str(), signature.name.c_str(),
1704 signature.domain.c_str(), signature.path.c_str());
[email protected]f48b9432011-01-11 07:25:401705
1706 // Remove all the cookies identified by |dupes|. It is valid to delete our
1707 // list of iterators one at a time, since |cookies_| is a multimap (they
1708 // don't invalidate existing iterators following deletion).
mkwstbe84af312015-02-20 08:52:451709 for (CookieSet::iterator dupes_it = dupes.begin(); dupes_it != dupes.end();
[email protected]f48b9432011-01-11 07:25:401710 ++dupes_it) {
[email protected]218aa6a12011-09-13 17:38:381711 InternalDeleteCookie(*dupes_it, true,
[email protected]f48b9432011-01-11 07:25:401712 DELETE_COOKIE_DUPLICATE_IN_BACKING_STORE);
1713 }
1714 }
1715 DCHECK_EQ(num_duplicates, num_duplicates_found);
[email protected]f48b9432011-01-11 07:25:401716}
1717
1718void CookieMonster::SetDefaultCookieableSchemes() {
[email protected]7c4b66b2014-01-04 12:28:131719 // Always disable file scheme unless SetEnableFileScheme(true) is called.
1720 SetCookieableSchemes(kDefaultCookieableSchemes,
1721 kDefaultCookieableSchemesCount - 1);
[email protected]f48b9432011-01-11 07:25:401722}
1723
[email protected]f48b9432011-01-11 07:25:401724void CookieMonster::FindCookiesForHostAndDomain(
1725 const GURL& url,
1726 const CookieOptions& options,
1727 bool update_access_time,
1728 std::vector<CanonicalCookie*>* cookies) {
1729 lock_.AssertAcquired();
1730
1731 const Time current_time(CurrentTime());
1732
1733 // Probe to save statistics relatively frequently. We do it here rather
1734 // than in the set path as many websites won't set cookies, and we
1735 // want to collect statistics whenever the browser's being used.
1736 RecordPeriodicStats(current_time);
1737
[email protected]8e1583672012-02-11 04:39:411738 // Can just dispatch to FindCookiesForKey
1739 const std::string key(GetKey(url.host()));
mkwstbe84af312015-02-20 08:52:451740 FindCookiesForKey(key, url, options, current_time, update_access_time,
1741 cookies);
[email protected]f48b9432011-01-11 07:25:401742}
1743
[email protected]dedec0b2013-02-28 04:50:101744void CookieMonster::FindCookiesForKey(const std::string& key,
1745 const GURL& url,
1746 const CookieOptions& options,
1747 const Time& current,
1748 bool update_access_time,
1749 std::vector<CanonicalCookie*>* cookies) {
[email protected]f48b9432011-01-11 07:25:401750 lock_.AssertAcquired();
1751
[email protected]f48b9432011-01-11 07:25:401752 for (CookieMapItPair its = cookies_.equal_range(key);
mkwstbe84af312015-02-20 08:52:451753 its.first != its.second;) {
[email protected]f48b9432011-01-11 07:25:401754 CookieMap::iterator curit = its.first;
1755 CanonicalCookie* cc = curit->second;
1756 ++its.first;
1757
1758 // If the cookie is expired, delete it.
[email protected]ba4ad0e2011-03-15 08:12:471759 if (cc->IsExpired(current) && !keep_expired_cookies_) {
[email protected]f48b9432011-01-11 07:25:401760 InternalDeleteCookie(curit, true, DELETE_COOKIE_EXPIRED);
1761 continue;
1762 }
1763
[email protected]65f4e7e2012-12-12 21:56:541764 // Filter out cookies that should not be included for a request to the
1765 // given |url|. HTTP only cookies are filtered depending on the passed
1766 // cookie |options|.
1767 if (!cc->IncludeForRequestURL(url, options))
[email protected]f48b9432011-01-11 07:25:401768 continue;
1769
[email protected]65f4e7e2012-12-12 21:56:541770 // Add this cookie to the set of matching cookies. Update the access
[email protected]f48b9432011-01-11 07:25:401771 // time if we've been requested to do so.
1772 if (update_access_time) {
1773 InternalUpdateCookieAccessTime(cc, current);
1774 }
1775 cookies->push_back(cc);
1776 }
1777}
1778
1779bool CookieMonster::DeleteAnyEquivalentCookie(const std::string& key,
1780 const CanonicalCookie& ecc,
[email protected]e7c590e52011-03-30 08:33:551781 bool skip_httponly,
jww601411a2015-11-20 19:46:571782 bool already_expired,
1783 bool enforce_strict_secure) {
[email protected]f48b9432011-01-11 07:25:401784 lock_.AssertAcquired();
1785
1786 bool found_equivalent_cookie = false;
1787 bool skipped_httponly = false;
jww601411a2015-11-20 19:46:571788 bool skipped_secure_cookie = false;
jww31e32632015-12-16 23:38:341789
1790 histogram_cookie_delete_equivalent_->Add(COOKIE_DELETE_EQUIVALENT_ATTEMPT);
1791
[email protected]f48b9432011-01-11 07:25:401792 for (CookieMapItPair its = cookies_.equal_range(key);
mkwstbe84af312015-02-20 08:52:451793 its.first != its.second;) {
[email protected]f48b9432011-01-11 07:25:401794 CookieMap::iterator curit = its.first;
1795 CanonicalCookie* cc = curit->second;
1796 ++its.first;
1797
jww601411a2015-11-20 19:46:571798 // If strict secure cookies is being enforced, then the equivalency
1799 // requirements are looser. If the cookie is being set from an insecure
1800 // scheme, then if a cookie already exists with the same name and it is
1801 // Secure, then the cookie should *not* be updated if they domain-match and
1802 // ignoring the path attribute.
1803 //
1804 // See: https://tools.ietf.org/html/draft-west-leave-secure-cookies-alone
1805 if (enforce_strict_secure && !ecc.Source().SchemeIsCryptographic() &&
1806 ecc.IsEquivalentForSecureCookieMatching(*cc) && cc->IsSecure()) {
1807 skipped_secure_cookie = true;
jww31e32632015-12-16 23:38:341808 histogram_cookie_delete_equivalent_->Add(
1809 COOKIE_DELETE_EQUIVALENT_SKIPPING_SECURE);
1810 // If the cookie is equivalent to the new cookie and wouldn't have been
1811 // skipped for being HTTP-only, record that it is a skipped secure cookie
1812 // that would have been deleted otherwise.
1813 if (ecc.IsEquivalent(*cc)) {
jwwa9a0d482015-12-16 18:19:411814 found_equivalent_cookie = true;
jww31e32632015-12-16 23:38:341815
1816 if (!skip_httponly || !cc->IsHttpOnly()) {
1817 histogram_cookie_delete_equivalent_->Add(
1818 COOKIE_DELETE_EQUIVALENT_WOULD_HAVE_DELETED);
1819 }
1820 }
jww601411a2015-11-20 19:46:571821 } else if (ecc.IsEquivalent(*cc)) {
[email protected]f48b9432011-01-11 07:25:401822 // We should never have more than one equivalent cookie, since they should
jww601411a2015-11-20 19:46:571823 // overwrite each other, unless secure cookies require secure scheme is
1824 // being enforced. In that case, cookies with different paths might exist
1825 // and be considered equivalent.
mkwstbe84af312015-02-20 08:52:451826 CHECK(!found_equivalent_cookie)
1827 << "Duplicate equivalent cookies found, cookie store is corrupted.";
[email protected]f48b9432011-01-11 07:25:401828 if (skip_httponly && cc->IsHttpOnly()) {
1829 skipped_httponly = true;
1830 } else {
jww31e32632015-12-16 23:38:341831 histogram_cookie_delete_equivalent_->Add(
1832 COOKIE_DELETE_EQUIVALENT_FOUND);
mkwstbe84af312015-02-20 08:52:451833 InternalDeleteCookie(curit, true, already_expired
1834 ? DELETE_COOKIE_EXPIRED_OVERWRITE
1835 : DELETE_COOKIE_OVERWRITE);
[email protected]f48b9432011-01-11 07:25:401836 }
1837 found_equivalent_cookie = true;
1838 }
1839 }
jww601411a2015-11-20 19:46:571840 return skipped_httponly || skipped_secure_cookie;
[email protected]f48b9432011-01-11 07:25:401841}
1842
[email protected]6210ce52013-09-20 03:33:141843CookieMonster::CookieMap::iterator CookieMonster::InternalInsertCookie(
1844 const std::string& key,
1845 CanonicalCookie* cc,
1846 bool sync_to_store) {
pkastinga9269aa42015-04-10 01:42:261847 // TODO(mkwst): Remove ScopedTracker below once crbug.com/456373 is fixed.
pkasting58e029b2015-02-21 05:17:281848 tracked_objects::ScopedTracker tracking_profile(
1849 FROM_HERE_WITH_EXPLICIT_FUNCTION(
1850 "456373 CookieMonster::InternalInsertCookie"));
[email protected]f48b9432011-01-11 07:25:401851 lock_.AssertAcquired();
1852
[email protected]90499482013-06-01 00:39:501853 if ((cc->IsPersistent() || persist_session_cookies_) && store_.get() &&
1854 sync_to_store)
[email protected]f48b9432011-01-11 07:25:401855 store_->AddCookie(*cc);
[email protected]6210ce52013-09-20 03:33:141856 CookieMap::iterator inserted =
1857 cookies_.insert(CookieMap::value_type(key, cc));
[email protected]8bb846f2011-03-23 12:08:181858 if (delegate_.get()) {
mkwstbe84af312015-02-20 08:52:451859 delegate_->OnCookieChanged(*cc, false,
1860 CookieMonsterDelegate::CHANGE_COOKIE_EXPLICIT);
[email protected]8bb846f2011-03-23 12:08:181861 }
mkwstc1aa4cc2015-04-03 19:57:451862
1863 // See InitializeHistograms() for details.
estark7feb65c2b2015-08-21 23:38:201864 int32_t cookie_type_sample =
1865 cc->IsFirstPartyOnly() ? 1 << COOKIE_TYPE_FIRSTPARTYONLY : 0;
1866 cookie_type_sample |= cc->IsHttpOnly() ? 1 << COOKIE_TYPE_HTTPONLY : 0;
1867 cookie_type_sample |= cc->IsSecure() ? 1 << COOKIE_TYPE_SECURE : 0;
1868 histogram_cookie_type_->Add(cookie_type_sample);
1869
1870 // Histogram the type of scheme used on URLs that set cookies. This
1871 // intentionally includes cookies that are set or overwritten by
1872 // http:// URLs, but not cookies that are cleared by http:// URLs, to
1873 // understand if the former behavior can be deprecated for Secure
1874 // cookies.
1875 if (!cc->Source().is_empty()) {
1876 CookieSource cookie_source_sample;
1877 if (cc->Source().SchemeIsCryptographic()) {
1878 cookie_source_sample =
1879 cc->IsSecure() ? COOKIE_SOURCE_SECURE_COOKIE_CRYPTOGRAPHIC_SCHEME
1880 : COOKIE_SOURCE_NONSECURE_COOKIE_CRYPTOGRAPHIC_SCHEME;
1881 } else {
1882 cookie_source_sample =
1883 cc->IsSecure()
1884 ? COOKIE_SOURCE_SECURE_COOKIE_NONCRYPTOGRAPHIC_SCHEME
1885 : COOKIE_SOURCE_NONSECURE_COOKIE_NONCRYPTOGRAPHIC_SCHEME;
1886 }
1887 histogram_cookie_source_scheme_->Add(cookie_source_sample);
1888 }
mkwstc1aa4cc2015-04-03 19:57:451889
msarda0aad8f02014-10-30 09:22:391890 RunCallbacks(*cc, false);
[email protected]6210ce52013-09-20 03:33:141891
1892 return inserted;
[email protected]f48b9432011-01-11 07:25:401893}
1894
[email protected]34602282010-02-03 22:14:151895bool CookieMonster::SetCookieWithCreationTimeAndOptions(
1896 const GURL& url,
1897 const std::string& cookie_line,
1898 const Time& creation_time_or_null,
1899 const CookieOptions& options) {
[email protected]b866a02d2010-07-28 16:41:041900 lock_.AssertAcquired();
initial.commit586acc5fe2008-07-26 22:42:521901
[email protected]4d3ce782010-10-29 18:31:281902 VLOG(kVlogSetCookies) << "SetCookie() line: " << cookie_line;
initial.commit586acc5fe2008-07-26 22:42:521903
[email protected]34602282010-02-03 22:14:151904 Time creation_time = creation_time_or_null;
1905 if (creation_time.is_null()) {
1906 creation_time = CurrentTime();
1907 last_time_seen_ = creation_time;
1908 }
1909
[email protected]abbd13b2012-11-15 17:54:201910 scoped_ptr<CanonicalCookie> cc(
1911 CanonicalCookie::Create(url, cookie_line, creation_time, options));
initial.commit586acc5fe2008-07-26 22:42:521912
1913 if (!cc.get()) {
[email protected]4d3ce782010-10-29 18:31:281914 VLOG(kVlogSetCookies) << "WARNING: Failed to allocate CanonicalCookie";
initial.commit586acc5fe2008-07-26 22:42:521915 return false;
1916 }
[email protected]fa77eb512010-07-22 16:12:511917 return SetCanonicalCookie(&cc, creation_time, options);
[email protected]f325f1e12010-04-30 22:38:551918}
initial.commit586acc5fe2008-07-26 22:42:521919
[email protected]f325f1e12010-04-30 22:38:551920bool CookieMonster::SetCanonicalCookie(scoped_ptr<CanonicalCookie>* cc,
[email protected]f325f1e12010-04-30 22:38:551921 const Time& creation_time,
1922 const CookieOptions& options) {
[email protected]7a964a72010-09-07 19:33:261923 const std::string key(GetKey((*cc)->Domain()));
[email protected]e7c590e52011-03-30 08:33:551924 bool already_expired = (*cc)->IsExpired(creation_time);
ellyjones399e35a22014-10-27 11:09:561925
[email protected]e7c590e52011-03-30 08:33:551926 if (DeleteAnyEquivalentCookie(key, **cc, options.exclude_httponly(),
jww601411a2015-11-20 19:46:571927 already_expired,
1928 options.enforce_strict_secure())) {
1929 std::string error;
1930 if (options.enforce_strict_secure()) {
1931 error =
1932 "SetCookie() not clobbering httponly cookie or secure cookie for "
1933 "insecure scheme";
1934 } else {
1935 error = "SetCookie() not clobbering httponly cookie";
1936 }
1937
1938 VLOG(kVlogSetCookies) << error;
[email protected]3a96c742008-11-19 19:46:271939 return false;
1940 }
initial.commit586acc5fe2008-07-26 22:42:521941
mkwstbe84af312015-02-20 08:52:451942 VLOG(kVlogSetCookies) << "SetCookie() key: " << key
1943 << " cc: " << (*cc)->DebugString();
initial.commit586acc5fe2008-07-26 22:42:521944
1945 // Realize that we might be setting an expired cookie, and the only point
1946 // was to delete the cookie which we've already done.
[email protected]e7c590e52011-03-30 08:33:551947 if (!already_expired || keep_expired_cookies_) {
[email protected]374f58b2010-07-20 15:29:261948 // See InitializeHistograms() for details.
[email protected]10b691f2012-07-11 15:22:151949 if ((*cc)->IsPersistent()) {
[email protected]8475bee2011-03-17 18:40:241950 histogram_expiration_duration_minutes_->Add(
1951 ((*cc)->ExpiryDate() - creation_time).InMinutes());
1952 }
1953
ellyjones399e35a22014-10-27 11:09:561954 {
1955 CanonicalCookie cookie = *(cc->get());
1956 InternalInsertCookie(key, cc->release(), true);
ellyjones399e35a22014-10-27 11:09:561957 }
[email protected]348dd662013-03-13 20:25:071958 } else {
1959 VLOG(kVlogSetCookies) << "SetCookie() not storing already expired cookie.";
[email protected]c4058fb2010-06-22 17:25:261960 }
initial.commit586acc5fe2008-07-26 22:42:521961
1962 // We assume that hopefully setting a cookie will be less common than
1963 // querying a cookie. Since setting a cookie can put us over our limits,
1964 // make sure that we garbage collect... We can also make the assumption that
1965 // if a cookie was set, in the common case it will be used soon after,
1966 // and we will purge the expired cookies in GetCookies().
jww82d99c12015-11-25 18:39:531967 GarbageCollect(creation_time, key, options.enforce_strict_secure());
initial.commit586acc5fe2008-07-26 22:42:521968
1969 return true;
1970}
1971
drogerd5d1278c2015-03-17 19:21:511972bool CookieMonster::SetCanonicalCookies(const CookieList& list) {
1973 base::AutoLock autolock(lock_);
1974
ttuttle859dc7a2015-04-23 19:42:291975 CookieOptions options;
drogerd5d1278c2015-03-17 19:21:511976 options.set_include_httponly();
1977
1978 for (CookieList::const_iterator it = list.begin(); it != list.end(); ++it) {
1979 scoped_ptr<CanonicalCookie> canonical_cookie(new CanonicalCookie(*it));
1980 if (!SetCanonicalCookie(&canonical_cookie, it->CreationDate(), options))
1981 return false;
1982 }
1983
1984 return true;
1985}
1986
[email protected]7a964a72010-09-07 19:33:261987void CookieMonster::InternalUpdateCookieAccessTime(CanonicalCookie* cc,
1988 const Time& current) {
[email protected]bb8905722010-05-21 17:29:041989 lock_.AssertAcquired();
1990
[email protected]77e0a462008-11-01 00:43:351991 // Based off the Mozilla code. When a cookie has been accessed recently,
1992 // don't bother updating its access time again. This reduces the number of
1993 // updates we do during pageload, which in turn reduces the chance our storage
1994 // backend will hit its batch thresholds and be forced to update.
[email protected]77e0a462008-11-01 00:43:351995 if ((current - cc->LastAccessDate()) < last_access_threshold_)
1996 return;
1997
1998 cc->SetLastAccessDate(current);
[email protected]90499482013-06-01 00:39:501999 if ((cc->IsPersistent() || persist_session_cookies_) && store_.get())
[email protected]77e0a462008-11-01 00:43:352000 store_->UpdateCookieAccessTime(*cc);
2001}
2002
[email protected]6210ce52013-09-20 03:33:142003// InternalDeleteCookies must not invalidate iterators other than the one being
2004// deleted.
initial.commit586acc5fe2008-07-26 22:42:522005void CookieMonster::InternalDeleteCookie(CookieMap::iterator it,
[email protected]c4058fb2010-06-22 17:25:262006 bool sync_to_store,
2007 DeletionCause deletion_cause) {
[email protected]bb8905722010-05-21 17:29:042008 lock_.AssertAcquired();
2009
[email protected]8bb846f2011-03-23 12:08:182010 // Ideally, this would be asserted up where we define ChangeCauseMapping,
2011 // but DeletionCause's visibility (or lack thereof) forces us to make
2012 // this check here.
mostynb91e0da982015-01-20 19:17:272013 static_assert(arraysize(ChangeCauseMapping) == DELETE_COOKIE_LAST_ENTRY + 1,
2014 "ChangeCauseMapping size should match DeletionCause size");
[email protected]8bb846f2011-03-23 12:08:182015
[email protected]374f58b2010-07-20 15:29:262016 // See InitializeHistograms() for details.
[email protected]7a964a72010-09-07 19:33:262017 if (deletion_cause != DELETE_COOKIE_DONT_RECORD)
2018 histogram_cookie_deletion_cause_->Add(deletion_cause);
[email protected]c4058fb2010-06-22 17:25:262019
initial.commit586acc5fe2008-07-26 22:42:522020 CanonicalCookie* cc = it->second;
xiyuan8dbb89892015-04-13 17:04:302021 VLOG(kVlogSetCookies) << "InternalDeleteCookie()"
2022 << ", cause:" << deletion_cause
2023 << ", cc: " << cc->DebugString();
[email protected]7a964a72010-09-07 19:33:262024
[email protected]90499482013-06-01 00:39:502025 if ((cc->IsPersistent() || persist_session_cookies_) && store_.get() &&
2026 sync_to_store)
initial.commit586acc5fe2008-07-26 22:42:522027 store_->DeleteCookie(*cc);
[email protected]8bb846f2011-03-23 12:08:182028 if (delegate_.get()) {
2029 ChangeCausePair mapping = ChangeCauseMapping[deletion_cause];
2030
2031 if (mapping.notify)
2032 delegate_->OnCookieChanged(*cc, true, mapping.cause);
2033 }
msarda0aad8f02014-10-30 09:22:392034 RunCallbacks(*cc, true);
initial.commit586acc5fe2008-07-26 22:42:522035 cookies_.erase(it);
2036 delete cc;
2037}
2038
[email protected]8807b322010-10-01 17:10:142039// Domain expiry behavior is unchanged by key/expiry scheme (the
[email protected]8ad5d462013-05-02 08:45:262040// meaning of the key is different, but that's not visible to this routine).
jww82d99c12015-11-25 18:39:532041size_t CookieMonster::GarbageCollect(const Time& current,
2042 const std::string& key,
2043 bool enforce_strict_secure) {
[email protected]bb8905722010-05-21 17:29:042044 lock_.AssertAcquired();
2045
jww82d99c12015-11-25 18:39:532046 size_t num_deleted = 0;
mkwstbe84af312015-02-20 08:52:452047 Time safe_date(Time::Now() - TimeDelta::FromDays(kSafeFromGlobalPurgeDays));
initial.commit586acc5fe2008-07-26 22:42:522048
[email protected]8ad5d462013-05-02 08:45:262049 // Collect garbage for this key, minding cookie priorities.
[email protected]7a964a72010-09-07 19:33:262050 if (cookies_.count(key) > kDomainMaxCookies) {
[email protected]4d3ce782010-10-29 18:31:282051 VLOG(kVlogGarbageCollection) << "GarbageCollect() key: " << key;
[email protected]7a964a72010-09-07 19:33:262052
jww82d99c12015-11-25 18:39:532053 CookieItVector* cookie_its;
jww601411a2015-11-20 19:46:572054
jww82d99c12015-11-25 18:39:532055 CookieItVector non_expired_cookie_its;
2056 cookie_its = &non_expired_cookie_its;
2057 num_deleted +=
2058 GarbageCollectExpired(current, cookies_.equal_range(key), cookie_its);
2059
2060 CookieItVector secure_cookie_its;
2061 if (enforce_strict_secure && cookie_its->size() > kDomainMaxCookies) {
2062 VLOG(kVlogGarbageCollection) << "Garbage collecting non-Secure cookies.";
2063 num_deleted +=
2064 GarbageCollectNonSecure(non_expired_cookie_its, &secure_cookie_its);
2065 cookie_its = &secure_cookie_its;
2066 }
2067
2068 if (cookie_its->size() > kDomainMaxCookies) {
[email protected]8ad5d462013-05-02 08:45:262069 VLOG(kVlogGarbageCollection) << "Deep Garbage Collect domain.";
2070 size_t purge_goal =
jww82d99c12015-11-25 18:39:532071 cookie_its->size() - (kDomainMaxCookies - kDomainPurgeCookies);
[email protected]8ad5d462013-05-02 08:45:262072 DCHECK(purge_goal > kDomainPurgeCookies);
2073
2074 // Boundary iterators into |cookie_its| for different priorities.
2075 CookieItVector::iterator it_bdd[4];
2076 // Intialize |it_bdd| while sorting |cookie_its| by priorities.
2077 // Schematic: [MLLHMHHLMM] => [LLL|MMMM|HHH], with 4 boundaries.
jww82d99c12015-11-25 18:39:532078 it_bdd[0] = cookie_its->begin();
2079 it_bdd[3] = cookie_its->end();
mkwstbe84af312015-02-20 08:52:452080 it_bdd[1] =
2081 PartitionCookieByPriority(it_bdd[0], it_bdd[3], COOKIE_PRIORITY_LOW);
[email protected]8ad5d462013-05-02 08:45:262082 it_bdd[2] = PartitionCookieByPriority(it_bdd[1], it_bdd[3],
2083 COOKIE_PRIORITY_MEDIUM);
mkwstbe84af312015-02-20 08:52:452084 size_t quota[3] = {kDomainCookiesQuotaLow,
2085 kDomainCookiesQuotaMedium,
2086 kDomainCookiesQuotaHigh};
[email protected]8ad5d462013-05-02 08:45:262087
2088 // Purge domain cookies in 3 rounds.
2089 // Round 1: consider low-priority cookies only: evict least-recently
2090 // accessed, while protecting quota[0] of these from deletion.
2091 // Round 2: consider {low, medium}-priority cookies, evict least-recently
2092 // accessed, while protecting quota[0] + quota[1].
2093 // Round 3: consider all cookies, evict least-recently accessed.
2094 size_t accumulated_quota = 0;
2095 CookieItVector::iterator it_purge_begin = it_bdd[0];
2096 for (int i = 0; i < 3 && purge_goal > 0; ++i) {
2097 accumulated_quota += quota[i];
2098
[email protected]8ad5d462013-05-02 08:45:262099 size_t num_considered = it_bdd[i + 1] - it_purge_begin;
2100 if (num_considered <= accumulated_quota)
2101 continue;
2102
2103 // Number of cookies that will be purged in this round.
2104 size_t round_goal =
2105 std::min(purge_goal, num_considered - accumulated_quota);
2106 purge_goal -= round_goal;
2107
2108 SortLeastRecentlyAccessed(it_purge_begin, it_bdd[i + 1], round_goal);
2109 // Cookies accessed on or after |safe_date| would have been safe from
2110 // global purge, and we want to keep track of this.
2111 CookieItVector::iterator it_purge_end = it_purge_begin + round_goal;
2112 CookieItVector::iterator it_purge_middle =
2113 LowerBoundAccessDate(it_purge_begin, it_purge_end, safe_date);
2114 // Delete cookies accessed before |safe_date|.
2115 num_deleted += GarbageCollectDeleteRange(
mkwstbe84af312015-02-20 08:52:452116 current, DELETE_COOKIE_EVICTED_DOMAIN_PRE_SAFE, it_purge_begin,
[email protected]8ad5d462013-05-02 08:45:262117 it_purge_middle);
2118 // Delete cookies accessed on or after |safe_date|.
2119 num_deleted += GarbageCollectDeleteRange(
mkwstbe84af312015-02-20 08:52:452120 current, DELETE_COOKIE_EVICTED_DOMAIN_POST_SAFE, it_purge_middle,
[email protected]8ad5d462013-05-02 08:45:262121 it_purge_end);
2122 it_purge_begin = it_purge_end;
2123 }
2124 DCHECK_EQ(0U, purge_goal);
[email protected]8807b322010-10-01 17:10:142125 }
initial.commit586acc5fe2008-07-26 22:42:522126 }
2127
[email protected]8ad5d462013-05-02 08:45:262128 // Collect garbage for everything. With firefox style we want to preserve
2129 // cookies accessed in kSafeFromGlobalPurgeDays, otherwise evict.
mkwstbe84af312015-02-20 08:52:452130 if (cookies_.size() > kMaxCookies && earliest_access_time_ < safe_date) {
[email protected]4d3ce782010-10-29 18:31:282131 VLOG(kVlogGarbageCollection) << "GarbageCollect() everything";
[email protected]8ad5d462013-05-02 08:45:262132 CookieItVector cookie_its;
jww82d99c12015-11-25 18:39:532133
[email protected]7a964a72010-09-07 19:33:262134 num_deleted += GarbageCollectExpired(
2135 current, CookieMapItPair(cookies_.begin(), cookies_.end()),
2136 &cookie_its);
jww82d99c12015-11-25 18:39:532137
[email protected]8ad5d462013-05-02 08:45:262138 if (cookie_its.size() > kMaxCookies) {
2139 VLOG(kVlogGarbageCollection) << "Deep Garbage Collect everything.";
2140 size_t purge_goal = cookie_its.size() - (kMaxCookies - kPurgeCookies);
2141 DCHECK(purge_goal > kPurgeCookies);
jww82d99c12015-11-25 18:39:532142
2143 if (enforce_strict_secure) {
2144 CookieItVector secure_cookie_its;
2145 CookieItVector non_secure_cookie_its;
2146 SplitCookieVectorIntoSecureAndNonSecure(cookie_its, &secure_cookie_its,
2147 &non_secure_cookie_its);
2148 size_t non_secure_purge_goal =
2149 std::min<size_t>(purge_goal, non_secure_cookie_its.size() - 1);
2150
2151 size_t just_deleted = GarbageCollectLeastRecentlyAccessed(
2152 current, safe_date, non_secure_purge_goal, non_secure_cookie_its);
2153 num_deleted += just_deleted;
2154
2155 if (just_deleted < purge_goal) {
2156 size_t secure_purge_goal = std::min<size_t>(
2157 purge_goal - just_deleted, secure_cookie_its.size() - 1);
2158 num_deleted += GarbageCollectLeastRecentlyAccessed(
2159 current, safe_date, secure_purge_goal, secure_cookie_its);
2160 }
2161 } else {
2162 num_deleted += GarbageCollectLeastRecentlyAccessed(
2163 current, safe_date, purge_goal, cookie_its);
2164 }
[email protected]8807b322010-10-01 17:10:142165 }
[email protected]c890ed192008-10-30 23:45:532166 }
2167
2168 return num_deleted;
2169}
2170
jww82d99c12015-11-25 18:39:532171size_t CookieMonster::GarbageCollectExpired(const Time& current,
2172 const CookieMapItPair& itpair,
2173 CookieItVector* cookie_its) {
[email protected]ba4ad0e2011-03-15 08:12:472174 if (keep_expired_cookies_)
2175 return 0;
2176
[email protected]bb8905722010-05-21 17:29:042177 lock_.AssertAcquired();
2178
[email protected]c890ed192008-10-30 23:45:532179 int num_deleted = 0;
2180 for (CookieMap::iterator it = itpair.first, end = itpair.second; it != end;) {
2181 CookieMap::iterator curit = it;
2182 ++it;
2183
2184 if (curit->second->IsExpired(current)) {
[email protected]2f3f3592010-07-07 20:11:512185 InternalDeleteCookie(curit, true, DELETE_COOKIE_EXPIRED);
[email protected]c890ed192008-10-30 23:45:532186 ++num_deleted;
2187 } else if (cookie_its) {
2188 cookie_its->push_back(curit);
2189 }
initial.commit586acc5fe2008-07-26 22:42:522190 }
2191
2192 return num_deleted;
2193}
2194
jww82d99c12015-11-25 18:39:532195size_t CookieMonster::GarbageCollectNonSecure(
2196 const CookieItVector& valid_cookies,
2197 CookieItVector* cookie_its) {
2198 lock_.AssertAcquired();
2199
2200 size_t num_deleted = 0;
2201 for (const auto& curr_cookie_it : valid_cookies) {
2202 if (!curr_cookie_it->second->IsSecure()) {
2203 InternalDeleteCookie(curr_cookie_it, true, DELETE_COOKIE_NON_SECURE);
2204 ++num_deleted;
2205 } else if (cookie_its) {
2206 cookie_its->push_back(curr_cookie_it);
2207 }
2208 }
2209
2210 return num_deleted;
2211}
2212
2213size_t CookieMonster::GarbageCollectDeleteRange(
2214 const Time& current,
2215 DeletionCause cause,
2216 CookieItVector::iterator it_begin,
2217 CookieItVector::iterator it_end) {
[email protected]8ad5d462013-05-02 08:45:262218 for (CookieItVector::iterator it = it_begin; it != it_end; it++) {
2219 histogram_evicted_last_access_minutes_->Add(
2220 (current - (*it)->second->LastAccessDate()).InMinutes());
2221 InternalDeleteCookie((*it), true, cause);
[email protected]c10da4b02010-03-25 14:38:322222 }
[email protected]8ad5d462013-05-02 08:45:262223 return it_end - it_begin;
[email protected]c10da4b02010-03-25 14:38:322224}
2225
mmenke74bcbd52016-01-21 17:17:562226size_t CookieMonster::GarbageCollectLeastRecentlyAccessed(
2227 const base::Time& current,
2228 const base::Time& safe_date,
2229 size_t purge_goal,
2230 CookieItVector cookie_its) {
2231 // Sorts up to *and including* |cookie_its[purge_goal]|, so
2232 // |earliest_access_time| will be properly assigned even if
2233 // |global_purge_it| == |cookie_its.begin() + purge_goal|.
2234 SortLeastRecentlyAccessed(cookie_its.begin(), cookie_its.end(), purge_goal);
2235 // Find boundary to cookies older than safe_date.
2236 CookieItVector::iterator global_purge_it = LowerBoundAccessDate(
2237 cookie_its.begin(), cookie_its.begin() + purge_goal, safe_date);
2238 // Only delete the old cookies, and if strict secure is enabled, delete
2239 // non-secure ones first.
2240 size_t num_deleted =
2241 GarbageCollectDeleteRange(current, DELETE_COOKIE_EVICTED_GLOBAL,
2242 cookie_its.begin(), global_purge_it);
2243 // Set access day to the oldest cookie that wasn't deleted.
2244 earliest_access_time_ = (*global_purge_it)->second->LastAccessDate();
2245 return num_deleted;
2246}
2247
[email protected]ed32c212013-05-14 20:49:292248// A wrapper around registry_controlled_domains::GetDomainAndRegistry
[email protected]f48b9432011-01-11 07:25:402249// to make clear we're creating a key for our local map. Here and
2250// in FindCookiesForHostAndDomain() are the only two places where
2251// we need to conditionalize based on key type.
2252//
2253// Note that this key algorithm explicitly ignores the scheme. This is
2254// because when we're entering cookies into the map from the backing store,
2255// we in general won't have the scheme at that point.
2256// In practical terms, this means that file cookies will be stored
2257// in the map either by an empty string or by UNC name (and will be
2258// limited by kMaxCookiesPerHost), and extension cookies will be stored
2259// based on the single extension id, as the extension id won't have the
2260// form of a DNS host and hence GetKey() will return it unchanged.
2261//
2262// Arguably the right thing to do here is to make the key
2263// algorithm dependent on the scheme, and make sure that the scheme is
2264// available everywhere the key must be obtained (specfically at backing
2265// store load time). This would require either changing the backing store
2266// database schema to include the scheme (far more trouble than it's worth), or
2267// separating out file cookies into their own CookieMonster instance and
2268// thus restricting each scheme to a single cookie monster (which might
2269// be worth it, but is still too much trouble to solve what is currently a
2270// non-problem).
2271std::string CookieMonster::GetKey(const std::string& domain) const {
[email protected]f48b9432011-01-11 07:25:402272 std::string effective_domain(
[email protected]ed32c212013-05-14 20:49:292273 registry_controlled_domains::GetDomainAndRegistry(
[email protected]aabe1792014-01-30 21:37:462274 domain, registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES));
[email protected]f48b9432011-01-11 07:25:402275 if (effective_domain.empty())
2276 effective_domain = domain;
2277
2278 if (!effective_domain.empty() && effective_domain[0] == '.')
2279 return effective_domain.substr(1);
2280 return effective_domain;
2281}
2282
2283bool CookieMonster::HasCookieableScheme(const GURL& url) {
2284 lock_.AssertAcquired();
2285
2286 // Make sure the request is on a cookie-able url scheme.
2287 for (size_t i = 0; i < cookieable_schemes_.size(); ++i) {
2288 // We matched a scheme.
2289 if (url.SchemeIs(cookieable_schemes_[i].c_str())) {
2290 // We've matched a supported scheme.
initial.commit586acc5fe2008-07-26 22:42:522291 return true;
2292 }
2293 }
[email protected]f48b9432011-01-11 07:25:402294
2295 // The scheme didn't match any in our whitelist.
mkwstbe84af312015-02-20 08:52:452296 VLOG(kVlogPerCookieMonster)
2297 << "WARNING: Unsupported cookie scheme: " << url.scheme();
initial.commit586acc5fe2008-07-26 22:42:522298 return false;
2299}
2300
[email protected]c4058fb2010-06-22 17:25:262301// Test to see if stats should be recorded, and record them if so.
2302// The goal here is to get sampling for the average browser-hour of
2303// activity. We won't take samples when the web isn't being surfed,
2304// and when the web is being surfed, we'll take samples about every
2305// kRecordStatisticsIntervalSeconds.
2306// last_statistic_record_time_ is initialized to Now() rather than null
2307// in the constructor so that we won't take statistics right after
2308// startup, to avoid bias from browsers that are started but not used.
2309void CookieMonster::RecordPeriodicStats(const base::Time& current_time) {
2310 const base::TimeDelta kRecordStatisticsIntervalTime(
2311 base::TimeDelta::FromSeconds(kRecordStatisticsIntervalSeconds));
2312
[email protected]7a964a72010-09-07 19:33:262313 // If we've taken statistics recently, return.
2314 if (current_time - last_statistic_record_time_ <=
[email protected]c4058fb2010-06-22 17:25:262315 kRecordStatisticsIntervalTime) {
[email protected]7a964a72010-09-07 19:33:262316 return;
[email protected]c4058fb2010-06-22 17:25:262317 }
[email protected]7a964a72010-09-07 19:33:262318
2319 // See InitializeHistograms() for details.
2320 histogram_count_->Add(cookies_.size());
2321
2322 // More detailed statistics on cookie counts at different granularities.
[email protected]7a964a72010-09-07 19:33:262323 last_statistic_record_time_ = current_time;
[email protected]c4058fb2010-06-22 17:25:262324}
2325
[email protected]f48b9432011-01-11 07:25:402326// Initialize all histogram counter variables used in this class.
2327//
2328// Normal histogram usage involves using the macros defined in
2329// histogram.h, which automatically takes care of declaring these
2330// variables (as statics), initializing them, and accumulating into
2331// them, all from a single entry point. Unfortunately, that solution
2332// doesn't work for the CookieMonster, as it's vulnerable to races between
2333// separate threads executing the same functions and hence initializing the
2334// same static variables. There isn't a race danger in the histogram
2335// accumulation calls; they are written to be resilient to simultaneous
2336// calls from multiple threads.
2337//
2338// The solution taken here is to have per-CookieMonster instance
2339// variables that are constructed during CookieMonster construction.
2340// Note that these variables refer to the same underlying histogram,
2341// so we still race (but safely) with other CookieMonster instances
2342// for accumulation.
2343//
2344// To do this we've expanded out the individual histogram macros calls,
2345// with declarations of the variables in the class decl, initialization here
2346// (done from the class constructor) and direct calls to the accumulation
2347// methods where needed. The specific histogram macro calls on which the
2348// initialization is based are included in comments below.
2349void CookieMonster::InitializeHistograms() {
2350 // From UMA_HISTOGRAM_CUSTOM_COUNTS
2351 histogram_expiration_duration_minutes_ = base::Histogram::FactoryGet(
mkwstbe84af312015-02-20 08:52:452352 "Cookie.ExpirationDurationMinutes", 1, kMinutesInTenYears, 50,
[email protected]f48b9432011-01-11 07:25:402353 base::Histogram::kUmaTargetedHistogramFlag);
[email protected]f48b9432011-01-11 07:25:402354 histogram_evicted_last_access_minutes_ = base::Histogram::FactoryGet(
mkwstbe84af312015-02-20 08:52:452355 "Cookie.EvictedLastAccessMinutes", 1, kMinutesInTenYears, 50,
[email protected]f48b9432011-01-11 07:25:402356 base::Histogram::kUmaTargetedHistogramFlag);
2357 histogram_count_ = base::Histogram::FactoryGet(
mkwstbe84af312015-02-20 08:52:452358 "Cookie.Count", 1, 4000, 50, base::Histogram::kUmaTargetedHistogramFlag);
[email protected]f48b9432011-01-11 07:25:402359
2360 // From UMA_HISTOGRAM_ENUMERATION
2361 histogram_cookie_deletion_cause_ = base::LinearHistogram::FactoryGet(
mkwstbe84af312015-02-20 08:52:452362 "Cookie.DeletionCause", 1, DELETE_COOKIE_LAST_ENTRY - 1,
2363 DELETE_COOKIE_LAST_ENTRY, base::Histogram::kUmaTargetedHistogramFlag);
mkwstc1aa4cc2015-04-03 19:57:452364 histogram_cookie_type_ = base::LinearHistogram::FactoryGet(
mkwst87378d92015-04-10 21:22:112365 "Cookie.Type", 1, (1 << COOKIE_TYPE_LAST_ENTRY) - 1,
2366 1 << COOKIE_TYPE_LAST_ENTRY, base::Histogram::kUmaTargetedHistogramFlag);
estark7feb65c2b2015-08-21 23:38:202367 histogram_cookie_source_scheme_ = base::LinearHistogram::FactoryGet(
2368 "Cookie.CookieSourceScheme", 1, COOKIE_SOURCE_LAST_ENTRY - 1,
2369 COOKIE_SOURCE_LAST_ENTRY, base::Histogram::kUmaTargetedHistogramFlag);
jww31e32632015-12-16 23:38:342370 histogram_cookie_delete_equivalent_ = base::LinearHistogram::FactoryGet(
2371 "Cookie.CookieDeleteEquivalent", 1,
2372 COOKIE_DELETE_EQUIVALENT_LAST_ENTRY - 1,
2373 COOKIE_DELETE_EQUIVALENT_LAST_ENTRY,
2374 base::Histogram::kUmaTargetedHistogramFlag);
[email protected]f48b9432011-01-11 07:25:402375
2376 // From UMA_HISTOGRAM_{CUSTOM_,}TIMES
[email protected]c7593fb22011-11-14 23:54:272377 histogram_time_blocked_on_load_ = base::Histogram::FactoryTimeGet(
mkwstbe84af312015-02-20 08:52:452378 "Cookie.TimeBlockedOnLoad", base::TimeDelta::FromMilliseconds(1),
2379 base::TimeDelta::FromMinutes(1), 50,
2380 base::Histogram::kUmaTargetedHistogramFlag);
[email protected]f48b9432011-01-11 07:25:402381}
2382
[email protected]f48b9432011-01-11 07:25:402383// The system resolution is not high enough, so we can have multiple
2384// set cookies that result in the same system time. When this happens, we
2385// increment by one Time unit. Let's hope computers don't get too fast.
2386Time CookieMonster::CurrentTime() {
mkwstbe84af312015-02-20 08:52:452387 return std::max(Time::Now(), Time::FromInternalValue(
2388 last_time_seen_.ToInternalValue() + 1));
[email protected]f48b9432011-01-11 07:25:402389}
2390
mmenke74bcbd52016-01-21 17:17:562391void CookieMonster::DoCookieTask(
2392 const scoped_refptr<CookieMonsterTask>& task_item) {
2393 {
2394 base::AutoLock autolock(lock_);
2395 MarkCookieStoreAsInitialized();
2396 FetchAllCookiesIfNecessary();
2397 if (!finished_fetching_all_cookies_ && store_.get()) {
2398 tasks_pending_.push(task_item);
2399 return;
2400 }
2401 }
2402
2403 task_item->Run();
2404}
2405
2406void CookieMonster::DoCookieTaskForURL(
2407 const scoped_refptr<CookieMonsterTask>& task_item,
2408 const GURL& url) {
2409 {
2410 base::AutoLock autolock(lock_);
2411 MarkCookieStoreAsInitialized();
2412 if (ShouldFetchAllCookiesWhenFetchingAnyCookie())
2413 FetchAllCookiesIfNecessary();
2414 // If cookies for the requested domain key (eTLD+1) have been loaded from DB
2415 // then run the task, otherwise load from DB.
2416 if (!finished_fetching_all_cookies_ && store_.get()) {
2417 // Checks if the domain key has been loaded.
2418 std::string key(
2419 cookie_util::GetEffectiveDomain(url.scheme(), url.host()));
2420 if (keys_loaded_.find(key) == keys_loaded_.end()) {
2421 std::map<std::string,
2422 std::deque<scoped_refptr<CookieMonsterTask>>>::iterator it =
2423 tasks_pending_for_key_.find(key);
2424 if (it == tasks_pending_for_key_.end()) {
2425 store_->LoadCookiesForKey(
2426 key, base::Bind(&CookieMonster::OnKeyLoaded, this, key));
2427 it = tasks_pending_for_key_
2428 .insert(std::make_pair(
2429 key, std::deque<scoped_refptr<CookieMonsterTask>>()))
2430 .first;
2431 }
2432 it->second.push_back(task_item);
2433 return;
2434 }
2435 }
2436 }
2437 task_item->Run();
2438}
2439
drogerd5d1278c2015-03-17 19:21:512440void CookieMonster::ComputeCookieDiff(CookieList* old_cookies,
2441 CookieList* new_cookies,
2442 CookieList* cookies_to_add,
2443 CookieList* cookies_to_delete) {
2444 DCHECK(old_cookies);
2445 DCHECK(new_cookies);
2446 DCHECK(cookies_to_add);
2447 DCHECK(cookies_to_delete);
2448 DCHECK(cookies_to_add->empty());
2449 DCHECK(cookies_to_delete->empty());
2450
2451 // Sort both lists.
2452 // A set ordered by FullDiffCookieSorter is also ordered by
2453 // PartialDiffCookieSorter.
2454 std::sort(old_cookies->begin(), old_cookies->end(), FullDiffCookieSorter);
2455 std::sort(new_cookies->begin(), new_cookies->end(), FullDiffCookieSorter);
2456
2457 // Select any old cookie for deletion if no new cookie has the same name,
2458 // domain, and path.
2459 std::set_difference(
2460 old_cookies->begin(), old_cookies->end(), new_cookies->begin(),
2461 new_cookies->end(),
2462 std::inserter(*cookies_to_delete, cookies_to_delete->begin()),
2463 PartialDiffCookieSorter);
2464
2465 // Select any new cookie for addition (or update) if no old cookie is exactly
2466 // equivalent.
2467 std::set_difference(new_cookies->begin(), new_cookies->end(),
2468 old_cookies->begin(), old_cookies->end(),
2469 std::inserter(*cookies_to_add, cookies_to_add->begin()),
2470 FullDiffCookieSorter);
2471}
2472
msarda0aad8f02014-10-30 09:22:392473void CookieMonster::RunCallbacks(const CanonicalCookie& cookie, bool removed) {
ellyjones399e35a22014-10-27 11:09:562474 lock_.AssertAcquired();
2475 CookieOptions opts;
2476 opts.set_include_httponly();
mkwst202534e32016-01-15 16:07:152477 opts.set_include_first_party_only_cookies();
ellyjones399e35a22014-10-27 11:09:562478 // Note that the callbacks in hook_map_ are wrapped with MakeAsync(), so they
2479 // are guaranteed to not take long - they just post a RunAsync task back to
2480 // the appropriate thread's message loop and return. It is important that this
2481 // method not run user-supplied callbacks directly, since the CookieMonster
2482 // lock is held and it is easy to accidentally introduce deadlocks.
2483 for (CookieChangedHookMap::iterator it = hook_map_.begin();
2484 it != hook_map_.end(); ++it) {
2485 std::pair<GURL, std::string> key = it->first;
2486 if (cookie.IncludeForRequestURL(key.first, opts) &&
2487 cookie.Name() == key.second) {
msarda0aad8f02014-10-30 09:22:392488 it->second->Notify(cookie, removed);
ellyjones399e35a22014-10-27 11:09:562489 }
2490 }
2491}
2492
[email protected]63725312012-07-19 08:24:162493} // namespace net