cookie_monster.cc 100 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565
  1. // Copyright (c) 2012 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. // Portions of this code based on Mozilla:
  5. // (netwerk/cookie/src/nsCookieService.cpp)
  6. /* ***** BEGIN LICENSE BLOCK *****
  7. * Version: MPL 1.1/GPL 2.0/LGPL 2.1
  8. *
  9. * The contents of this file are subject to the Mozilla Public License Version
  10. * 1.1 (the "License"); you may not use this file except in compliance with
  11. * the License. You may obtain a copy of the License at
  12. * http://www.mozilla.org/MPL/
  13. *
  14. * Software distributed under the License is distributed on an "AS IS" basis,
  15. * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  16. * for the specific language governing rights and limitations under the
  17. * License.
  18. *
  19. * The Original Code is mozilla.org code.
  20. *
  21. * The Initial Developer of the Original Code is
  22. * Netscape Communications Corporation.
  23. * Portions created by the Initial Developer are Copyright (C) 2003
  24. * the Initial Developer. All Rights Reserved.
  25. *
  26. * Contributor(s):
  27. * Daniel Witte (dwitte@stanford.edu)
  28. * Michiel van Leeuwen (mvl@exedo.nl)
  29. *
  30. * Alternatively, the contents of this file may be used under the terms of
  31. * either the GNU General Public License Version 2 or later (the "GPL"), or
  32. * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  33. * in which case the provisions of the GPL or the LGPL are applicable instead
  34. * of those above. If you wish to allow use of your version of this file only
  35. * under the terms of either the GPL or the LGPL, and not to allow others to
  36. * use your version of this file under the terms of the MPL, indicate your
  37. * decision by deleting the provisions above and replace them with the notice
  38. * and other provisions required by the GPL or the LGPL. If you do not delete
  39. * the provisions above, a recipient may use your version of this file under
  40. * the terms of any one of the MPL, the GPL or the LGPL.
  41. *
  42. * ***** END LICENSE BLOCK ***** */
  43. #include "net/cookies/cookie_monster.h"
  44. #include <functional>
  45. #include <numeric>
  46. #include <set>
  47. #include <utility>
  48. #include "base/bind.h"
  49. #include "base/callback.h"
  50. #include "base/containers/flat_map.h"
  51. #include "base/feature_list.h"
  52. #include "base/location.h"
  53. #include "base/logging.h"
  54. #include "base/metrics/field_trial.h"
  55. #include "base/metrics/histogram_functions.h"
  56. #include "base/metrics/histogram_macros.h"
  57. #include "base/ranges/algorithm.h"
  58. #include "base/strings/strcat.h"
  59. #include "base/strings/string_piece.h"
  60. #include "base/strings/string_util.h"
  61. #include "base/strings/stringprintf.h"
  62. #include "base/task/single_thread_task_runner.h"
  63. #include "base/threading/thread_task_runner_handle.h"
  64. #include "net/base/features.h"
  65. #include "net/base/isolation_info.h"
  66. #include "net/base/registry_controlled_domains/registry_controlled_domain.h"
  67. #include "net/base/schemeful_site.h"
  68. #include "net/base/url_util.h"
  69. #include "net/cookies/canonical_cookie.h"
  70. #include "net/cookies/cookie_constants.h"
  71. #include "net/cookies/cookie_monster_change_dispatcher.h"
  72. #include "net/cookies/cookie_monster_netlog_params.h"
  73. #include "net/cookies/cookie_util.h"
  74. #include "net/cookies/parsed_cookie.h"
  75. #include "net/http/http_util.h"
  76. #include "net/log/net_log.h"
  77. #include "net/log/net_log_values.h"
  78. #include "third_party/abseil-cpp/absl/types/optional.h"
  79. #include "url/origin.h"
  80. #include "url/third_party/mozilla/url_parse.h"
  81. #include "url/url_canon.h"
  82. #include "url/url_constants.h"
  83. using base::Time;
  84. using base::TimeTicks;
  85. using TimeRange = net::CookieDeletionInfo::TimeRange;
  86. // In steady state, most cookie requests can be satisfied by the in memory
  87. // cookie monster store. If the cookie request cannot be satisfied by the in
  88. // memory store, the relevant cookies must be fetched from the persistent
  89. // store. The task is queued in CookieMonster::tasks_pending_ if it requires
  90. // all cookies to be loaded from the backend, or tasks_pending_for_key_ if it
  91. // only requires all cookies associated with an eTLD+1.
  92. //
  93. // On the browser critical paths (e.g. for loading initial web pages in a
  94. // session restore) it may take too long to wait for the full load. If a cookie
  95. // request is for a specific URL, DoCookieCallbackForURL is called, which
  96. // triggers a priority load if the key is not loaded yet by calling
  97. // PersistentCookieStore::LoadCookiesForKey. The request is queued in
  98. // CookieMonster::tasks_pending_for_key_ and executed upon receiving
  99. // notification of key load completion via CookieMonster::OnKeyLoaded(). If
  100. // multiple requests for the same eTLD+1 are received before key load
  101. // completion, only the first request calls
  102. // PersistentCookieStore::LoadCookiesForKey, all subsequent requests are queued
  103. // in CookieMonster::tasks_pending_for_key_ and executed upon receiving
  104. // notification of key load completion triggered by the first request for the
  105. // same eTLD+1.
  106. static const int kDaysInTenYears = 10 * 365;
  107. static const int kMinutesInTenYears = kDaysInTenYears * 24 * 60;
  108. namespace {
  109. void MaybeRunDeleteCallback(base::WeakPtr<net::CookieMonster> cookie_monster,
  110. base::OnceClosure callback) {
  111. if (cookie_monster && callback)
  112. std::move(callback).Run();
  113. }
  114. template <typename T>
  115. void MaybeRunCookieCallback(base::OnceCallback<void(const T&)> callback,
  116. const T& result) {
  117. if (callback)
  118. std::move(callback).Run(result);
  119. }
  120. template <typename T, typename U>
  121. void MaybeRunCookieCallback(
  122. base::OnceCallback<void(const T&, const U&)> callback,
  123. const T& first,
  124. const U& second) {
  125. if (callback)
  126. std::move(callback).Run(first, second);
  127. }
  128. template <typename T>
  129. void MaybeRunCookieCallback(base::OnceCallback<void(T)> callback,
  130. const T& result) {
  131. if (callback)
  132. std::move(callback).Run(result);
  133. }
  134. // Anonymous and Fenced Frame uses a CookiePartitionKey with a nonce. In these
  135. // contexts, access to unpartitioned cookie is not granted.
  136. //
  137. // This returns true if the |list| of key should include unpartitioned cookie in
  138. // GetCookie...().
  139. bool IncludeUnpartitionedCookies(
  140. const net::CookiePartitionKeyCollection& list) {
  141. if (list.IsEmpty() || list.ContainsAllKeys())
  142. return true;
  143. for (const net::CookiePartitionKey& key : list.PartitionKeys()) {
  144. if (!key.nonce())
  145. return true;
  146. }
  147. return false;
  148. }
  149. } // namespace
  150. namespace net {
  151. // See comments at declaration of these variables in cookie_monster.h
  152. // for details.
  153. const size_t CookieMonster::kDomainMaxCookies = 180;
  154. const size_t CookieMonster::kDomainPurgeCookies = 30;
  155. const size_t CookieMonster::kMaxCookies = 3300;
  156. const size_t CookieMonster::kPurgeCookies = 300;
  157. const size_t CookieMonster::kMaxDomainPurgedKeys = 100;
  158. const size_t CookieMonster::kPerPartitionDomainMaxCookies = 10;
  159. const size_t CookieMonster::kDomainCookiesQuotaLow = 30;
  160. const size_t CookieMonster::kDomainCookiesQuotaMedium = 50;
  161. const size_t CookieMonster::kDomainCookiesQuotaHigh =
  162. kDomainMaxCookies - kDomainPurgeCookies - kDomainCookiesQuotaLow -
  163. kDomainCookiesQuotaMedium;
  164. const int CookieMonster::kSafeFromGlobalPurgeDays = 30;
  165. namespace {
  166. bool ContainsControlCharacter(const std::string& s) {
  167. return base::ranges::any_of(s, &HttpUtil::IsControlChar);
  168. }
  169. typedef std::vector<CanonicalCookie*> CanonicalCookieVector;
  170. // Default minimum delay after updating a cookie's LastAccessDate before we
  171. // will update it again.
  172. const int kDefaultAccessUpdateThresholdSeconds = 60;
  173. // Comparator to sort cookies from highest creation date to lowest
  174. // creation date.
  175. struct OrderByCreationTimeDesc {
  176. bool operator()(const CookieMonster::CookieMap::iterator& a,
  177. const CookieMonster::CookieMap::iterator& b) const {
  178. return a->second->CreationDate() > b->second->CreationDate();
  179. }
  180. };
  181. bool LRACookieSorter(const CookieMonster::CookieMap::iterator& it1,
  182. const CookieMonster::CookieMap::iterator& it2) {
  183. if (it1->second->LastAccessDate() != it2->second->LastAccessDate())
  184. return it1->second->LastAccessDate() < it2->second->LastAccessDate();
  185. // Ensure stability for == last access times by falling back to creation.
  186. return it1->second->CreationDate() < it2->second->CreationDate();
  187. }
  188. // For a CookieItVector iterator range [|it_begin|, |it_end|),
  189. // sorts the first |num_sort| elements by LastAccessDate().
  190. void SortLeastRecentlyAccessed(CookieMonster::CookieItVector::iterator it_begin,
  191. CookieMonster::CookieItVector::iterator it_end,
  192. size_t num_sort) {
  193. DCHECK_LE(static_cast<int>(num_sort), it_end - it_begin);
  194. std::partial_sort(it_begin, it_begin + num_sort, it_end, LRACookieSorter);
  195. }
  196. // Given a single cookie vector |cookie_its|, pushs all of the secure cookies in
  197. // |cookie_its| into |secure_cookie_its| and all of the non-secure cookies into
  198. // |non_secure_cookie_its|. Both |secure_cookie_its| and |non_secure_cookie_its|
  199. // must be non-NULL.
  200. void SplitCookieVectorIntoSecureAndNonSecure(
  201. const CookieMonster::CookieItVector& cookie_its,
  202. CookieMonster::CookieItVector* secure_cookie_its,
  203. CookieMonster::CookieItVector* non_secure_cookie_its) {
  204. DCHECK(secure_cookie_its && non_secure_cookie_its);
  205. for (const auto& curit : cookie_its) {
  206. if (curit->second->IsSecure())
  207. secure_cookie_its->push_back(curit);
  208. else
  209. non_secure_cookie_its->push_back(curit);
  210. }
  211. }
  212. bool LowerBoundAccessDateComparator(const CookieMonster::CookieMap::iterator it,
  213. const Time& access_date) {
  214. return it->second->LastAccessDate() < access_date;
  215. }
  216. // For a CookieItVector iterator range [|it_begin|, |it_end|)
  217. // from a CookieItVector sorted by LastAccessDate(), returns the
  218. // first iterator with access date >= |access_date|, or cookie_its_end if this
  219. // holds for all.
  220. CookieMonster::CookieItVector::iterator LowerBoundAccessDate(
  221. const CookieMonster::CookieItVector::iterator its_begin,
  222. const CookieMonster::CookieItVector::iterator its_end,
  223. const Time& access_date) {
  224. return std::lower_bound(its_begin, its_end, access_date,
  225. LowerBoundAccessDateComparator);
  226. }
  227. // Mapping between DeletionCause and CookieChangeCause; the
  228. // mapping also provides a boolean that specifies whether or not an
  229. // OnCookieChange notification ought to be generated.
  230. typedef struct ChangeCausePair_struct {
  231. CookieChangeCause cause;
  232. bool notify;
  233. } ChangeCausePair;
  234. const ChangeCausePair kChangeCauseMapping[] = {
  235. // DELETE_COOKIE_EXPLICIT
  236. {CookieChangeCause::EXPLICIT, true},
  237. // DELETE_COOKIE_OVERWRITE
  238. {CookieChangeCause::OVERWRITE, true},
  239. // DELETE_COOKIE_EXPIRED
  240. {CookieChangeCause::EXPIRED, true},
  241. // DELETE_COOKIE_EVICTED
  242. {CookieChangeCause::EVICTED, true},
  243. // DELETE_COOKIE_DUPLICATE_IN_BACKING_STORE
  244. {CookieChangeCause::EXPLICIT, false},
  245. // DELETE_COOKIE_DONT_RECORD
  246. {CookieChangeCause::EXPLICIT, false},
  247. // DELETE_COOKIE_EVICTED_DOMAIN
  248. {CookieChangeCause::EVICTED, true},
  249. // DELETE_COOKIE_EVICTED_GLOBAL
  250. {CookieChangeCause::EVICTED, true},
  251. // DELETE_COOKIE_EVICTED_DOMAIN_PRE_SAFE
  252. {CookieChangeCause::EVICTED, true},
  253. // DELETE_COOKIE_EVICTED_DOMAIN_POST_SAFE
  254. {CookieChangeCause::EVICTED, true},
  255. // DELETE_COOKIE_EXPIRED_OVERWRITE
  256. {CookieChangeCause::EXPIRED_OVERWRITE, true},
  257. // DELETE_COOKIE_CONTROL_CHAR
  258. {CookieChangeCause::EVICTED, true},
  259. // DELETE_COOKIE_NON_SECURE
  260. {CookieChangeCause::EVICTED, true},
  261. // DELETE_COOKIE_EVICTED_PER_PARTITION_DOMAIN
  262. {CookieChangeCause::EVICTED, true},
  263. // DELETE_COOKIE_LAST_ENTRY
  264. {CookieChangeCause::EXPLICIT, false}};
  265. bool IsCookieEligibleForEviction(CookiePriority current_priority_level,
  266. bool protect_secure_cookies,
  267. const CanonicalCookie* cookie) {
  268. if (cookie->Priority() == current_priority_level && protect_secure_cookies)
  269. return !cookie->IsSecure();
  270. return cookie->Priority() == current_priority_level;
  271. }
  272. size_t CountCookiesForPossibleDeletion(
  273. CookiePriority priority,
  274. const CookieMonster::CookieItVector* cookies,
  275. bool protect_secure_cookies) {
  276. size_t cookies_count = 0U;
  277. for (const auto& cookie : *cookies) {
  278. if (cookie->second->Priority() == priority) {
  279. if (!protect_secure_cookies || cookie->second->IsSecure())
  280. cookies_count++;
  281. }
  282. }
  283. return cookies_count;
  284. }
  285. // Records minutes until the expiration date of a cookie to the appropriate
  286. // histogram. Only histograms cookies that have an expiration date (i.e. are
  287. // persistent).
  288. void HistogramExpirationDuration(const CanonicalCookie& cookie,
  289. base::Time creation_time) {
  290. if (!cookie.IsPersistent())
  291. return;
  292. int expiration_duration_minutes =
  293. (cookie.ExpiryDate() - creation_time).InMinutes();
  294. if (cookie.IsSecure()) {
  295. UMA_HISTOGRAM_CUSTOM_COUNTS("Cookie.ExpirationDurationMinutesSecure",
  296. expiration_duration_minutes, 1,
  297. kMinutesInTenYears, 50);
  298. } else {
  299. UMA_HISTOGRAM_CUSTOM_COUNTS("Cookie.ExpirationDurationMinutesNonSecure",
  300. expiration_duration_minutes, 1,
  301. kMinutesInTenYears, 50);
  302. }
  303. // The proposed rfc6265bis sets an upper limit on Expires/Max-Age attribute
  304. // values of 400 days. We need to study the impact this change would have:
  305. // https://httpwg.org/http-extensions/draft-ietf-httpbis-rfc6265bis.html
  306. int expiration_duration_days = (cookie.ExpiryDate() - creation_time).InDays();
  307. if (expiration_duration_days > 400) {
  308. UMA_HISTOGRAM_CUSTOM_COUNTS("Cookie.ExpirationDuration400DaysGT",
  309. expiration_duration_days, 401, kDaysInTenYears,
  310. 100);
  311. } else {
  312. UMA_HISTOGRAM_CUSTOM_COUNTS("Cookie.ExpirationDuration400DaysLTE",
  313. expiration_duration_days, 1, 400, 50);
  314. }
  315. }
  316. } // namespace
  317. CookieMonster::CookieMonster(scoped_refptr<PersistentCookieStore> store,
  318. NetLog* net_log,
  319. bool first_party_sets_enabled)
  320. : CookieMonster(std::move(store),
  321. base::Seconds(kDefaultAccessUpdateThresholdSeconds),
  322. net_log,
  323. first_party_sets_enabled) {}
  324. CookieMonster::CookieMonster(scoped_refptr<PersistentCookieStore> store,
  325. base::TimeDelta last_access_threshold,
  326. NetLog* net_log,
  327. bool first_party_sets_enabled)
  328. : change_dispatcher_(this, first_party_sets_enabled),
  329. net_log_(NetLogWithSource::Make(net_log, NetLogSourceType::COOKIE_STORE)),
  330. store_(std::move(store)),
  331. last_access_threshold_(last_access_threshold),
  332. last_statistic_record_time_(base::Time::Now()),
  333. first_party_sets_enabled_(first_party_sets_enabled) {
  334. cookieable_schemes_.insert(
  335. cookieable_schemes_.begin(), kDefaultCookieableSchemes,
  336. kDefaultCookieableSchemes + kDefaultCookieableSchemesCount);
  337. net_log_.BeginEvent(NetLogEventType::COOKIE_STORE_ALIVE, [&] {
  338. return NetLogCookieMonsterConstructorParams(store_ != nullptr);
  339. });
  340. }
  341. // Asynchronous CookieMonster API
  342. void CookieMonster::FlushStore(base::OnceClosure callback) {
  343. DCHECK(thread_checker_.CalledOnValidThread());
  344. if (initialized_ && store_.get()) {
  345. store_->Flush(std::move(callback));
  346. } else if (callback) {
  347. base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
  348. std::move(callback));
  349. }
  350. }
  351. void CookieMonster::SetForceKeepSessionState() {
  352. DCHECK(thread_checker_.CalledOnValidThread());
  353. if (store_)
  354. store_->SetForceKeepSessionState();
  355. }
  356. void CookieMonster::SetAllCookiesAsync(const CookieList& list,
  357. SetCookiesCallback callback) {
  358. DoCookieCallback(base::BindOnce(
  359. // base::Unretained is safe as DoCookieCallback stores
  360. // the callback on |*this|, so the callback will not outlive
  361. // the object.
  362. &CookieMonster::SetAllCookies, base::Unretained(this), list,
  363. std::move(callback)));
  364. }
  365. void CookieMonster::SetCanonicalCookieAsync(
  366. std::unique_ptr<CanonicalCookie> cookie,
  367. const GURL& source_url,
  368. const CookieOptions& options,
  369. SetCookiesCallback callback,
  370. absl::optional<CookieAccessResult> cookie_access_result) {
  371. DCHECK(cookie->IsCanonical());
  372. std::string domain = cookie->Domain();
  373. DoCookieCallbackForHostOrDomain(
  374. base::BindOnce(
  375. // base::Unretained is safe as DoCookieCallbackForHostOrDomain stores
  376. // the callback on |*this|, so the callback will not outlive
  377. // the object.
  378. &CookieMonster::SetCanonicalCookie, base::Unretained(this),
  379. std::move(cookie), source_url, options, std::move(callback),
  380. std::move(cookie_access_result)),
  381. domain);
  382. }
  383. void CookieMonster::GetCookieListWithOptionsAsync(
  384. const GURL& url,
  385. const CookieOptions& options,
  386. const CookiePartitionKeyCollection& cookie_partition_key_collection,
  387. GetCookieListCallback callback) {
  388. DoCookieCallbackForURL(
  389. base::BindOnce(
  390. // base::Unretained is safe as DoCookieCallbackForURL stores
  391. // the callback on |*this|, so the callback will not outlive
  392. // the object.
  393. &CookieMonster::GetCookieListWithOptions, base::Unretained(this), url,
  394. options, cookie_partition_key_collection, std::move(callback)),
  395. url);
  396. }
  397. void CookieMonster::GetAllCookiesAsync(GetAllCookiesCallback callback) {
  398. DoCookieCallback(base::BindOnce(
  399. // base::Unretained is safe as DoCookieCallback stores
  400. // the callback on |*this|, so the callback will not outlive
  401. // the object.
  402. &CookieMonster::GetAllCookies, base::Unretained(this),
  403. std::move(callback)));
  404. }
  405. void CookieMonster::GetAllCookiesWithAccessSemanticsAsync(
  406. GetAllCookiesWithAccessSemanticsCallback callback) {
  407. DoCookieCallback(base::BindOnce(
  408. // base::Unretained is safe as DoCookieCallback stores
  409. // the callback on |*this|, so the callback will not outlive
  410. // the object.
  411. &CookieMonster::GetAllCookies, base::Unretained(this),
  412. base::BindOnce(&CookieMonster::AttachAccessSemanticsListForCookieList,
  413. base::Unretained(this), std::move(callback))));
  414. }
  415. void CookieMonster::DeleteCanonicalCookieAsync(const CanonicalCookie& cookie,
  416. DeleteCallback callback) {
  417. DoCookieCallback(base::BindOnce(
  418. // base::Unretained is safe as DoCookieCallback stores
  419. // the callback on |*this|, so the callback will not outlive
  420. // the object.
  421. &CookieMonster::DeleteCanonicalCookie, base::Unretained(this), cookie,
  422. std::move(callback)));
  423. }
  424. void CookieMonster::DeleteAllCreatedInTimeRangeAsync(
  425. const TimeRange& creation_range,
  426. DeleteCallback callback) {
  427. DoCookieCallback(base::BindOnce(
  428. // base::Unretained is safe as DoCookieCallback stores
  429. // the callback on |*this|, so the callback will not outlive
  430. // the object.
  431. &CookieMonster::DeleteAllCreatedInTimeRange, base::Unretained(this),
  432. creation_range, std::move(callback)));
  433. }
  434. void CookieMonster::DeleteAllMatchingInfoAsync(CookieDeletionInfo delete_info,
  435. DeleteCallback callback) {
  436. auto cookie_matcher =
  437. base::BindRepeating(&CookieMonster::MatchCookieDeletionInfo,
  438. base::Unretained(this), std::move(delete_info));
  439. DoCookieCallback(base::BindOnce(
  440. // base::Unretained is safe as DoCookieCallback stores
  441. // the callback on |*this|, so the callback will not outlive
  442. // the object.
  443. &CookieMonster::DeleteMatchingCookies, base::Unretained(this),
  444. std::move(cookie_matcher), DELETE_COOKIE_EXPLICIT, std::move(callback)));
  445. }
  446. void CookieMonster::DeleteSessionCookiesAsync(
  447. CookieStore::DeleteCallback callback) {
  448. auto session_cookie_matcher =
  449. base::BindRepeating([](const net::CanonicalCookie& cookie) {
  450. return !cookie.IsPersistent();
  451. });
  452. DoCookieCallback(base::BindOnce(
  453. // base::Unretained is safe as DoCookieCallback stores
  454. // the callback on |*this|, so the callback will not outlive
  455. // the object.
  456. &CookieMonster::DeleteMatchingCookies, base::Unretained(this),
  457. std::move(session_cookie_matcher), DELETE_COOKIE_EXPIRED,
  458. std::move(callback)));
  459. }
  460. void CookieMonster::DeleteMatchingCookiesAsync(
  461. CookieStore::DeletePredicate predicate,
  462. CookieStore::DeleteCallback callback) {
  463. DoCookieCallback(base::BindOnce(
  464. // base::Unretained is safe as DoCookieCallback stores
  465. // the callback on |*this|, so the callback will not outlive
  466. // the object.
  467. &CookieMonster::DeleteMatchingCookies, base::Unretained(this),
  468. std::move(predicate), DELETE_COOKIE_EXPLICIT, std::move(callback)));
  469. }
  470. void CookieMonster::SetCookieableSchemes(
  471. const std::vector<std::string>& schemes,
  472. SetCookieableSchemesCallback callback) {
  473. DCHECK(thread_checker_.CalledOnValidThread());
  474. // Calls to this method will have no effect if made after a WebView or
  475. // CookieManager instance has been created.
  476. if (initialized_) {
  477. MaybeRunCookieCallback(std::move(callback), false);
  478. return;
  479. }
  480. cookieable_schemes_ = schemes;
  481. MaybeRunCookieCallback(std::move(callback), true);
  482. }
  483. // This function must be called before the CookieMonster is used.
  484. void CookieMonster::SetPersistSessionCookies(bool persist_session_cookies) {
  485. DCHECK(thread_checker_.CalledOnValidThread());
  486. DCHECK(!initialized_);
  487. net_log_.AddEntryWithBoolParams(
  488. NetLogEventType::COOKIE_STORE_SESSION_PERSISTENCE, NetLogEventPhase::NONE,
  489. "persistence", persist_session_cookies);
  490. persist_session_cookies_ = persist_session_cookies;
  491. }
  492. const char* const CookieMonster::kDefaultCookieableSchemes[] = {"http", "https",
  493. "ws", "wss"};
  494. const int CookieMonster::kDefaultCookieableSchemesCount =
  495. std::size(kDefaultCookieableSchemes);
  496. CookieChangeDispatcher& CookieMonster::GetChangeDispatcher() {
  497. return change_dispatcher_;
  498. }
  499. CookieMonster::~CookieMonster() {
  500. DCHECK(thread_checker_.CalledOnValidThread());
  501. net_log_.EndEvent(NetLogEventType::COOKIE_STORE_ALIVE);
  502. }
  503. // static
  504. bool CookieMonster::CookieSorter(const CanonicalCookie* cc1,
  505. const CanonicalCookie* cc2) {
  506. // Mozilla sorts on the path length (longest first), and then it sorts by
  507. // creation time (oldest first). The RFC says the sort order for the domain
  508. // attribute is undefined.
  509. if (cc1->Path().length() == cc2->Path().length())
  510. return cc1->CreationDate() < cc2->CreationDate();
  511. return cc1->Path().length() > cc2->Path().length();
  512. }
  513. void CookieMonster::GetAllCookies(GetAllCookiesCallback callback) {
  514. DCHECK(thread_checker_.CalledOnValidThread());
  515. // This function is being called to scrape the cookie list for management UI
  516. // or similar. We shouldn't show expired cookies in this list since it will
  517. // just be confusing to users, and this function is called rarely enough (and
  518. // is already slow enough) that it's OK to take the time to garbage collect
  519. // the expired cookies now.
  520. //
  521. // Note that this does not prune cookies to be below our limits (if we've
  522. // exceeded them) the way that calling GarbageCollect() would.
  523. GarbageCollectExpired(
  524. Time::Now(), CookieMapItPair(cookies_.begin(), cookies_.end()), nullptr);
  525. GarbageCollectAllExpiredPartitionedCookies(Time::Now());
  526. // Copy the CanonicalCookie pointers from the map so that we can use the same
  527. // sorter as elsewhere, then copy the result out.
  528. std::vector<CanonicalCookie*> cookie_ptrs;
  529. cookie_ptrs.reserve(cookies_.size());
  530. for (const auto& cookie : cookies_)
  531. cookie_ptrs.push_back(cookie.second.get());
  532. for (const auto& cookie_partition : partitioned_cookies_) {
  533. for (const auto& cookie : *cookie_partition.second.get())
  534. cookie_ptrs.push_back(cookie.second.get());
  535. }
  536. std::sort(cookie_ptrs.begin(), cookie_ptrs.end(), CookieSorter);
  537. CookieList cookie_list;
  538. cookie_list.reserve(cookie_ptrs.size());
  539. for (auto* cookie_ptr : cookie_ptrs)
  540. cookie_list.push_back(*cookie_ptr);
  541. MaybeRunCookieCallback(std::move(callback), cookie_list);
  542. }
  543. void CookieMonster::AttachAccessSemanticsListForCookieList(
  544. GetAllCookiesWithAccessSemanticsCallback callback,
  545. const CookieList& cookie_list) {
  546. std::vector<CookieAccessSemantics> access_semantics_list;
  547. for (const CanonicalCookie& cookie : cookie_list) {
  548. access_semantics_list.push_back(GetAccessSemanticsForCookie(cookie));
  549. }
  550. MaybeRunCookieCallback(std::move(callback), cookie_list,
  551. access_semantics_list);
  552. }
  553. void CookieMonster::GetCookieListWithOptions(
  554. const GURL& url,
  555. const CookieOptions& options,
  556. const CookiePartitionKeyCollection& cookie_partition_key_collection,
  557. GetCookieListCallback callback) {
  558. DCHECK(thread_checker_.CalledOnValidThread());
  559. CookieAccessResultList included_cookies;
  560. CookieAccessResultList excluded_cookies;
  561. if (HasCookieableScheme(url)) {
  562. std::vector<CanonicalCookie*> cookie_ptrs;
  563. if (IncludeUnpartitionedCookies(cookie_partition_key_collection)) {
  564. cookie_ptrs = FindCookiesForRegistryControlledHost(url);
  565. } else {
  566. DCHECK(!cookie_partition_key_collection.IsEmpty());
  567. }
  568. if (!cookie_partition_key_collection.IsEmpty()) {
  569. if (cookie_partition_key_collection.ContainsAllKeys()) {
  570. for (const auto& it : partitioned_cookies_) {
  571. std::vector<CanonicalCookie*> partitioned_cookie_ptrs =
  572. FindPartitionedCookiesForRegistryControlledHost(it.first, url);
  573. cookie_ptrs.insert(cookie_ptrs.end(), partitioned_cookie_ptrs.begin(),
  574. partitioned_cookie_ptrs.end());
  575. }
  576. } else {
  577. for (const CookiePartitionKey& key :
  578. cookie_partition_key_collection.PartitionKeys()) {
  579. std::vector<CanonicalCookie*> partitioned_cookie_ptrs =
  580. FindPartitionedCookiesForRegistryControlledHost(key, url);
  581. cookie_ptrs.insert(cookie_ptrs.end(), partitioned_cookie_ptrs.begin(),
  582. partitioned_cookie_ptrs.end());
  583. }
  584. }
  585. }
  586. std::sort(cookie_ptrs.begin(), cookie_ptrs.end(), CookieSorter);
  587. included_cookies.reserve(cookie_ptrs.size());
  588. FilterCookiesWithOptions(url, options, &cookie_ptrs, &included_cookies,
  589. &excluded_cookies);
  590. }
  591. MaybeRunCookieCallback(std::move(callback), included_cookies,
  592. excluded_cookies);
  593. }
  594. void CookieMonster::DeleteAllCreatedInTimeRange(const TimeRange& creation_range,
  595. DeleteCallback callback) {
  596. DCHECK(thread_checker_.CalledOnValidThread());
  597. uint32_t num_deleted = 0;
  598. for (auto it = cookies_.begin(); it != cookies_.end();) {
  599. auto curit = it;
  600. CanonicalCookie* cc = curit->second.get();
  601. ++it;
  602. if (creation_range.Contains(cc->CreationDate())) {
  603. InternalDeleteCookie(curit, true, /*sync_to_store*/
  604. DELETE_COOKIE_EXPLICIT);
  605. ++num_deleted;
  606. }
  607. }
  608. for (PartitionedCookieMap::iterator partition_it =
  609. partitioned_cookies_.begin();
  610. partition_it != partitioned_cookies_.end();) {
  611. auto cur_partition_it = partition_it;
  612. CookieMap::iterator cookie_it = cur_partition_it->second->begin();
  613. CookieMap::iterator cookie_end = cur_partition_it->second->end();
  614. // InternalDeletePartitionedCookie may delete this cookie partition if it
  615. // only has one cookie, so we need to increment the iterator beforehand.
  616. ++partition_it;
  617. while (cookie_it != cookie_end) {
  618. auto cur_cookie_it = cookie_it;
  619. CanonicalCookie* cc = cur_cookie_it->second.get();
  620. ++cookie_it;
  621. if (creation_range.Contains(cc->CreationDate())) {
  622. InternalDeletePartitionedCookie(cur_partition_it, cur_cookie_it,
  623. true /*sync_to_store*/,
  624. DELETE_COOKIE_EXPLICIT);
  625. ++num_deleted;
  626. }
  627. }
  628. }
  629. FlushStore(
  630. base::BindOnce(&MaybeRunDeleteCallback, weak_ptr_factory_.GetWeakPtr(),
  631. callback ? base::BindOnce(std::move(callback), num_deleted)
  632. : base::OnceClosure()));
  633. }
  634. bool CookieMonster::MatchCookieDeletionInfo(
  635. const CookieDeletionInfo& delete_info,
  636. const net::CanonicalCookie& cookie) {
  637. bool delegate_treats_url_as_trustworthy = false; // irrelevant if no URL.
  638. if (delete_info.url.has_value()) {
  639. delegate_treats_url_as_trustworthy =
  640. cookie_access_delegate() &&
  641. cookie_access_delegate()->ShouldTreatUrlAsTrustworthy(
  642. delete_info.url.value());
  643. }
  644. // Deletion uses all inclusive options, so it's ok to get the
  645. // `CookieSamePartyStatus` wrong here.
  646. return delete_info.Matches(
  647. cookie,
  648. CookieAccessParams{GetAccessSemanticsForCookie(cookie),
  649. delegate_treats_url_as_trustworthy,
  650. CookieSamePartyStatus::kNoSamePartyEnforcement});
  651. }
  652. void CookieMonster::DeleteCanonicalCookie(const CanonicalCookie& cookie,
  653. DeleteCallback callback) {
  654. DCHECK(thread_checker_.CalledOnValidThread());
  655. uint32_t result = 0u;
  656. CookieMap* cookie_map = nullptr;
  657. PartitionedCookieMap::iterator cookie_partition_it;
  658. if (cookie.IsPartitioned()) {
  659. cookie_partition_it =
  660. partitioned_cookies_.find(cookie.PartitionKey().value());
  661. if (cookie_partition_it != partitioned_cookies_.end())
  662. cookie_map = cookie_partition_it->second.get();
  663. } else {
  664. cookie_map = &cookies_;
  665. }
  666. if (cookie_map) {
  667. for (CookieMapItPair its = cookie_map->equal_range(GetKey(cookie.Domain()));
  668. its.first != its.second; ++its.first) {
  669. const std::unique_ptr<CanonicalCookie>& candidate = its.first->second;
  670. // Historically, this has refused modification if the cookie has changed
  671. // value in between the CanonicalCookie object was returned by a getter
  672. // and when this ran. The later parts of the conditional (everything but
  673. // the equivalence check) attempt to preserve this behavior.
  674. if (candidate->IsEquivalent(cookie) &&
  675. candidate->Value() == cookie.Value()) {
  676. if (cookie.IsPartitioned()) {
  677. InternalDeletePartitionedCookie(cookie_partition_it, its.first, true,
  678. DELETE_COOKIE_EXPLICIT);
  679. } else {
  680. InternalDeleteCookie(its.first, true, DELETE_COOKIE_EXPLICIT);
  681. }
  682. result = 1u;
  683. break;
  684. }
  685. }
  686. }
  687. FlushStore(
  688. base::BindOnce(&MaybeRunDeleteCallback, weak_ptr_factory_.GetWeakPtr(),
  689. callback ? base::BindOnce(std::move(callback), result)
  690. : base::OnceClosure()));
  691. }
  692. void CookieMonster::DeleteMatchingCookies(DeletePredicate predicate,
  693. DeletionCause cause,
  694. DeleteCallback callback) {
  695. DCHECK(thread_checker_.CalledOnValidThread());
  696. DCHECK(predicate);
  697. uint32_t num_deleted = 0;
  698. for (auto it = cookies_.begin(); it != cookies_.end();) {
  699. auto curit = it;
  700. CanonicalCookie* cc = curit->second.get();
  701. ++it;
  702. if (predicate.Run(*cc)) {
  703. InternalDeleteCookie(curit, true /*sync_to_store*/, cause);
  704. ++num_deleted;
  705. }
  706. }
  707. for (auto partition_it = partitioned_cookies_.begin();
  708. partition_it != partitioned_cookies_.end();) {
  709. // InternalDeletePartitionedCookie may invalidate |partition_it| if that
  710. // cookie partition only has one cookie.
  711. auto cur_partition_it = partition_it;
  712. CookieMap::iterator cookie_it = cur_partition_it->second->begin();
  713. CookieMap::iterator cookie_end = cur_partition_it->second->end();
  714. ++partition_it;
  715. while (cookie_it != cookie_end) {
  716. auto cur_cookie_it = cookie_it;
  717. CanonicalCookie* cc = cur_cookie_it->second.get();
  718. ++cookie_it;
  719. if (predicate.Run(*cc)) {
  720. InternalDeletePartitionedCookie(cur_partition_it, cur_cookie_it, true,
  721. cause);
  722. ++num_deleted;
  723. }
  724. }
  725. }
  726. FlushStore(
  727. base::BindOnce(&MaybeRunDeleteCallback, weak_ptr_factory_.GetWeakPtr(),
  728. callback ? base::BindOnce(std::move(callback), num_deleted)
  729. : base::OnceClosure()));
  730. }
  731. void CookieMonster::MarkCookieStoreAsInitialized() {
  732. DCHECK(thread_checker_.CalledOnValidThread());
  733. initialized_ = true;
  734. }
  735. void CookieMonster::FetchAllCookiesIfNecessary() {
  736. DCHECK(thread_checker_.CalledOnValidThread());
  737. if (store_.get() && !started_fetching_all_cookies_) {
  738. started_fetching_all_cookies_ = true;
  739. FetchAllCookies();
  740. }
  741. }
  742. void CookieMonster::FetchAllCookies() {
  743. DCHECK(thread_checker_.CalledOnValidThread());
  744. DCHECK(store_.get()) << "Store must exist to initialize";
  745. DCHECK(!finished_fetching_all_cookies_)
  746. << "All cookies have already been fetched.";
  747. // We bind in the current time so that we can report the wall-clock time for
  748. // loading cookies.
  749. store_->Load(base::BindOnce(&CookieMonster::OnLoaded,
  750. weak_ptr_factory_.GetWeakPtr(), TimeTicks::Now()),
  751. net_log_);
  752. }
  753. void CookieMonster::OnLoaded(
  754. TimeTicks beginning_time,
  755. std::vector<std::unique_ptr<CanonicalCookie>> cookies) {
  756. DCHECK(thread_checker_.CalledOnValidThread());
  757. StoreLoadedCookies(std::move(cookies));
  758. base::UmaHistogramCustomTimes("Cookie.TimeBlockedOnLoad",
  759. base::TimeTicks::Now() - beginning_time,
  760. base::Milliseconds(1), base::Minutes(1), 50);
  761. // Invoke the task queue of cookie request.
  762. InvokeQueue();
  763. }
  764. void CookieMonster::OnKeyLoaded(
  765. const std::string& key,
  766. std::vector<std::unique_ptr<CanonicalCookie>> cookies) {
  767. DCHECK(thread_checker_.CalledOnValidThread());
  768. StoreLoadedCookies(std::move(cookies));
  769. auto tasks_pending_for_key = tasks_pending_for_key_.find(key);
  770. // TODO(mmenke): Can this be turned into a DCHECK?
  771. if (tasks_pending_for_key == tasks_pending_for_key_.end())
  772. return;
  773. // Run all tasks for the key. Note that running a task can result in multiple
  774. // tasks being added to the back of the deque.
  775. while (!tasks_pending_for_key->second.empty()) {
  776. base::OnceClosure task = std::move(tasks_pending_for_key->second.front());
  777. tasks_pending_for_key->second.pop_front();
  778. std::move(task).Run();
  779. }
  780. tasks_pending_for_key_.erase(tasks_pending_for_key);
  781. // This has to be done last, in case running a task queues a new task for the
  782. // key, to ensure tasks are run in the correct order.
  783. keys_loaded_.insert(key);
  784. }
  785. void CookieMonster::StoreLoadedCookies(
  786. std::vector<std::unique_ptr<CanonicalCookie>> cookies) {
  787. DCHECK(thread_checker_.CalledOnValidThread());
  788. // Even if a key is expired, insert it so it can be garbage collected,
  789. // removed, and sync'd.
  790. CookieItVector cookies_with_control_chars;
  791. std::vector<PartitionedCookieMapIterators>
  792. partitioned_cookies_with_control_chars;
  793. for (auto& cookie : cookies) {
  794. CanonicalCookie* cookie_ptr = cookie.get();
  795. CookieAccessResult access_result;
  796. access_result.access_semantics = CookieAccessSemantics::UNKNOWN;
  797. if (cookie_ptr->IsPartitioned()) {
  798. auto inserted = InternalInsertPartitionedCookie(
  799. GetKey(cookie_ptr->Domain()), std::move(cookie),
  800. false /* sync_to_store */, access_result,
  801. false /* dispatch_change */);
  802. if (ContainsControlCharacter(cookie_ptr->Name()) ||
  803. ContainsControlCharacter(cookie_ptr->Value())) {
  804. partitioned_cookies_with_control_chars.push_back(inserted);
  805. }
  806. } else {
  807. auto inserted =
  808. InternalInsertCookie(GetKey(cookie_ptr->Domain()), std::move(cookie),
  809. false /* sync_to_store */, access_result,
  810. false /* dispatch_change */);
  811. if (ContainsControlCharacter(cookie_ptr->Name()) ||
  812. ContainsControlCharacter(cookie_ptr->Value())) {
  813. cookies_with_control_chars.push_back(inserted);
  814. }
  815. }
  816. const Time cookie_access_time(cookie_ptr->LastAccessDate());
  817. if (earliest_access_time_.is_null() ||
  818. cookie_access_time < earliest_access_time_) {
  819. earliest_access_time_ = cookie_access_time;
  820. }
  821. }
  822. // Any cookies that contain control characters that we have loaded from the
  823. // persistent store should be deleted. See http://crbug.com/238041.
  824. for (auto it = cookies_with_control_chars.begin();
  825. it != cookies_with_control_chars.end();) {
  826. auto curit = it;
  827. ++it;
  828. InternalDeleteCookie(*curit, true, DELETE_COOKIE_CONTROL_CHAR);
  829. }
  830. for (auto it = partitioned_cookies_with_control_chars.begin();
  831. it != partitioned_cookies_with_control_chars.end();) {
  832. // InternalDeletePartitionedCookie may invalidate the current iterator, so
  833. // we increment the iterator in the loop before calling the function.
  834. auto curit = it;
  835. ++it;
  836. InternalDeletePartitionedCookie(curit->first, curit->second, true,
  837. DELETE_COOKIE_CONTROL_CHAR);
  838. }
  839. // After importing cookies from the PersistentCookieStore, verify that
  840. // none of our other constraints are violated.
  841. // In particular, the backing store might have given us duplicate cookies.
  842. // This method could be called multiple times due to priority loading, thus
  843. // cookies loaded in previous runs will be validated again, but this is OK
  844. // since they are expected to be much fewer than total DB.
  845. EnsureCookiesMapIsValid();
  846. }
  847. void CookieMonster::InvokeQueue() {
  848. DCHECK(thread_checker_.CalledOnValidThread());
  849. // Move all per-key tasks into the global queue, if there are any. This is
  850. // protection about a race where the store learns about all cookies loading
  851. // before it learned about the cookies for a key loading.
  852. // Needed to prevent any recursively queued tasks from going back into the
  853. // per-key queues.
  854. seen_global_task_ = true;
  855. for (auto& tasks_for_key : tasks_pending_for_key_) {
  856. tasks_pending_.insert(tasks_pending_.begin(),
  857. std::make_move_iterator(tasks_for_key.second.begin()),
  858. std::make_move_iterator(tasks_for_key.second.end()));
  859. }
  860. tasks_pending_for_key_.clear();
  861. while (!tasks_pending_.empty()) {
  862. base::OnceClosure request_task = std::move(tasks_pending_.front());
  863. tasks_pending_.pop_front();
  864. std::move(request_task).Run();
  865. }
  866. DCHECK(tasks_pending_for_key_.empty());
  867. finished_fetching_all_cookies_ = true;
  868. keys_loaded_.clear();
  869. }
  870. void CookieMonster::EnsureCookiesMapIsValid() {
  871. DCHECK(thread_checker_.CalledOnValidThread());
  872. // Iterate through all the of the cookies, grouped by host.
  873. for (auto next = cookies_.begin(); next != cookies_.end();) {
  874. auto cur_range_begin = next;
  875. const std::string key = cur_range_begin->first; // Keep a copy.
  876. auto cur_range_end = cookies_.upper_bound(key);
  877. next = cur_range_end;
  878. // Ensure no equivalent cookies for this host.
  879. TrimDuplicateCookiesForKey(key, cur_range_begin, cur_range_end,
  880. absl::nullopt);
  881. }
  882. for (auto cookie_partition_it = partitioned_cookies_.begin();
  883. cookie_partition_it != partitioned_cookies_.end();) {
  884. auto cur_cookie_partition_it = cookie_partition_it;
  885. ++cookie_partition_it;
  886. // Iterate through the cookies in this partition, grouped by host.
  887. CookieMap* cookie_partition = cur_cookie_partition_it->second.get();
  888. auto prev_range_end = cookie_partition->begin();
  889. while (prev_range_end != cookie_partition->end()) {
  890. auto cur_range_begin = prev_range_end;
  891. const std::string key = cur_range_begin->first; // Keep a copy.
  892. auto cur_range_end = cookie_partition->upper_bound(key);
  893. prev_range_end = cur_range_end;
  894. // Ensure no equivalent cookies for this host and cookie partition key.
  895. TrimDuplicateCookiesForKey(key, cur_range_begin, cur_range_end,
  896. absl::make_optional(cur_cookie_partition_it));
  897. }
  898. }
  899. }
  900. // Our strategy to find duplicates is:
  901. // (1) Build a map from cookie unique key to
  902. // {list of cookies with this signature, sorted by creation time}.
  903. // (2) For each list with more than 1 entry, keep the cookie having the
  904. // most recent creation time, and delete the others.
  905. //
  906. void CookieMonster::TrimDuplicateCookiesForKey(
  907. const std::string& key,
  908. CookieMap::iterator begin,
  909. CookieMap::iterator end,
  910. absl::optional<PartitionedCookieMap::iterator> cookie_partition_it) {
  911. DCHECK(thread_checker_.CalledOnValidThread());
  912. // Set of cookies ordered by creation time.
  913. typedef std::multiset<CookieMap::iterator, OrderByCreationTimeDesc> CookieSet;
  914. // Helper map we populate to find the duplicates.
  915. typedef std::map<CanonicalCookie::UniqueCookieKey, CookieSet> EquivalenceMap;
  916. EquivalenceMap equivalent_cookies;
  917. // The number of duplicate cookies that have been found.
  918. int num_duplicates = 0;
  919. // Iterate through all of the cookies in our range, and insert them into
  920. // the equivalence map.
  921. for (auto it = begin; it != end; ++it) {
  922. DCHECK_EQ(key, it->first);
  923. CanonicalCookie* cookie = it->second.get();
  924. CanonicalCookie::UniqueCookieKey signature(cookie->UniqueKey());
  925. CookieSet& set = equivalent_cookies[signature];
  926. // We found a duplicate!
  927. if (!set.empty())
  928. num_duplicates++;
  929. // We save the iterator into |cookies_| rather than the actual cookie
  930. // pointer, since we may need to delete it later.
  931. set.insert(it);
  932. }
  933. // If there were no duplicates, we are done!
  934. if (num_duplicates == 0)
  935. return;
  936. // Make sure we find everything below that we did above.
  937. int num_duplicates_found = 0;
  938. // Otherwise, delete all the duplicate cookies, both from our in-memory store
  939. // and from the backing store.
  940. for (std::pair<const CanonicalCookie::UniqueCookieKey, CookieSet>&
  941. equivalent_cookie : equivalent_cookies) {
  942. const CanonicalCookie::UniqueCookieKey& signature = equivalent_cookie.first;
  943. CookieSet& dupes = equivalent_cookie.second;
  944. if (dupes.size() <= 1)
  945. continue; // This cookiename/path has no duplicates.
  946. num_duplicates_found += dupes.size() - 1;
  947. // Since |dupes| is sorted by creation time (descending), the first cookie
  948. // is the most recent one (or tied for it), so we will keep it. The rest are
  949. // duplicates.
  950. dupes.erase(dupes.begin());
  951. // TODO(crbug.com/1225444) Include cookie partition key in this log
  952. // statement as well if needed.
  953. LOG(ERROR) << base::StringPrintf(
  954. "Found %d duplicate cookies for key='%s', "
  955. "with {name='%s', domain='%s', path='%s'}",
  956. static_cast<int>(dupes.size()), key.c_str(),
  957. std::get<1>(signature).c_str(), std::get<2>(signature).c_str(),
  958. std::get<3>(signature).c_str());
  959. // Remove all the cookies identified by |dupes|. It is valid to delete our
  960. // list of iterators one at a time, since |cookies_| is a multimap (they
  961. // don't invalidate existing iterators following deletion).
  962. for (const CookieMap::iterator& dupe : dupes) {
  963. if (cookie_partition_it) {
  964. InternalDeletePartitionedCookie(
  965. cookie_partition_it.value(), dupe, true,
  966. DELETE_COOKIE_DUPLICATE_IN_BACKING_STORE);
  967. } else {
  968. InternalDeleteCookie(dupe, true,
  969. DELETE_COOKIE_DUPLICATE_IN_BACKING_STORE);
  970. }
  971. }
  972. }
  973. DCHECK_EQ(num_duplicates, num_duplicates_found);
  974. }
  975. std::vector<CanonicalCookie*>
  976. CookieMonster::FindCookiesForRegistryControlledHost(const GURL& url,
  977. CookieMap* cookie_map) {
  978. DCHECK(thread_checker_.CalledOnValidThread());
  979. if (!cookie_map)
  980. cookie_map = &cookies_;
  981. Time current_time = Time::Now();
  982. // Retrieve all cookies for a given key
  983. const std::string key(GetKey(url.host_piece()));
  984. std::vector<CanonicalCookie*> cookies;
  985. for (CookieMapItPair its = cookie_map->equal_range(key);
  986. its.first != its.second;) {
  987. auto curit = its.first;
  988. CanonicalCookie* cc = curit->second.get();
  989. ++its.first;
  990. // If the cookie is expired, delete it.
  991. if (cc->IsExpired(current_time)) {
  992. InternalDeleteCookie(curit, true, DELETE_COOKIE_EXPIRED);
  993. continue;
  994. }
  995. cookies.push_back(cc);
  996. }
  997. return cookies;
  998. }
  999. std::vector<CanonicalCookie*>
  1000. CookieMonster::FindPartitionedCookiesForRegistryControlledHost(
  1001. const CookiePartitionKey& cookie_partition_key,
  1002. const GURL& url) {
  1003. DCHECK(thread_checker_.CalledOnValidThread());
  1004. PartitionedCookieMap::iterator it =
  1005. partitioned_cookies_.find(cookie_partition_key);
  1006. if (it == partitioned_cookies_.end())
  1007. return std::vector<CanonicalCookie*>();
  1008. return FindCookiesForRegistryControlledHost(url, it->second.get());
  1009. }
  1010. void CookieMonster::FilterCookiesWithOptions(
  1011. const GURL url,
  1012. const CookieOptions options,
  1013. std::vector<CanonicalCookie*>* cookie_ptrs,
  1014. CookieAccessResultList* included_cookies,
  1015. CookieAccessResultList* excluded_cookies) {
  1016. DCHECK(thread_checker_.CalledOnValidThread());
  1017. // Probe to save statistics relatively frequently. We do it here rather
  1018. // than in the set path as many websites won't set cookies, and we
  1019. // want to collect statistics whenever the browser's being used.
  1020. Time current_time = Time::Now();
  1021. RecordPeriodicStats(current_time);
  1022. bool delegate_treats_url_as_trustworthy =
  1023. cookie_access_delegate() &&
  1024. cookie_access_delegate()->ShouldTreatUrlAsTrustworthy(url);
  1025. for (CanonicalCookie* cookie_ptr : *cookie_ptrs) {
  1026. // Filter out cookies that should not be included for a request to the
  1027. // given |url|. HTTP only cookies are filtered depending on the passed
  1028. // cookie |options|.
  1029. CookieAccessResult access_result = cookie_ptr->IncludeForRequestURL(
  1030. url, options,
  1031. CookieAccessParams{
  1032. GetAccessSemanticsForCookie(*cookie_ptr),
  1033. delegate_treats_url_as_trustworthy,
  1034. cookie_util::GetSamePartyStatus(*cookie_ptr, options,
  1035. first_party_sets_enabled_)});
  1036. if (!access_result.status.IsInclude()) {
  1037. UMA_HISTOGRAM_BOOLEAN(
  1038. "Cookie.SameParty.ReadExclusionDecidedBySameParty",
  1039. access_result.status.HasOnlyExclusionReason(
  1040. CookieInclusionStatus::EXCLUDE_SAMEPARTY_CROSS_PARTY_CONTEXT));
  1041. if (options.return_excluded_cookies())
  1042. excluded_cookies->push_back({*cookie_ptr, access_result});
  1043. continue;
  1044. }
  1045. if (options.update_access_time())
  1046. InternalUpdateCookieAccessTime(cookie_ptr, current_time);
  1047. int destination_port = url.EffectiveIntPort();
  1048. if (IsLocalhost(url)) {
  1049. UMA_HISTOGRAM_ENUMERATION(
  1050. "Cookie.Port.Read.Localhost",
  1051. ReducePortRangeForCookieHistogram(destination_port));
  1052. UMA_HISTOGRAM_ENUMERATION(
  1053. "Cookie.Port.ReadDiffersFromSet.Localhost",
  1054. IsCookieSentToSamePortThatSetIt(url, cookie_ptr->SourcePort(),
  1055. cookie_ptr->SourceScheme()));
  1056. } else {
  1057. UMA_HISTOGRAM_ENUMERATION(
  1058. "Cookie.Port.Read.RemoteHost",
  1059. ReducePortRangeForCookieHistogram(destination_port));
  1060. UMA_HISTOGRAM_ENUMERATION(
  1061. "Cookie.Port.ReadDiffersFromSet.RemoteHost",
  1062. IsCookieSentToSamePortThatSetIt(url, cookie_ptr->SourcePort(),
  1063. cookie_ptr->SourceScheme()));
  1064. }
  1065. if (cookie_ptr->IsDomainCookie()) {
  1066. UMA_HISTOGRAM_ENUMERATION(
  1067. "Cookie.Port.ReadDiffersFromSet.DomainSet",
  1068. IsCookieSentToSamePortThatSetIt(url, cookie_ptr->SourcePort(),
  1069. cookie_ptr->SourceScheme()));
  1070. }
  1071. if (cookie_ptr->IsSameParty()) {
  1072. UMA_HISTOGRAM_BOOLEAN("Cookie.SamePartyReadIncluded.IsHTTP",
  1073. !options.exclude_httponly());
  1074. UMA_HISTOGRAM_EXACT_LINEAR(
  1075. "Cookie.SamePartyReadIncluded.PartyContextSize",
  1076. options.full_party_context_size(),
  1077. 1 + IsolationInfo::kPartyContextMaxSize);
  1078. }
  1079. included_cookies->push_back({*cookie_ptr, access_result});
  1080. }
  1081. }
  1082. void CookieMonster::MaybeDeleteEquivalentCookieAndUpdateStatus(
  1083. const std::string& key,
  1084. const CanonicalCookie& cookie_being_set,
  1085. bool allowed_to_set_secure_cookie,
  1086. bool skip_httponly,
  1087. bool already_expired,
  1088. base::Time* creation_date_to_inherit,
  1089. CookieInclusionStatus* status,
  1090. absl::optional<PartitionedCookieMap::iterator> cookie_partition_it) {
  1091. DCHECK(thread_checker_.CalledOnValidThread());
  1092. DCHECK(!status->HasExclusionReason(
  1093. CookieInclusionStatus::EXCLUDE_OVERWRITE_SECURE));
  1094. DCHECK(!status->HasExclusionReason(
  1095. CookieInclusionStatus::EXCLUDE_OVERWRITE_HTTP_ONLY));
  1096. CookieMap* cookie_map = &cookies_;
  1097. if (cookie_partition_it) {
  1098. cookie_map = cookie_partition_it.value()->second.get();
  1099. }
  1100. bool found_equivalent_cookie = false;
  1101. CookieMap::iterator deletion_candidate_it = cookie_map->end();
  1102. CanonicalCookie* skipped_secure_cookie = nullptr;
  1103. // Check every cookie matching this domain key for equivalence.
  1104. CookieMapItPair range_its = cookie_map->equal_range(key);
  1105. for (auto cur_it = range_its.first; cur_it != range_its.second; ++cur_it) {
  1106. CanonicalCookie* cur_existing_cookie = cur_it->second.get();
  1107. // Evaluate "Leave Secure Cookies Alone":
  1108. // If the cookie is being set from an insecure source, then if an
  1109. // "equivalent" Secure cookie already exists, then the cookie should *not*
  1110. // be updated.
  1111. //
  1112. // "Equivalent" means they are the same by
  1113. // IsEquivalentForSecureCookieMatching(). See the comment there for
  1114. // details. (Note this is not a symmetric comparison.) This notion of
  1115. // equivalence is slightly more inclusive than the usual IsEquivalent() one.
  1116. //
  1117. // See: https://tools.ietf.org/html/draft-ietf-httpbis-cookie-alone
  1118. if (cur_existing_cookie->IsSecure() && !allowed_to_set_secure_cookie &&
  1119. cookie_being_set.IsEquivalentForSecureCookieMatching(
  1120. *cur_existing_cookie)) {
  1121. // Hold onto this for additional Netlogging later if we end up preserving
  1122. // a would-have-been-deleted cookie because of this.
  1123. skipped_secure_cookie = cur_existing_cookie;
  1124. net_log_.AddEvent(NetLogEventType::COOKIE_STORE_COOKIE_REJECTED_SECURE,
  1125. [&](NetLogCaptureMode capture_mode) {
  1126. return NetLogCookieMonsterCookieRejectedSecure(
  1127. skipped_secure_cookie, &cookie_being_set,
  1128. capture_mode);
  1129. });
  1130. status->AddExclusionReason(
  1131. CookieInclusionStatus::EXCLUDE_OVERWRITE_SECURE);
  1132. }
  1133. if (cookie_being_set.IsEquivalent(*cur_existing_cookie)) {
  1134. // We should never have more than one equivalent cookie, since they should
  1135. // overwrite each other.
  1136. CHECK(!found_equivalent_cookie)
  1137. << "Duplicate equivalent cookies found, cookie store is corrupted.";
  1138. DCHECK(deletion_candidate_it == cookie_map->end());
  1139. found_equivalent_cookie = true;
  1140. // The |cookie_being_set| is rejected for trying to overwrite an httponly
  1141. // cookie when it should not be able to.
  1142. if (skip_httponly && cur_existing_cookie->IsHttpOnly()) {
  1143. net_log_.AddEvent(
  1144. NetLogEventType::COOKIE_STORE_COOKIE_REJECTED_HTTPONLY,
  1145. [&](NetLogCaptureMode capture_mode) {
  1146. return NetLogCookieMonsterCookieRejectedHttponly(
  1147. cur_existing_cookie, &cookie_being_set, capture_mode);
  1148. });
  1149. status->AddExclusionReason(
  1150. CookieInclusionStatus::EXCLUDE_OVERWRITE_HTTP_ONLY);
  1151. } else {
  1152. deletion_candidate_it = cur_it;
  1153. }
  1154. }
  1155. }
  1156. if (deletion_candidate_it != cookie_map->end()) {
  1157. CanonicalCookie* deletion_candidate = deletion_candidate_it->second.get();
  1158. if (deletion_candidate->Value() == cookie_being_set.Value())
  1159. *creation_date_to_inherit = deletion_candidate->CreationDate();
  1160. if (status->IsInclude()) {
  1161. if (cookie_being_set.IsPartitioned()) {
  1162. InternalDeletePartitionedCookie(
  1163. cookie_partition_it.value(), deletion_candidate_it,
  1164. true /* sync_to_store */,
  1165. already_expired ? DELETE_COOKIE_EXPIRED_OVERWRITE
  1166. : DELETE_COOKIE_OVERWRITE);
  1167. } else {
  1168. InternalDeleteCookie(deletion_candidate_it, true /* sync_to_store */,
  1169. already_expired ? DELETE_COOKIE_EXPIRED_OVERWRITE
  1170. : DELETE_COOKIE_OVERWRITE);
  1171. }
  1172. } else if (status->HasExclusionReason(
  1173. CookieInclusionStatus::EXCLUDE_OVERWRITE_SECURE)) {
  1174. // Log that we preserved a cookie that would have been deleted due to
  1175. // Leave Secure Cookies Alone. This arbitrarily only logs the last
  1176. // |skipped_secure_cookie| that we were left with after the for loop, even
  1177. // if there were multiple matching Secure cookies that were left alone.
  1178. DCHECK(skipped_secure_cookie);
  1179. net_log_.AddEvent(
  1180. NetLogEventType::COOKIE_STORE_COOKIE_PRESERVED_SKIPPED_SECURE,
  1181. [&](NetLogCaptureMode capture_mode) {
  1182. return NetLogCookieMonsterCookiePreservedSkippedSecure(
  1183. skipped_secure_cookie, deletion_candidate, &cookie_being_set,
  1184. capture_mode);
  1185. });
  1186. }
  1187. }
  1188. }
  1189. CookieMonster::CookieMap::iterator CookieMonster::InternalInsertCookie(
  1190. const std::string& key,
  1191. std::unique_ptr<CanonicalCookie> cc,
  1192. bool sync_to_store,
  1193. const CookieAccessResult& access_result,
  1194. bool dispatch_change) {
  1195. DCHECK(thread_checker_.CalledOnValidThread());
  1196. CanonicalCookie* cc_ptr = cc.get();
  1197. net_log_.AddEvent(NetLogEventType::COOKIE_STORE_COOKIE_ADDED,
  1198. [&](NetLogCaptureMode capture_mode) {
  1199. return NetLogCookieMonsterCookieAdded(
  1200. cc.get(), sync_to_store, capture_mode);
  1201. });
  1202. if (ShouldUpdatePersistentStore(cc_ptr) && sync_to_store)
  1203. store_->AddCookie(*cc_ptr);
  1204. auto inserted = cookies_.insert(CookieMap::value_type(key, std::move(cc)));
  1205. LogCookieTypeToUMA(cc_ptr, access_result);
  1206. DCHECK(access_result.status.IsInclude());
  1207. if (dispatch_change) {
  1208. change_dispatcher_.DispatchChange(
  1209. CookieChangeInfo(*cc_ptr, access_result, CookieChangeCause::INSERTED),
  1210. true);
  1211. }
  1212. // If this is the first cookie in |cookies_| with this key, increment the
  1213. // |num_keys_| counter.
  1214. bool different_prev =
  1215. inserted == cookies_.begin() || std::prev(inserted)->first != key;
  1216. // According to std::multiqueue documentation:
  1217. // "If the container has elements with equivalent key, inserts at the upper
  1218. // bound of that range. (since C++11)"
  1219. // This means that "inserted" iterator either points to the last element in
  1220. // the map, or the element succeeding it has to have different key.
  1221. DCHECK(std::next(inserted) == cookies_.end() ||
  1222. std::next(inserted)->first != key);
  1223. if (different_prev)
  1224. ++num_keys_;
  1225. return inserted;
  1226. }
  1227. bool CookieMonster::ShouldUpdatePersistentStore(CanonicalCookie* cc) {
  1228. return (cc->IsPersistent() || persist_session_cookies_) && store_.get();
  1229. }
  1230. void CookieMonster::LogCookieTypeToUMA(
  1231. CanonicalCookie* cc,
  1232. const CookieAccessResult& access_result) {
  1233. int32_t type_sample =
  1234. !cc->IsEffectivelySameSiteNone(access_result.access_semantics)
  1235. ? 1 << COOKIE_TYPE_SAME_SITE
  1236. : 0;
  1237. type_sample |= cc->IsHttpOnly() ? 1 << COOKIE_TYPE_HTTPONLY : 0;
  1238. type_sample |= cc->IsSecure() ? 1 << COOKIE_TYPE_SECURE : 0;
  1239. UMA_HISTOGRAM_EXACT_LINEAR("Cookie.Type", type_sample,
  1240. (1 << COOKIE_TYPE_LAST_ENTRY));
  1241. }
  1242. CookieMonster::PartitionedCookieMapIterators
  1243. CookieMonster::InternalInsertPartitionedCookie(
  1244. std::string key,
  1245. std::unique_ptr<CanonicalCookie> cc,
  1246. bool sync_to_store,
  1247. const CookieAccessResult& access_result,
  1248. bool dispatch_change) {
  1249. DCHECK(cc->IsPartitioned());
  1250. DCHECK(thread_checker_.CalledOnValidThread());
  1251. CanonicalCookie* cc_ptr = cc.get();
  1252. net_log_.AddEvent(NetLogEventType::COOKIE_STORE_COOKIE_ADDED,
  1253. [&](NetLogCaptureMode capture_mode) {
  1254. return NetLogCookieMonsterCookieAdded(
  1255. cc.get(), sync_to_store, capture_mode);
  1256. });
  1257. if (ShouldUpdatePersistentStore(cc_ptr) && sync_to_store)
  1258. store_->AddCookie(*cc_ptr);
  1259. CookiePartitionKey partition_key(cc->PartitionKey().value());
  1260. PartitionedCookieMap::iterator partition_it =
  1261. partitioned_cookies_.find(partition_key);
  1262. if (partition_it == partitioned_cookies_.end()) {
  1263. partition_it =
  1264. partitioned_cookies_
  1265. .insert(PartitionedCookieMap::value_type(
  1266. std::move(partition_key), std::make_unique<CookieMap>()))
  1267. .first;
  1268. }
  1269. CookieMap::iterator cookie_it = partition_it->second->insert(
  1270. CookieMap::value_type(std::move(key), std::move(cc)));
  1271. ++num_partitioned_cookies_;
  1272. LogCookieTypeToUMA(cc_ptr, access_result);
  1273. DCHECK(access_result.status.IsInclude());
  1274. if (dispatch_change) {
  1275. change_dispatcher_.DispatchChange(
  1276. CookieChangeInfo(*cc_ptr, access_result, CookieChangeCause::INSERTED),
  1277. true);
  1278. }
  1279. return std::make_pair(partition_it, cookie_it);
  1280. }
  1281. void CookieMonster::SetCanonicalCookie(
  1282. std::unique_ptr<CanonicalCookie> cc,
  1283. const GURL& source_url,
  1284. const CookieOptions& options,
  1285. SetCookiesCallback callback,
  1286. absl::optional<CookieAccessResult> cookie_access_result) {
  1287. DCHECK(thread_checker_.CalledOnValidThread());
  1288. bool delegate_treats_url_as_trustworthy =
  1289. cookie_access_delegate() &&
  1290. cookie_access_delegate()->ShouldTreatUrlAsTrustworthy(source_url);
  1291. CookieAccessResult access_result = cc->IsSetPermittedInContext(
  1292. source_url, options,
  1293. CookieAccessParams(GetAccessSemanticsForCookie(*cc),
  1294. delegate_treats_url_as_trustworthy,
  1295. cookie_util::GetSamePartyStatus(
  1296. *cc, options, first_party_sets_enabled_)),
  1297. cookieable_schemes_, cookie_access_result);
  1298. const std::string key(GetKey(cc->Domain()));
  1299. base::Time creation_date = cc->CreationDate();
  1300. if (creation_date.is_null()) {
  1301. creation_date = Time::Now();
  1302. cc->SetCreationDate(creation_date);
  1303. }
  1304. bool already_expired = cc->IsExpired(creation_date);
  1305. base::Time creation_date_to_inherit;
  1306. absl::optional<PartitionedCookieMap::iterator> cookie_partition_it;
  1307. bool should_try_to_delete_duplicates = true;
  1308. if (cc->IsPartitioned()) {
  1309. auto it = partitioned_cookies_.find(cc->PartitionKey().value());
  1310. if (it == partitioned_cookies_.end()) {
  1311. // This is the first cookie in its partition, so it won't have any
  1312. // duplicates.
  1313. should_try_to_delete_duplicates = false;
  1314. } else {
  1315. cookie_partition_it = absl::make_optional(it);
  1316. }
  1317. }
  1318. // Iterates through existing cookies for the same eTLD+1, and potentially
  1319. // deletes an existing cookie, so any ExclusionReasons in |status| that would
  1320. // prevent such deletion should be finalized beforehand.
  1321. if (should_try_to_delete_duplicates) {
  1322. MaybeDeleteEquivalentCookieAndUpdateStatus(
  1323. key, *cc, access_result.is_allowed_to_access_secure_cookies,
  1324. options.exclude_httponly(), already_expired, &creation_date_to_inherit,
  1325. &access_result.status, cookie_partition_it);
  1326. }
  1327. if (access_result.status.HasExclusionReason(
  1328. CookieInclusionStatus::EXCLUDE_OVERWRITE_SECURE) ||
  1329. access_result.status.HasExclusionReason(
  1330. CookieInclusionStatus::EXCLUDE_OVERWRITE_HTTP_ONLY)) {
  1331. DVLOG(net::cookie_util::kVlogSetCookies)
  1332. << "SetCookie() not clobbering httponly cookie or secure cookie for "
  1333. "insecure scheme";
  1334. }
  1335. if (access_result.status.IsInclude()) {
  1336. DVLOG(net::cookie_util::kVlogSetCookies)
  1337. << "SetCookie() key: " << key << " cc: " << cc->DebugString();
  1338. if (cc->IsSameParty()) {
  1339. UMA_HISTOGRAM_BOOLEAN("Cookie.SamePartySetIncluded.IsHTTP",
  1340. !options.exclude_httponly());
  1341. UMA_HISTOGRAM_EXACT_LINEAR("Cookie.SamePartySetIncluded.PartyContextSize",
  1342. options.full_party_context_size(),
  1343. 1 + IsolationInfo::kPartyContextMaxSize);
  1344. }
  1345. bool is_partitioned_cookie = cc->IsPartitioned();
  1346. CookiePartitionKey cookie_partition_key;
  1347. if (is_partitioned_cookie)
  1348. cookie_partition_key = cc->PartitionKey().value();
  1349. // Realize that we might be setting an expired cookie, and the only point
  1350. // was to delete the cookie which we've already done.
  1351. if (!already_expired) {
  1352. HistogramExpirationDuration(*cc, creation_date);
  1353. // Histogram the type of scheme used on URLs that set cookies. This
  1354. // intentionally includes cookies that are set or overwritten by
  1355. // http:// URLs, but not cookies that are cleared by http:// URLs, to
  1356. // understand if the former behavior can be deprecated for Secure
  1357. // cookies.
  1358. // TODO(crbug.com/993120): Consider removing this histogram. The decision
  1359. // it was added to evaluate has been implemented and standardized.
  1360. CookieSource cookie_source_sample =
  1361. (source_url.SchemeIsCryptographic()
  1362. ? (cc->IsSecure()
  1363. ? CookieSource::kSecureCookieCryptographicScheme
  1364. : CookieSource::kNonsecureCookieCryptographicScheme)
  1365. : (cc->IsSecure()
  1366. ? CookieSource::kSecureCookieNoncryptographicScheme
  1367. : CookieSource::kNonsecureCookieNoncryptographicScheme));
  1368. UMA_HISTOGRAM_ENUMERATION("Cookie.CookieSourceScheme",
  1369. cookie_source_sample);
  1370. UMA_HISTOGRAM_BOOLEAN("Cookie.DomainSet", cc->IsDomainCookie());
  1371. if (!creation_date_to_inherit.is_null()) {
  1372. cc->SetCreationDate(creation_date_to_inherit);
  1373. }
  1374. if (is_partitioned_cookie) {
  1375. InternalInsertPartitionedCookie(key, std::move(cc), true,
  1376. access_result);
  1377. } else {
  1378. InternalInsertCookie(key, std::move(cc), true, access_result);
  1379. }
  1380. } else {
  1381. DVLOG(net::cookie_util::kVlogSetCookies)
  1382. << "SetCookie() not storing already expired cookie.";
  1383. }
  1384. // We assume that hopefully setting a cookie will be less common than
  1385. // querying a cookie. Since setting a cookie can put us over our limits,
  1386. // make sure that we garbage collect... We can also make the assumption
  1387. // that if a cookie was set, in the common case it will be used soon after,
  1388. // and we will purge the expired cookies in GetCookies().
  1389. if (is_partitioned_cookie) {
  1390. GarbageCollectPartitionedCookies(creation_date, cookie_partition_key,
  1391. key);
  1392. } else {
  1393. GarbageCollect(creation_date, key);
  1394. }
  1395. if (IsLocalhost(source_url)) {
  1396. UMA_HISTOGRAM_ENUMERATION(
  1397. "Cookie.Port.Set.Localhost",
  1398. ReducePortRangeForCookieHistogram(source_url.EffectiveIntPort()));
  1399. } else {
  1400. UMA_HISTOGRAM_ENUMERATION(
  1401. "Cookie.Port.Set.RemoteHost",
  1402. ReducePortRangeForCookieHistogram(source_url.EffectiveIntPort()));
  1403. }
  1404. UMA_HISTOGRAM_ENUMERATION("Cookie.CookieSourceSchemeName",
  1405. GetSchemeNameEnum(source_url));
  1406. } else {
  1407. UMA_HISTOGRAM_BOOLEAN(
  1408. "Cookie.SameParty.SetExclusionDecidedBySameParty",
  1409. access_result.status.HasOnlyExclusionReason(
  1410. CookieInclusionStatus::EXCLUDE_SAMEPARTY_CROSS_PARTY_CONTEXT));
  1411. }
  1412. // TODO(chlily): Log metrics.
  1413. MaybeRunCookieCallback(std::move(callback), access_result);
  1414. }
  1415. void CookieMonster::SetAllCookies(CookieList list,
  1416. SetCookiesCallback callback) {
  1417. DCHECK(thread_checker_.CalledOnValidThread());
  1418. // Nuke the existing store.
  1419. while (!cookies_.empty()) {
  1420. // TODO(rdsmith): The CANONICAL is a lie.
  1421. InternalDeleteCookie(cookies_.begin(), true, DELETE_COOKIE_EXPLICIT);
  1422. }
  1423. // Set all passed in cookies.
  1424. for (const auto& cookie : list) {
  1425. const std::string key(GetKey(cookie.Domain()));
  1426. Time creation_time = cookie.CreationDate();
  1427. if (cookie.IsExpired(creation_time))
  1428. continue;
  1429. HistogramExpirationDuration(cookie, creation_time);
  1430. CookieAccessResult access_result;
  1431. access_result.access_semantics = GetAccessSemanticsForCookie(cookie);
  1432. if (cookie.IsPartitioned()) {
  1433. InternalInsertPartitionedCookie(
  1434. key, std::make_unique<CanonicalCookie>(cookie), true, access_result);
  1435. GarbageCollectPartitionedCookies(creation_time,
  1436. cookie.PartitionKey().value(), key);
  1437. } else {
  1438. InternalInsertCookie(key, std::make_unique<CanonicalCookie>(cookie), true,
  1439. access_result);
  1440. GarbageCollect(creation_time, key);
  1441. }
  1442. }
  1443. // TODO(rdsmith): If this function always returns the same value, it
  1444. // shouldn't have a return value. But it should also be deleted (see
  1445. // https://codereview.chromium.org/2882063002/#msg64), which would
  1446. // solve the return value problem.
  1447. MaybeRunCookieCallback(std::move(callback), CookieAccessResult());
  1448. }
  1449. void CookieMonster::InternalUpdateCookieAccessTime(CanonicalCookie* cc,
  1450. const Time& current) {
  1451. DCHECK(thread_checker_.CalledOnValidThread());
  1452. // Based off the Mozilla code. When a cookie has been accessed recently,
  1453. // don't bother updating its access time again. This reduces the number of
  1454. // updates we do during pageload, which in turn reduces the chance our storage
  1455. // backend will hit its batch thresholds and be forced to update.
  1456. if ((current - cc->LastAccessDate()) < last_access_threshold_)
  1457. return;
  1458. cc->SetLastAccessDate(current);
  1459. if (ShouldUpdatePersistentStore(cc))
  1460. store_->UpdateCookieAccessTime(*cc);
  1461. }
  1462. // InternalDeleteCookies must not invalidate iterators other than the one being
  1463. // deleted.
  1464. void CookieMonster::InternalDeleteCookie(CookieMap::iterator it,
  1465. bool sync_to_store,
  1466. DeletionCause deletion_cause) {
  1467. DCHECK(thread_checker_.CalledOnValidThread());
  1468. // Ideally, this would be asserted up where we define kChangeCauseMapping,
  1469. // but DeletionCause's visibility (or lack thereof) forces us to make
  1470. // this check here.
  1471. static_assert(std::size(kChangeCauseMapping) == DELETE_COOKIE_LAST_ENTRY + 1,
  1472. "kChangeCauseMapping size should match DeletionCause size");
  1473. CanonicalCookie* cc = it->second.get();
  1474. DVLOG(net::cookie_util::kVlogSetCookies)
  1475. << "InternalDeleteCookie()"
  1476. << ", cause:" << deletion_cause << ", cc: " << cc->DebugString();
  1477. ChangeCausePair mapping = kChangeCauseMapping[deletion_cause];
  1478. if (deletion_cause != DELETE_COOKIE_DONT_RECORD) {
  1479. net_log_.AddEvent(NetLogEventType::COOKIE_STORE_COOKIE_DELETED,
  1480. [&](NetLogCaptureMode capture_mode) {
  1481. return NetLogCookieMonsterCookieDeleted(
  1482. cc, mapping.cause, sync_to_store, capture_mode);
  1483. });
  1484. }
  1485. if (ShouldUpdatePersistentStore(cc) && sync_to_store)
  1486. store_->DeleteCookie(*cc);
  1487. change_dispatcher_.DispatchChange(
  1488. CookieChangeInfo(
  1489. *cc,
  1490. CookieAccessResult(CookieEffectiveSameSite::UNDEFINED,
  1491. CookieInclusionStatus(),
  1492. GetAccessSemanticsForCookie(*cc),
  1493. true /* is_allowed_to_access_secure_cookies */),
  1494. mapping.cause),
  1495. mapping.notify);
  1496. // If this is the last cookie in |cookies_| with this key, decrement the
  1497. // |num_keys_| counter.
  1498. bool different_prev =
  1499. it == cookies_.begin() || std::prev(it)->first != it->first;
  1500. bool different_next =
  1501. std::next(it) == cookies_.end() || std::next(it)->first != it->first;
  1502. if (different_prev && different_next)
  1503. --num_keys_;
  1504. cookies_.erase(it);
  1505. }
  1506. void CookieMonster::InternalDeletePartitionedCookie(
  1507. PartitionedCookieMap::iterator partition_it,
  1508. CookieMap::iterator cookie_it,
  1509. bool sync_to_store,
  1510. DeletionCause deletion_cause) {
  1511. DCHECK(thread_checker_.CalledOnValidThread());
  1512. // Ideally, this would be asserted up where we define kChangeCauseMapping,
  1513. // but DeletionCause's visibility (or lack thereof) forces us to make
  1514. // this check here.
  1515. static_assert(std::size(kChangeCauseMapping) == DELETE_COOKIE_LAST_ENTRY + 1,
  1516. "kChangeCauseMapping size should match DeletionCause size");
  1517. CanonicalCookie* cc = cookie_it->second.get();
  1518. DCHECK(cc->IsPartitioned());
  1519. DVLOG(net::cookie_util::kVlogSetCookies)
  1520. << "InternalDeletePartitionedCookie()"
  1521. << ", cause:" << deletion_cause << ", cc: " << cc->DebugString();
  1522. ChangeCausePair mapping = kChangeCauseMapping[deletion_cause];
  1523. if (deletion_cause != DELETE_COOKIE_DONT_RECORD) {
  1524. net_log_.AddEvent(NetLogEventType::COOKIE_STORE_COOKIE_DELETED,
  1525. [&](NetLogCaptureMode capture_mode) {
  1526. return NetLogCookieMonsterCookieDeleted(
  1527. cc, mapping.cause, sync_to_store, capture_mode);
  1528. });
  1529. }
  1530. if (ShouldUpdatePersistentStore(cc) && sync_to_store)
  1531. store_->DeleteCookie(*cc);
  1532. change_dispatcher_.DispatchChange(
  1533. CookieChangeInfo(
  1534. *cc,
  1535. CookieAccessResult(CookieEffectiveSameSite::UNDEFINED,
  1536. CookieInclusionStatus(),
  1537. GetAccessSemanticsForCookie(*cc),
  1538. true /* is_allowed_to_access_secure_cookies */),
  1539. mapping.cause),
  1540. mapping.notify);
  1541. partition_it->second->erase(cookie_it);
  1542. --num_partitioned_cookies_;
  1543. if (partition_it->second->empty())
  1544. partitioned_cookies_.erase(partition_it);
  1545. }
  1546. // Domain expiry behavior is unchanged by key/expiry scheme (the
  1547. // meaning of the key is different, but that's not visible to this routine).
  1548. size_t CookieMonster::GarbageCollect(const Time& current,
  1549. const std::string& key) {
  1550. DCHECK(thread_checker_.CalledOnValidThread());
  1551. size_t num_deleted = 0;
  1552. Time safe_date(Time::Now() - base::Days(kSafeFromGlobalPurgeDays));
  1553. // Collect garbage for this key, minding cookie priorities.
  1554. if (cookies_.count(key) > kDomainMaxCookies) {
  1555. DVLOG(net::cookie_util::kVlogGarbageCollection)
  1556. << "GarbageCollect() key: " << key;
  1557. CookieItVector* cookie_its;
  1558. CookieItVector non_expired_cookie_its;
  1559. cookie_its = &non_expired_cookie_its;
  1560. num_deleted +=
  1561. GarbageCollectExpired(current, cookies_.equal_range(key), cookie_its);
  1562. if (cookie_its->size() > kDomainMaxCookies) {
  1563. DVLOG(net::cookie_util::kVlogGarbageCollection)
  1564. << "Deep Garbage Collect domain.";
  1565. if (domain_purged_keys_.size() < kMaxDomainPurgedKeys)
  1566. domain_purged_keys_.insert(key);
  1567. size_t purge_goal =
  1568. cookie_its->size() - (kDomainMaxCookies - kDomainPurgeCookies);
  1569. DCHECK(purge_goal > kDomainPurgeCookies);
  1570. // Sort the cookies by access date, from least-recent to most-recent.
  1571. std::sort(cookie_its->begin(), cookie_its->end(), LRACookieSorter);
  1572. // Remove all but the kDomainCookiesQuotaLow most-recently accessed
  1573. // cookies with low-priority. Then, if cookies still need to be removed,
  1574. // bump the quota and remove low- and medium-priority. Then, if cookies
  1575. // _still_ need to be removed, bump the quota and remove cookies with
  1576. // any priority.
  1577. //
  1578. // 1. Low-priority non-secure cookies.
  1579. // 2. Low-priority secure cookies.
  1580. // 3. Medium-priority non-secure cookies.
  1581. // 4. High-priority non-secure cookies.
  1582. // 5. Medium-priority secure cookies.
  1583. // 6. High-priority secure cookies.
  1584. constexpr struct {
  1585. CookiePriority priority;
  1586. bool protect_secure_cookies;
  1587. } kPurgeRounds[] = {
  1588. // 1. Low-priority non-secure cookies.
  1589. {COOKIE_PRIORITY_LOW, true},
  1590. // 2. Low-priority secure cookies.
  1591. {COOKIE_PRIORITY_LOW, false},
  1592. // 3. Medium-priority non-secure cookies.
  1593. {COOKIE_PRIORITY_MEDIUM, true},
  1594. // 4. High-priority non-secure cookies.
  1595. {COOKIE_PRIORITY_HIGH, true},
  1596. // 5. Medium-priority secure cookies.
  1597. {COOKIE_PRIORITY_MEDIUM, false},
  1598. // 6. High-priority secure cookies.
  1599. {COOKIE_PRIORITY_HIGH, false},
  1600. };
  1601. size_t quota = 0;
  1602. for (const auto& purge_round : kPurgeRounds) {
  1603. // Adjust quota according to the priority of cookies. Each round should
  1604. // protect certain number of cookies in order to avoid starvation.
  1605. // For example, when each round starts to remove cookies, the number of
  1606. // cookies of that priority are counted and a decision whether they
  1607. // should be deleted or not is made. If yes, some number of cookies of
  1608. // that priority are deleted considering the quota.
  1609. switch (purge_round.priority) {
  1610. case COOKIE_PRIORITY_LOW:
  1611. quota = kDomainCookiesQuotaLow;
  1612. break;
  1613. case COOKIE_PRIORITY_MEDIUM:
  1614. quota = kDomainCookiesQuotaMedium;
  1615. break;
  1616. case COOKIE_PRIORITY_HIGH:
  1617. quota = kDomainCookiesQuotaHigh;
  1618. break;
  1619. }
  1620. size_t just_deleted = 0u;
  1621. // Purge up to |purge_goal| for all cookies at the given priority. This
  1622. // path will be taken only if the initial non-secure purge did not evict
  1623. // enough cookies.
  1624. if (purge_goal > 0) {
  1625. just_deleted = PurgeLeastRecentMatches(
  1626. cookie_its, purge_round.priority, quota, purge_goal,
  1627. purge_round.protect_secure_cookies);
  1628. DCHECK_LE(just_deleted, purge_goal);
  1629. purge_goal -= just_deleted;
  1630. num_deleted += just_deleted;
  1631. }
  1632. }
  1633. DCHECK_EQ(0u, purge_goal);
  1634. }
  1635. }
  1636. // Collect garbage for everything. With firefox style we want to preserve
  1637. // cookies accessed in kSafeFromGlobalPurgeDays, otherwise evict.
  1638. if (cookies_.size() > kMaxCookies && earliest_access_time_ < safe_date) {
  1639. DVLOG(net::cookie_util::kVlogGarbageCollection)
  1640. << "GarbageCollect() everything";
  1641. CookieItVector cookie_its;
  1642. num_deleted += GarbageCollectExpired(
  1643. current, CookieMapItPair(cookies_.begin(), cookies_.end()),
  1644. &cookie_its);
  1645. if (cookie_its.size() > kMaxCookies) {
  1646. DVLOG(net::cookie_util::kVlogGarbageCollection)
  1647. << "Deep Garbage Collect everything.";
  1648. size_t purge_goal = cookie_its.size() - (kMaxCookies - kPurgeCookies);
  1649. DCHECK(purge_goal > kPurgeCookies);
  1650. CookieItVector secure_cookie_its;
  1651. CookieItVector non_secure_cookie_its;
  1652. SplitCookieVectorIntoSecureAndNonSecure(cookie_its, &secure_cookie_its,
  1653. &non_secure_cookie_its);
  1654. size_t non_secure_purge_goal =
  1655. std::min<size_t>(purge_goal, non_secure_cookie_its.size());
  1656. base::Time earliest_non_secure_access_time;
  1657. size_t just_deleted = GarbageCollectLeastRecentlyAccessed(
  1658. current, safe_date, non_secure_purge_goal, non_secure_cookie_its,
  1659. &earliest_non_secure_access_time);
  1660. num_deleted += just_deleted;
  1661. if (secure_cookie_its.size() == 0) {
  1662. // This case is unlikely, but should still update
  1663. // |earliest_access_time_| if only have non-secure cookies.
  1664. earliest_access_time_ = earliest_non_secure_access_time;
  1665. // Garbage collection can't delete all cookies.
  1666. DCHECK(!earliest_access_time_.is_null());
  1667. } else if (just_deleted < purge_goal) {
  1668. size_t secure_purge_goal = std::min<size_t>(purge_goal - just_deleted,
  1669. secure_cookie_its.size());
  1670. base::Time earliest_secure_access_time;
  1671. num_deleted += GarbageCollectLeastRecentlyAccessed(
  1672. current, safe_date, secure_purge_goal, secure_cookie_its,
  1673. &earliest_secure_access_time);
  1674. if (!earliest_non_secure_access_time.is_null() &&
  1675. earliest_non_secure_access_time < earliest_secure_access_time) {
  1676. earliest_access_time_ = earliest_non_secure_access_time;
  1677. } else {
  1678. earliest_access_time_ = earliest_secure_access_time;
  1679. }
  1680. // Garbage collection can't delete all cookies.
  1681. DCHECK(!earliest_access_time_.is_null());
  1682. }
  1683. // If there are secure cookies, but deleting non-secure cookies was enough
  1684. // to meet the purge goal, secure cookies are never examined, so
  1685. // |earliest_access_time_| can't be determined. Leaving it alone will mean
  1686. // it's no later than the real earliest last access time, so this won't
  1687. // lead to any problems.
  1688. }
  1689. }
  1690. return num_deleted;
  1691. }
  1692. size_t CookieMonster::GarbageCollectPartitionedCookies(
  1693. const base::Time& current,
  1694. const CookiePartitionKey& cookie_partition_key,
  1695. const std::string& key) {
  1696. DCHECK(thread_checker_.CalledOnValidThread());
  1697. size_t num_deleted = 0;
  1698. PartitionedCookieMap::iterator cookie_partition_it =
  1699. partitioned_cookies_.find(cookie_partition_key);
  1700. if (cookie_partition_it == partitioned_cookies_.end())
  1701. return num_deleted;
  1702. if (cookie_partition_it->second->count(key) > kPerPartitionDomainMaxCookies) {
  1703. // TODO(crbug.com/1225444): Log garbage collection for partitioned cookies.
  1704. CookieItVector non_expired_cookie_its;
  1705. num_deleted += GarbageCollectExpiredPartitionedCookies(
  1706. current, cookie_partition_it,
  1707. cookie_partition_it->second->equal_range(key), &non_expired_cookie_its);
  1708. if (non_expired_cookie_its.size() > kPerPartitionDomainMaxCookies) {
  1709. // TODO(crbug.com/1225444): Log deep garbage collection for partitioned
  1710. // cookies.
  1711. // For now, just delete the least recently accessed partition cookies
  1712. // until we are under the per-partition domain limit. All partitioned
  1713. // cookies are Secure since they require the __Host- prefix.
  1714. std::sort(non_expired_cookie_its.begin(), non_expired_cookie_its.end(),
  1715. LRACookieSorter);
  1716. for (size_t i = 0;
  1717. i < (non_expired_cookie_its.size() - kPerPartitionDomainMaxCookies);
  1718. ++i) {
  1719. InternalDeletePartitionedCookie(
  1720. cookie_partition_it, non_expired_cookie_its[i], true,
  1721. DELETE_COOKIE_EVICTED_PER_PARTITION_DOMAIN);
  1722. ++num_deleted;
  1723. }
  1724. }
  1725. }
  1726. // TODO(crbug.com/1225444): Enforce global limit on partitioned cookies.
  1727. return num_deleted;
  1728. }
  1729. size_t CookieMonster::PurgeLeastRecentMatches(CookieItVector* cookies,
  1730. CookiePriority priority,
  1731. size_t to_protect,
  1732. size_t purge_goal,
  1733. bool protect_secure_cookies) {
  1734. DCHECK(thread_checker_.CalledOnValidThread());
  1735. // 1. Count number of the cookies at |priority|
  1736. size_t cookies_count_possibly_to_be_deleted = CountCookiesForPossibleDeletion(
  1737. priority, cookies, false /* count all cookies */);
  1738. // 2. If |cookies_count_possibly_to_be_deleted| at |priority| is less than or
  1739. // equal |to_protect|, skip round in order to preserve the quota. This
  1740. // involves secure and non-secure cookies at |priority|.
  1741. if (cookies_count_possibly_to_be_deleted <= to_protect)
  1742. return 0u;
  1743. // 3. Calculate number of secure cookies at |priority|
  1744. // and number of cookies at |priority| that can possibly be deleted.
  1745. // It is guaranteed we do not delete more than |purge_goal| even if
  1746. // |cookies_count_possibly_to_be_deleted| is higher.
  1747. size_t secure_cookies = 0u;
  1748. if (protect_secure_cookies) {
  1749. secure_cookies = CountCookiesForPossibleDeletion(
  1750. priority, cookies, protect_secure_cookies /* count secure cookies */);
  1751. cookies_count_possibly_to_be_deleted -=
  1752. std::max(secure_cookies, to_protect);
  1753. } else {
  1754. cookies_count_possibly_to_be_deleted -= to_protect;
  1755. }
  1756. size_t removed = 0u;
  1757. size_t current = 0u;
  1758. while ((removed < purge_goal && current < cookies->size()) &&
  1759. cookies_count_possibly_to_be_deleted > 0) {
  1760. const CanonicalCookie* current_cookie = cookies->at(current)->second.get();
  1761. // Only delete the current cookie if the priority is equal to
  1762. // the current level.
  1763. if (IsCookieEligibleForEviction(priority, protect_secure_cookies,
  1764. current_cookie)) {
  1765. InternalDeleteCookie(cookies->at(current), true,
  1766. DELETE_COOKIE_EVICTED_DOMAIN);
  1767. cookies->erase(cookies->begin() + current);
  1768. removed++;
  1769. cookies_count_possibly_to_be_deleted--;
  1770. } else {
  1771. current++;
  1772. }
  1773. }
  1774. return removed;
  1775. }
  1776. size_t CookieMonster::GarbageCollectExpired(const Time& current,
  1777. const CookieMapItPair& itpair,
  1778. CookieItVector* cookie_its) {
  1779. DCHECK(thread_checker_.CalledOnValidThread());
  1780. int num_deleted = 0;
  1781. for (CookieMap::iterator it = itpair.first, end = itpair.second; it != end;) {
  1782. auto curit = it;
  1783. ++it;
  1784. if (curit->second->IsExpired(current)) {
  1785. InternalDeleteCookie(curit, true, DELETE_COOKIE_EXPIRED);
  1786. ++num_deleted;
  1787. } else if (cookie_its) {
  1788. cookie_its->push_back(curit);
  1789. }
  1790. }
  1791. return num_deleted;
  1792. }
  1793. size_t CookieMonster::GarbageCollectExpiredPartitionedCookies(
  1794. const Time& current,
  1795. const PartitionedCookieMap::iterator& cookie_partition_it,
  1796. const CookieMapItPair& itpair,
  1797. CookieItVector* cookie_its) {
  1798. DCHECK(thread_checker_.CalledOnValidThread());
  1799. int num_deleted = 0;
  1800. for (CookieMap::iterator it = itpair.first, end = itpair.second; it != end;) {
  1801. auto curit = it;
  1802. ++it;
  1803. if (curit->second->IsExpired(current)) {
  1804. InternalDeletePartitionedCookie(cookie_partition_it, curit, true,
  1805. DELETE_COOKIE_EXPIRED);
  1806. ++num_deleted;
  1807. } else if (cookie_its) {
  1808. cookie_its->push_back(curit);
  1809. }
  1810. }
  1811. return num_deleted;
  1812. }
  1813. void CookieMonster::GarbageCollectAllExpiredPartitionedCookies(
  1814. const Time& current) {
  1815. for (auto it = partitioned_cookies_.begin();
  1816. it != partitioned_cookies_.end();) {
  1817. // GarbageCollectExpiredPartitionedCookies calls
  1818. // InternalDeletePartitionedCookie which may invalidate
  1819. // |cur_cookie_partition_it|.
  1820. auto cur_cookie_partition_it = it;
  1821. ++it;
  1822. GarbageCollectExpiredPartitionedCookies(
  1823. current, cur_cookie_partition_it,
  1824. CookieMapItPair(cur_cookie_partition_it->second->begin(),
  1825. cur_cookie_partition_it->second->end()),
  1826. nullptr /*cookie_its*/);
  1827. }
  1828. }
  1829. size_t CookieMonster::GarbageCollectDeleteRange(
  1830. const Time& current,
  1831. DeletionCause cause,
  1832. CookieItVector::iterator it_begin,
  1833. CookieItVector::iterator it_end) {
  1834. DCHECK(thread_checker_.CalledOnValidThread());
  1835. for (auto it = it_begin; it != it_end; it++) {
  1836. InternalDeleteCookie((*it), true, cause);
  1837. }
  1838. return it_end - it_begin;
  1839. }
  1840. size_t CookieMonster::GarbageCollectLeastRecentlyAccessed(
  1841. const base::Time& current,
  1842. const base::Time& safe_date,
  1843. size_t purge_goal,
  1844. CookieItVector cookie_its,
  1845. base::Time* earliest_time) {
  1846. DCHECK_LE(purge_goal, cookie_its.size());
  1847. DCHECK(thread_checker_.CalledOnValidThread());
  1848. // Sorts up to *and including* |cookie_its[purge_goal]| (if it exists), so
  1849. // |earliest_time| will be properly assigned even if
  1850. // |global_purge_it| == |cookie_its.begin() + purge_goal|.
  1851. SortLeastRecentlyAccessed(
  1852. cookie_its.begin(), cookie_its.end(),
  1853. cookie_its.size() < purge_goal ? purge_goal + 1 : purge_goal);
  1854. // Find boundary to cookies older than safe_date.
  1855. auto global_purge_it = LowerBoundAccessDate(
  1856. cookie_its.begin(), cookie_its.begin() + purge_goal, safe_date);
  1857. // Only delete the old cookies and delete non-secure ones first.
  1858. size_t num_deleted =
  1859. GarbageCollectDeleteRange(current, DELETE_COOKIE_EVICTED_GLOBAL,
  1860. cookie_its.begin(), global_purge_it);
  1861. if (global_purge_it != cookie_its.end())
  1862. *earliest_time = (*global_purge_it)->second->LastAccessDate();
  1863. return num_deleted;
  1864. }
  1865. // A wrapper around registry_controlled_domains::GetDomainAndRegistry
  1866. // to make clear we're creating a key for our local map or for the persistent
  1867. // store's use. Here and in FindCookiesForRegistryControlledHost() are the only
  1868. // two places where we need to conditionalize based on key type.
  1869. //
  1870. // Note that this key algorithm explicitly ignores the scheme. This is
  1871. // because when we're entering cookies into the map from the backing store,
  1872. // we in general won't have the scheme at that point.
  1873. // In practical terms, this means that file cookies will be stored
  1874. // in the map either by an empty string or by UNC name (and will be
  1875. // limited by kMaxCookiesPerHost), and extension cookies will be stored
  1876. // based on the single extension id, as the extension id won't have the
  1877. // form of a DNS host and hence GetKey() will return it unchanged.
  1878. //
  1879. // Arguably the right thing to do here is to make the key
  1880. // algorithm dependent on the scheme, and make sure that the scheme is
  1881. // available everywhere the key must be obtained (specfically at backing
  1882. // store load time). This would require either changing the backing store
  1883. // database schema to include the scheme (far more trouble than it's worth), or
  1884. // separating out file cookies into their own CookieMonster instance and
  1885. // thus restricting each scheme to a single cookie monster (which might
  1886. // be worth it, but is still too much trouble to solve what is currently a
  1887. // non-problem).
  1888. //
  1889. // static
  1890. std::string CookieMonster::GetKey(base::StringPiece domain) {
  1891. std::string effective_domain(
  1892. registry_controlled_domains::GetDomainAndRegistry(
  1893. domain, registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES));
  1894. if (effective_domain.empty())
  1895. effective_domain = std::string(domain);
  1896. return cookie_util::CookieDomainAsHost(effective_domain);
  1897. }
  1898. bool CookieMonster::HasCookieableScheme(const GURL& url) {
  1899. DCHECK(thread_checker_.CalledOnValidThread());
  1900. // Make sure the request is on a cookie-able url scheme.
  1901. bool is_cookieable = base::ranges::any_of(
  1902. cookieable_schemes_, [&url](const std::string& cookieable_scheme) {
  1903. return url.SchemeIs(cookieable_scheme.c_str());
  1904. });
  1905. if (!is_cookieable) {
  1906. // The scheme didn't match any in our allowed list.
  1907. DVLOG(net::cookie_util::kVlogPerCookieMonster)
  1908. << "WARNING: Unsupported cookie scheme: " << url.scheme();
  1909. }
  1910. return is_cookieable;
  1911. }
  1912. CookieAccessSemantics CookieMonster::GetAccessSemanticsForCookie(
  1913. const CanonicalCookie& cookie) const {
  1914. if (cookie_access_delegate())
  1915. return cookie_access_delegate()->GetAccessSemantics(cookie);
  1916. return CookieAccessSemantics::UNKNOWN;
  1917. }
  1918. // Test to see if stats should be recorded, and record them if so.
  1919. // The goal here is to get sampling for the average browser-hour of
  1920. // activity. We won't take samples when the web isn't being surfed,
  1921. // and when the web is being surfed, we'll take samples about every
  1922. // kRecordStatisticsIntervalSeconds.
  1923. // last_statistic_record_time_ is initialized to Now() rather than null
  1924. // in the constructor so that we won't take statistics right after
  1925. // startup, to avoid bias from browsers that are started but not used.
  1926. void CookieMonster::RecordPeriodicStats(const base::Time& current_time) {
  1927. DCHECK(thread_checker_.CalledOnValidThread());
  1928. const base::TimeDelta kRecordStatisticsIntervalTime(
  1929. base::Seconds(kRecordStatisticsIntervalSeconds));
  1930. // If we've taken statistics recently, return.
  1931. if (current_time - last_statistic_record_time_ <=
  1932. kRecordStatisticsIntervalTime) {
  1933. return;
  1934. }
  1935. if (DoRecordPeriodicStats())
  1936. last_statistic_record_time_ = current_time;
  1937. }
  1938. bool CookieMonster::DoRecordPeriodicStats() {
  1939. // These values are all bogus if we have only partially loaded the cookies.
  1940. if (started_fetching_all_cookies_ && !finished_fetching_all_cookies_)
  1941. return false;
  1942. base::UmaHistogramCounts100000("Cookie.Count2", cookies_.size());
  1943. if (cookie_access_delegate()) {
  1944. std::vector<SchemefulSite> sites;
  1945. for (const auto& entry : cookies_) {
  1946. sites.emplace_back(
  1947. GURL(base::StrCat({url::kHttpsScheme, "://", entry.first})));
  1948. }
  1949. for (const auto& [partition_key, cookie_map] : partitioned_cookies_) {
  1950. for (const auto& [domain, unused_cookie] : *cookie_map) {
  1951. sites.emplace_back(
  1952. GURL(base::StrCat({url::kHttpsScheme, "://", domain})));
  1953. }
  1954. }
  1955. absl::optional<base::flat_map<SchemefulSite, FirstPartySetEntry>>
  1956. maybe_sets = cookie_access_delegate()->FindFirstPartySetOwners(
  1957. sites,
  1958. base::BindOnce(&CookieMonster::RecordPeriodicFirstPartySetsStats,
  1959. weak_ptr_factory_.GetWeakPtr()));
  1960. if (maybe_sets.has_value())
  1961. RecordPeriodicFirstPartySetsStats(maybe_sets.value());
  1962. }
  1963. // Can be up to kMaxDomainPurgedKeys.
  1964. UMA_HISTOGRAM_COUNTS_100("Cookie.NumDomainPurgedKeys",
  1965. domain_purged_keys_.size());
  1966. // Can be up to kMaxCookies.
  1967. UMA_HISTOGRAM_COUNTS_10000("Cookie.NumKeys", num_keys_);
  1968. std::map<std::string, size_t> n_same_site_none_cookies;
  1969. for (const auto& [host_key, host_cookie] : cookies_) {
  1970. if (!host_cookie || !host_cookie->IsEffectivelySameSiteNone())
  1971. continue;
  1972. n_same_site_none_cookies[host_key]++;
  1973. }
  1974. size_t max_n_cookies = 0;
  1975. for (const auto& entry : n_same_site_none_cookies) {
  1976. max_n_cookies = std::max(max_n_cookies, entry.second);
  1977. }
  1978. // Can be up to 180 cookies, the max per-domain.
  1979. base::UmaHistogramCounts1000("Cookie.MaxSameSiteNoneCookiesPerKey",
  1980. max_n_cookies);
  1981. // Collect stats for partitioned cookies if they are enabled.
  1982. if (base::FeatureList::IsEnabled(features::kPartitionedCookies)) {
  1983. base::UmaHistogramCounts1000("Cookie.PartitionCount",
  1984. partitioned_cookies_.size());
  1985. base::UmaHistogramCounts100000("Cookie.PartitionedCookieCount",
  1986. num_partitioned_cookies_);
  1987. }
  1988. return true;
  1989. }
  1990. void CookieMonster::RecordPeriodicFirstPartySetsStats(
  1991. base::flat_map<SchemefulSite, FirstPartySetEntry> sets) const {
  1992. base::flat_map<SchemefulSite, std::set<SchemefulSite>> grouped_by_owner;
  1993. for (const auto& [site, entry] : sets) {
  1994. grouped_by_owner[entry.primary()].insert(site);
  1995. }
  1996. for (const auto& set : grouped_by_owner) {
  1997. int sample = std::accumulate(
  1998. set.second.begin(), set.second.end(), 0,
  1999. [this](int acc, const net::SchemefulSite& site) -> int {
  2000. if (!site.has_registrable_domain_or_host())
  2001. return acc;
  2002. return acc + cookies_.count(site.registrable_domain_or_host());
  2003. });
  2004. base::UmaHistogramCustomCounts("Cookie.PerFirstPartySetCount", sample, 0,
  2005. 4000, 50);
  2006. }
  2007. }
  2008. void CookieMonster::DoCookieCallback(base::OnceClosure callback) {
  2009. DCHECK(thread_checker_.CalledOnValidThread());
  2010. MarkCookieStoreAsInitialized();
  2011. FetchAllCookiesIfNecessary();
  2012. seen_global_task_ = true;
  2013. if (!finished_fetching_all_cookies_ && store_.get()) {
  2014. tasks_pending_.push_back(std::move(callback));
  2015. return;
  2016. }
  2017. std::move(callback).Run();
  2018. }
  2019. void CookieMonster::DoCookieCallbackForURL(base::OnceClosure callback,
  2020. const GURL& url) {
  2021. DoCookieCallbackForHostOrDomain(std::move(callback), url.host_piece());
  2022. }
  2023. void CookieMonster::DoCookieCallbackForHostOrDomain(
  2024. base::OnceClosure callback,
  2025. base::StringPiece host_or_domain) {
  2026. MarkCookieStoreAsInitialized();
  2027. FetchAllCookiesIfNecessary();
  2028. // If cookies for the requested domain key (eTLD+1) have been loaded from DB
  2029. // then run the task, otherwise load from DB.
  2030. if (!finished_fetching_all_cookies_ && store_.get()) {
  2031. // If a global task has been previously seen, queue the task as a global
  2032. // task. Note that the CookieMonster may be in the middle of executing
  2033. // the global queue, |tasks_pending_| may be empty, which is why another
  2034. // bool is needed.
  2035. if (seen_global_task_) {
  2036. tasks_pending_.push_back(std::move(callback));
  2037. return;
  2038. }
  2039. // Checks if the domain key has been loaded.
  2040. std::string key = GetKey(host_or_domain);
  2041. if (keys_loaded_.find(key) == keys_loaded_.end()) {
  2042. auto it = tasks_pending_for_key_.find(key);
  2043. if (it == tasks_pending_for_key_.end()) {
  2044. store_->LoadCookiesForKey(
  2045. key, base::BindOnce(&CookieMonster::OnKeyLoaded,
  2046. weak_ptr_factory_.GetWeakPtr(), key));
  2047. it = tasks_pending_for_key_
  2048. .insert(std::make_pair(
  2049. key, base::circular_deque<base::OnceClosure>()))
  2050. .first;
  2051. }
  2052. it->second.push_back(std::move(callback));
  2053. return;
  2054. }
  2055. }
  2056. std::move(callback).Run();
  2057. }
  2058. CookieMonster::CookieSentToSamePort
  2059. CookieMonster::IsCookieSentToSamePortThatSetIt(
  2060. const GURL& destination,
  2061. int source_port,
  2062. CookieSourceScheme source_scheme) {
  2063. if (source_port == url::PORT_UNSPECIFIED)
  2064. return CookieSentToSamePort::kSourcePortUnspecified;
  2065. if (source_port == url::PORT_INVALID)
  2066. return CookieSentToSamePort::kInvalid;
  2067. int destination_port = destination.EffectiveIntPort();
  2068. if (source_port == destination_port)
  2069. return CookieSentToSamePort::kYes;
  2070. const std::string& destination_scheme = destination.scheme();
  2071. bool destination_port_is_default =
  2072. url::DefaultPortForScheme(destination_scheme.c_str(),
  2073. destination_scheme.length()) ==
  2074. destination_port;
  2075. // Since the source port has to be specified if we got to this point, that
  2076. // means this is a newer cookie that therefore has its scheme set as well.
  2077. DCHECK(source_scheme != CookieSourceScheme::kUnset);
  2078. std::string source_scheme_string =
  2079. source_scheme == CookieSourceScheme::kSecure
  2080. ? url::kHttpsScheme
  2081. : url::kHttpScheme; // wss/ws have the same default port values as
  2082. // https/http, so it's ok that we use these.
  2083. bool source_port_is_default =
  2084. url::DefaultPortForScheme(source_scheme_string.c_str(),
  2085. source_scheme_string.length()) == source_port;
  2086. if (destination_port_is_default && source_port_is_default)
  2087. return CookieSentToSamePort::kNoButDefault;
  2088. return CookieSentToSamePort::kNo;
  2089. }
  2090. void CookieMonster::ConvertPartitionedCookiesToUnpartitioned(const GURL& url) {
  2091. DoCookieCallbackForHostOrDomain(
  2092. base::BindOnce(
  2093. // base::Unretained is safe as DoCookieCallbackForHostOrDomain stores
  2094. // the callback on |*this|, so the callback will not outlive
  2095. // the object.
  2096. &CookieMonster::OnConvertPartitionedCookiesToUnpartitioned,
  2097. base::Unretained(this), url),
  2098. url.host());
  2099. }
  2100. void CookieMonster::OnConvertPartitionedCookiesToUnpartitioned(
  2101. const GURL& url) {
  2102. DCHECK(thread_checker_.CalledOnValidThread());
  2103. std::vector<CanonicalCookie*> cookie_ptrs_for_site =
  2104. FindCookiesForRegistryControlledHost(url);
  2105. for (const auto& it : partitioned_cookies_) {
  2106. std::vector<CanonicalCookie*> partitioned_cookie_ptrs =
  2107. FindPartitionedCookiesForRegistryControlledHost(it.first, url);
  2108. cookie_ptrs_for_site.insert(cookie_ptrs_for_site.end(),
  2109. partitioned_cookie_ptrs.begin(),
  2110. partitioned_cookie_ptrs.end());
  2111. }
  2112. // We only want cookies whose domain is a match for the entire URL host.
  2113. // This should exclude cookies set on subdomains.
  2114. std::vector<CanonicalCookie*> cookie_ptrs;
  2115. CookieOptions options = CookieOptions::MakeAllInclusive();
  2116. bool delegate_treats_url_as_trustworthy =
  2117. cookie_access_delegate() &&
  2118. cookie_access_delegate()->ShouldTreatUrlAsTrustworthy(url);
  2119. CookieAccessParams accesss_params{
  2120. net::CookieAccessSemantics::UNKNOWN, delegate_treats_url_as_trustworthy,
  2121. CookieSamePartyStatus::kNoSamePartyEnforcement};
  2122. for (auto* cookie : cookie_ptrs_for_site) {
  2123. if (cookie->IncludeForRequestURL(url, options, accesss_params)
  2124. .status.IsInclude()) {
  2125. cookie_ptrs.push_back(cookie);
  2126. }
  2127. }
  2128. std::map<std::tuple<std::string, std::string, std::string>,
  2129. std::vector<const net::CanonicalCookie*>>
  2130. cookies;
  2131. for (const auto* cookie : cookie_ptrs) {
  2132. auto key =
  2133. std::make_tuple(cookie->Name(), cookie->Domain(), cookie->Path());
  2134. auto found_it = cookies.find(key);
  2135. if (found_it == cookies.end()) {
  2136. cookies.insert(decltype(cookies)::value_type(key, {}));
  2137. cookies.find(key)->second.push_back(cookie);
  2138. } else {
  2139. found_it->second.push_back(cookie);
  2140. }
  2141. }
  2142. for (const auto& kv_pair : cookies) {
  2143. bool should_convert_cookie = false;
  2144. net::CanonicalCookie cookie_to_convert;
  2145. if (kv_pair.second.size() == 1u) {
  2146. // If there is only a single partitioned cookie, we just need to convert
  2147. // it to unpartitioned.
  2148. if (kv_pair.second[0]->IsPartitioned() &&
  2149. !kv_pair.second[0]->PartitionKey()->nonce())
  2150. should_convert_cookie = true;
  2151. cookie_to_convert = *kv_pair.second[0];
  2152. } else {
  2153. for (const auto* cookie : kv_pair.second) {
  2154. // If the site only has partitioned cookies, we first check if there is
  2155. // a cookie whose partition key is same-site with the cookie's domain.
  2156. //
  2157. // If there are no partitioned cookies whose partition key is same-site
  2158. // with the cookie's domain, we convert the most recently accessed
  2159. // cookie to unpartitioned and delete the rest.
  2160. if (cookie->IsPartitioned() && !cookie->PartitionKey()->nonce()) {
  2161. if (cookie->PartitionKey()->site() ==
  2162. SchemefulSite(GURL("https://" + cookie->DomainWithoutDot()))) {
  2163. should_convert_cookie = true;
  2164. cookie_to_convert = *cookie;
  2165. break;
  2166. }
  2167. if (!should_convert_cookie ||
  2168. cookie->LastAccessDate() > cookie_to_convert.LastAccessDate()) {
  2169. should_convert_cookie = true;
  2170. cookie_to_convert = *cookie;
  2171. }
  2172. } else if (!cookie->IsPartitioned()) {
  2173. // If there is an unpartitioned cookie, we leave that cookie alone and
  2174. // only delete the partitioned cookies.
  2175. should_convert_cookie = false;
  2176. break;
  2177. }
  2178. }
  2179. }
  2180. if (should_convert_cookie)
  2181. ConvertPartitionedCookie(cookie_to_convert, url);
  2182. }
  2183. for (auto partition_it = partitioned_cookies_.begin();
  2184. partition_it != partitioned_cookies_.end();) {
  2185. // InternalDeletePartitionedCookie may invalidate |partition_it| if that
  2186. // cookie partition only has one cookie.
  2187. auto cur_partition_it = partition_it;
  2188. CookieMap::iterator cookie_it = cur_partition_it->second->begin();
  2189. CookieMap::iterator cookie_end = cur_partition_it->second->end();
  2190. ++partition_it;
  2191. while (cookie_it != cookie_end) {
  2192. auto cur_cookie_it = cookie_it;
  2193. CanonicalCookie* cc = cur_cookie_it->second.get();
  2194. ++cookie_it;
  2195. if (!cc->IncludeForRequestURL(url, options, accesss_params)
  2196. .status.IsInclude() ||
  2197. cc->PartitionKey()->nonce()) {
  2198. continue;
  2199. }
  2200. InternalDeletePartitionedCookie(cur_partition_it, cur_cookie_it, true,
  2201. DELETE_COOKIE_EXPLICIT);
  2202. }
  2203. }
  2204. }
  2205. void CookieMonster::ConvertPartitionedCookie(const net::CanonicalCookie& cookie,
  2206. const GURL& url) {
  2207. DCHECK(cookie.IsPartitioned());
  2208. auto new_cookie = net::CanonicalCookie::FromStorage(
  2209. cookie.Name(), cookie.Value(), cookie.Domain(), cookie.Path(),
  2210. cookie.CreationDate(), cookie.ExpiryDate(), base::Time::Now(),
  2211. cookie.LastUpdateDate(), cookie.IsSecure(), cookie.IsHttpOnly(),
  2212. cookie.SameSite(), cookie.Priority(), cookie.IsSameParty(), absl::nullopt,
  2213. cookie.SourceScheme(), cookie.SourcePort());
  2214. DCHECK(new_cookie);
  2215. bool delegate_treats_url_as_trustworthy =
  2216. cookie_access_delegate() &&
  2217. cookie_access_delegate()->ShouldTreatUrlAsTrustworthy(url);
  2218. CookieOptions options = CookieOptions::MakeAllInclusive();
  2219. CookieAccessResult access_result = new_cookie->IsSetPermittedInContext(
  2220. url, options,
  2221. CookieAccessParams(GetAccessSemanticsForCookie(*new_cookie),
  2222. delegate_treats_url_as_trustworthy,
  2223. cookie_util::GetSamePartyStatus(
  2224. *new_cookie, options, first_party_sets_enabled_)),
  2225. cookieable_schemes_);
  2226. auto key = GetKey(new_cookie->Domain());
  2227. InternalInsertCookie(key, std::move(new_cookie), /*sync_to_store=*/true,
  2228. access_result);
  2229. }
  2230. } // namespace net