xref: /aosp_15_r20/external/cronet/net/extras/sqlite/sqlite_persistent_cookie_store.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright 2012 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "net/extras/sqlite/sqlite_persistent_cookie_store.h"
6 
7 #include <iterator>
8 #include <map>
9 #include <memory>
10 #include <optional>
11 #include <set>
12 #include <tuple>
13 #include <unordered_set>
14 
15 #include "base/feature_list.h"
16 #include "base/files/file_path.h"
17 #include "base/files/file_util.h"
18 #include "base/functional/bind.h"
19 #include "base/functional/callback.h"
20 #include "base/location.h"
21 #include "base/logging.h"
22 #include "base/memory/raw_ptr.h"
23 #include "base/memory/ref_counted.h"
24 #include "base/metrics/histogram_functions.h"
25 #include "base/metrics/histogram_macros.h"
26 #include "base/strings/string_util.h"
27 #include "base/strings/stringprintf.h"
28 #include "base/synchronization/lock.h"
29 #include "base/task/sequenced_task_runner.h"
30 #include "base/thread_annotations.h"
31 #include "base/time/time.h"
32 #include "base/types/optional_ref.h"
33 #include "base/values.h"
34 #include "build/build_config.h"
35 #include "net/cookies/canonical_cookie.h"
36 #include "net/cookies/cookie_constants.h"
37 #include "net/cookies/cookie_util.h"
38 #include "net/extras/sqlite/cookie_crypto_delegate.h"
39 #include "net/extras/sqlite/sqlite_persistent_store_backend_base.h"
40 #include "net/log/net_log.h"
41 #include "net/log/net_log_values.h"
42 #include "sql/error_delegate_util.h"
43 #include "sql/meta_table.h"
44 #include "sql/statement.h"
45 #include "sql/transaction.h"
46 #include "url/gurl.h"
47 #include "url/third_party/mozilla/url_parse.h"
48 
49 using base::Time;
50 
51 namespace {
52 
53 static constexpr int kHoursInOneWeek = 24 * 7;
54 static constexpr int kHoursInOneYear = 24 * 365;
55 
CookieKeyedLoadNetLogParams(const std::string & key,net::NetLogCaptureMode capture_mode)56 base::Value::Dict CookieKeyedLoadNetLogParams(
57     const std::string& key,
58     net::NetLogCaptureMode capture_mode) {
59   if (!net::NetLogCaptureIncludesSensitive(capture_mode))
60     return base::Value::Dict();
61   base::Value::Dict dict;
62   dict.Set("key", key);
63   return dict;
64 }
65 
66 // Used to populate a histogram for problems when loading cookies.
67 //
68 // Please do not reorder or remove entries. New entries must be added to the
69 // end of the list, just before COOKIE_LOAD_PROBLEM_LAST_ENTRY.
70 enum CookieLoadProblem {
71   COOKIE_LOAD_PROBLEM_DECRYPT_FAILED = 0,
72   // Deprecated 03/2021.
73   // COOKIE_LOAD_PROBLEM_DECRYPT_TIMEOUT = 1,
74   COOKIE_LOAD_PROBLEM_NON_CANONICAL = 2,
75   COOKIE_LOAD_PROBLEM_OPEN_DB = 3,
76   COOKIE_LOAD_PROBLEM_RECOVERY_FAILED = 4,
77   COOKIE_LOAD_DELETE_COOKIE_PARTITION_FAILED = 5,
78   COOKIE_LOAD_PROBLEM_LAST_ENTRY
79 };
80 
81 // Used to populate a histogram for problems when committing cookies.
82 //
83 // Please do not reorder or remove entries. New entries must be added to the
84 // end of the list, just before COOKIE_COMMIT_PROBLEM_LAST_ENTRY.
85 enum CookieCommitProblem {
86   COOKIE_COMMIT_PROBLEM_ENCRYPT_FAILED = 0,
87   COOKIE_COMMIT_PROBLEM_ADD = 1,
88   COOKIE_COMMIT_PROBLEM_UPDATE_ACCESS = 2,
89   COOKIE_COMMIT_PROBLEM_DELETE = 3,
90   COOKIE_COMMIT_PROBLEM_TRANSACTION_COMMIT = 4,
91   COOKIE_COMMIT_PROBLEM_LAST_ENTRY
92 };
93 
RecordCookieLoadProblem(CookieLoadProblem event)94 void RecordCookieLoadProblem(CookieLoadProblem event) {
95   UMA_HISTOGRAM_ENUMERATION("Cookie.LoadProblem", event,
96                             COOKIE_LOAD_PROBLEM_LAST_ENTRY);
97 }
98 
RecordCookieCommitProblem(CookieCommitProblem event)99 void RecordCookieCommitProblem(CookieCommitProblem event) {
100   UMA_HISTOGRAM_ENUMERATION("Cookie.CommitProblem", event,
101                             COOKIE_COMMIT_PROBLEM_LAST_ENTRY);
102 }
103 
104 // Records metrics around the age in hours of a cookie loaded from the store via
105 // MakeCookiesFromSQLStatement for use by some browser context.
HistogramCookieAge(const net::CanonicalCookie & cookie)106 void HistogramCookieAge(const net::CanonicalCookie& cookie) {
107   if (cookie.IsPersistent()) {
108     // We are studying the age of script cookies in active use. This record is
109     // split into two histograms to improve resolution.
110     if (!cookie.LastUpdateDate().is_null() &&
111         cookie.SourceType() == net::CookieSourceType::kScript) {
112       const int script_cookie_age_since_last_update_in_hours =
113           (Time::Now() - cookie.LastUpdateDate()).InHours();
114       if (script_cookie_age_since_last_update_in_hours > kHoursInOneWeek) {
115         UMA_HISTOGRAM_CUSTOM_COUNTS(
116             "Cookie.ScriptAgeSinceLastUpdateInHoursGTOneWeek",
117             script_cookie_age_since_last_update_in_hours, kHoursInOneWeek + 1,
118             kHoursInOneYear, 100);
119       } else {
120         UMA_HISTOGRAM_CUSTOM_COUNTS(
121             "Cookie.ScriptAgeSinceLastUpdateInHoursLTEOneWeek",
122             script_cookie_age_since_last_update_in_hours, 1,
123             kHoursInOneWeek + 1, 100);
124       }
125     }
126   } else {
127     // We are studying the age of session cookies in active use. The record is
128     // split into two histograms to improve resolution.
129     if (!cookie.CreationDate().is_null()) {
130       const int session_cookie_age_in_hours =
131           (Time::Now() - cookie.CreationDate()).InHours();
132       if (session_cookie_age_in_hours > kHoursInOneWeek) {
133         UMA_HISTOGRAM_CUSTOM_COUNTS("Cookie.SessionAgeInHoursGTOneWeek2",
134                                     session_cookie_age_in_hours,
135                                     kHoursInOneWeek + 1, kHoursInOneYear, 100);
136       } else {
137         UMA_HISTOGRAM_CUSTOM_COUNTS("Cookie.SessionAgeInHoursLTEOneWeek2",
138                                     session_cookie_age_in_hours, 1,
139                                     kHoursInOneWeek + 1, 100);
140       }
141     }
142     // Similar to the above, except this metric tracks time since the cookie was
143     // last updated and not just initial creation.
144     if (!cookie.LastUpdateDate().is_null()) {
145       const int session_cookie_age_since_last_update_in_hours =
146           (Time::Now() - cookie.LastUpdateDate()).InHours();
147       if (session_cookie_age_since_last_update_in_hours > kHoursInOneWeek) {
148         UMA_HISTOGRAM_CUSTOM_COUNTS(
149             "Cookie.SessionAgeSinceLastUpdateInHoursGTOneWeek",
150             session_cookie_age_since_last_update_in_hours, kHoursInOneWeek + 1,
151             kHoursInOneYear, 100);
152       } else {
153         UMA_HISTOGRAM_CUSTOM_COUNTS(
154             "Cookie.SessionAgeSinceLastUpdateInHoursLTEOneWeek",
155             session_cookie_age_since_last_update_in_hours, 1,
156             kHoursInOneWeek + 1, 100);
157       }
158     }
159   }
160 }
161 
162 }  // namespace
163 
164 namespace net {
165 
GetCookieStoreBackgroundSequencePriority()166 base::TaskPriority GetCookieStoreBackgroundSequencePriority() {
167   return base::TaskPriority::USER_BLOCKING;
168 }
169 
170 namespace {
171 
172 // Version number of the database.
173 //
174 // Version 23 - 2024/04/10 - https://crrev.com/c/5169630
175 // Version 22 - 2024/03/22 - https://crrev.com/c/5378176
176 // Version 21 - 2023/11/22 - https://crrev.com/c/5049032
177 // Version 20 - 2023/11/14 - https://crrev.com/c/5030577
178 // Version 19 - 2023/09/22 - https://crrev.com/c/4704672
179 // Version 18 - 2022/04/19 - https://crrev.com/c/3594203
180 //
181 // Versions older than two years should be removed and marked as unsupported.
182 // This was last done in February 2024. https://crrev.com/c/5300252
183 // Be sure to update SQLitePersistentCookieStoreTest.TestInvalidVersionRecovery
184 // to test the latest unsupported version number.
185 //
186 // Unsupported versions:
187 // Version 17 - 2022/01/25 - https://crrev.com/c/3416230
188 // Version 16 - 2021/09/10 - https://crrev.com/c/3152897
189 // Version 15 - 2021/07/01 - https://crrev.com/c/3001822
190 // Version 14 - 2021/02/23 - https://crrev.com/c/2036899
191 // Version 13 - 2020/10/28 - https://crrev.com/c/2505468
192 // Version 12 - 2019/11/20 - https://crrev.com/c/1898301
193 // Version 11 - 2019/04/17 - https://crrev.com/c/1570416
194 // Version 10 - 2018/02/13 - https://crrev.com/c/906675
195 // Version 9  - 2015/04/17 - https://codereview.chromium.org/1083623003
196 // Version 8  - 2015/02/23 - https://codereview.chromium.org/876973003
197 // Version 7  - 2013/12/16 - https://codereview.chromium.org/24734007
198 // Version 6  - 2013/04/23 - https://codereview.chromium.org/14208017
199 // Version 5  - 2011/12/05 - https://codereview.chromium.org/8533013
200 // Version 4  - 2009/09/01 - https://codereview.chromium.org/183021
201 //
202 
203 // Version 23 adds the value for has_cross_site_ancestor and updates any
204 // preexisting cookies with a source_scheme value of kUnset and a is_secure of
205 // true to have a source_scheme value of kSecure.
206 //
207 // Version 22 adds one new field: "source_type". This reflects the source of
208 // the last set/update to the cookie (unknown, http, script, other). Existing
209 // cookies in the DB default to "unknown".
210 //
211 // Version 21 removes the is_same_party column.
212 //
213 // Version 20 changes the UNIQUE constraint to include the source_scheme and
214 // source_port and begins to insert, update, and delete cookies based on their
215 // source_scheme and source_port.
216 //
217 // Version 19 caps expires_utc to no more than 400 days in the future for all
218 // stored cookies with has_expires. This is in compliance with section 7.2 of
219 // draft-ietf-httpbis-rfc6265bis-12.
220 //
221 // Version 18 adds one new field: "last_update_utc" (if not 0 this represents
222 // the last time the cookie was updated). This is distinct from creation_utc
223 // which is carried forward when cookies are updated.
224 //
225 // Version 17 fixes crbug.com/1290841: Bug in V16 migration.
226 //
227 // Version 16 changes the unique constraint's order of columns to have
228 // top_frame_site_key be after host_key. This allows us to use the internal
229 // index created by the UNIQUE keyword without to load cookies by domain
230 // without us needing to supply a top_frame_site_key. This is necessary because
231 // CookieMonster tracks pending cookie loading tasks by host key only.
232 // Version 16 also removes the DEFAULT value from several columns.
233 //
234 // Version 15 adds one new field: "top_frame_site_key" (if not empty then the
235 // string is the scheme and site of the topmost-level frame the cookie was
236 // created in). This field is deserialized into the cookie's partition key.
237 // top_frame_site_key is *NOT* the site-for-cookies when the cookie was created.
238 // In migrating, top_frame_site_key defaults to empty string. This change also
239 // changes the uniqueness constraint on cookies to include the
240 // top_frame_site_key as well.
241 //
242 // Version 14 just reads all encrypted cookies and re-writes them out again to
243 // make sure the new encryption key is in use. This active migration only
244 // happens on Windows, on other OS, this migration is a no-op.
245 //
246 // Version 13 adds two new fields: "source_port" (the port number of the source
247 // origin, and "is_same_party" (boolean indicating whether the cookie had a
248 // SameParty attribute). In migrating, source_port defaults to -1
249 // (url::PORT_UNSPECIFIED) for old entries for which the source port is unknown,
250 // and is_same_party defaults to false.
251 //
252 // Version 12 adds a column for "source_scheme" to store whether the
253 // cookie was set from a URL with a cryptographic scheme.
254 //
255 // Version 11 renames the "firstpartyonly" column to "samesite", and changes any
256 // stored values of kCookieSameSiteNoRestriction into
257 // kCookieSameSiteUnspecified to reflect the fact that those cookies were set
258 // without a SameSite attribute specified. Support for a value of
259 // kCookieSameSiteExtended for "samesite" was added, however, that value is now
260 // deprecated and is mapped to CookieSameSite::UNSPECIFIED when loading from the
261 // database.
262 //
263 // Version 10 removes the uniqueness constraint on the creation time (which
264 // was not propagated up the stack and caused problems in
265 // http://crbug.com/800414 and others).  It replaces that constraint by a
266 // constraint on (name, domain, path), which is spec-compliant (see
267 // https://tools.ietf.org/html/rfc6265#section-5.3 step 11).  Those fields
268 // can then be used in place of the creation time for updating access
269 // time and deleting cookies.
270 // Version 10 also marks all booleans in the store with an "is_" prefix
271 // to indicated their booleanness, as SQLite has no such concept.
272 //
273 // Version 9 adds a partial index to track non-persistent cookies.
274 // Non-persistent cookies sometimes need to be deleted on startup. There are
275 // frequently few or no non-persistent cookies, so the partial index allows the
276 // deletion to be sped up or skipped, without having to page in the DB.
277 //
278 // Version 8 adds "first-party only" cookies.
279 //
280 // Version 7 adds encrypted values.  Old values will continue to be used but
281 // all new values written will be encrypted on selected operating systems.  New
282 // records read by old clients will simply get an empty cookie value while old
283 // records read by new clients will continue to operate with the unencrypted
284 // version.  New and old clients alike will always write/update records with
285 // what they support.
286 //
287 // Version 6 adds cookie priorities. This allows developers to influence the
288 // order in which cookies are evicted in order to meet domain cookie limits.
289 //
290 // Version 5 adds the columns has_expires and is_persistent, so that the
291 // database can store session cookies as well as persistent cookies. Databases
292 // of version 5 are incompatible with older versions of code. If a database of
293 // version 5 is read by older code, session cookies will be treated as normal
294 // cookies. Currently, these fields are written, but not read anymore.
295 //
296 // In version 4, we migrated the time epoch.  If you open the DB with an older
297 // version on Mac or Linux, the times will look wonky, but the file will likely
298 // be usable. On Windows version 3 and 4 are the same.
299 //
300 // Version 3 updated the database to include the last access time, so we can
301 // expire them in decreasing order of use when we've reached the maximum
302 // number of cookies.
303 const int kCurrentVersionNumber = 23;
304 const int kCompatibleVersionNumber = 23;
305 
306 }  // namespace
307 
308 // This class is designed to be shared between any client thread and the
309 // background task runner. It batches operations and commits them on a timer.
310 //
311 // SQLitePersistentCookieStore::Load is called to load all cookies.  It
312 // delegates to Backend::Load, which posts a Backend::LoadAndNotifyOnDBThread
313 // task to the background runner.  This task calls Backend::ChainLoadCookies(),
314 // which repeatedly posts itself to the BG runner to load each eTLD+1's cookies
315 // in separate tasks.  When this is complete, Backend::CompleteLoadOnIOThread is
316 // posted to the client runner, which notifies the caller of
317 // SQLitePersistentCookieStore::Load that the load is complete.
318 //
319 // If a priority load request is invoked via SQLitePersistentCookieStore::
320 // LoadCookiesForKey, it is delegated to Backend::LoadCookiesForKey, which posts
321 // Backend::LoadKeyAndNotifyOnDBThread to the BG runner. That routine loads just
322 // that single domain key (eTLD+1)'s cookies, and posts a Backend::
323 // CompleteLoadForKeyOnIOThread to the client runner to notify the caller of
324 // SQLitePersistentCookieStore::LoadCookiesForKey that that load is complete.
325 //
326 // Subsequent to loading, mutations may be queued by any thread using
327 // AddCookie, UpdateCookieAccessTime, and DeleteCookie. These are flushed to
328 // disk on the BG runner every 30 seconds, 512 operations, or call to Flush(),
329 // whichever occurs first.
330 class SQLitePersistentCookieStore::Backend
331     : public SQLitePersistentStoreBackendBase {
332  public:
Backend(const base::FilePath & path,scoped_refptr<base::SequencedTaskRunner> client_task_runner,scoped_refptr<base::SequencedTaskRunner> background_task_runner,bool restore_old_session_cookies,std::unique_ptr<CookieCryptoDelegate> crypto_delegate,bool enable_exclusive_access)333   Backend(const base::FilePath& path,
334           scoped_refptr<base::SequencedTaskRunner> client_task_runner,
335           scoped_refptr<base::SequencedTaskRunner> background_task_runner,
336           bool restore_old_session_cookies,
337           std::unique_ptr<CookieCryptoDelegate> crypto_delegate,
338           bool enable_exclusive_access)
339       : SQLitePersistentStoreBackendBase(path,
340                                          /* histogram_tag = */ "Cookie",
341                                          kCurrentVersionNumber,
342                                          kCompatibleVersionNumber,
343                                          std::move(background_task_runner),
344                                          std::move(client_task_runner),
345                                          enable_exclusive_access),
346         restore_old_session_cookies_(restore_old_session_cookies),
347         crypto_(std::move(crypto_delegate)) {}
348 
349   Backend(const Backend&) = delete;
350   Backend& operator=(const Backend&) = delete;
351 
352   // Creates or loads the SQLite database.
353   void Load(LoadedCallback loaded_callback);
354 
355   // Loads cookies for the domain key (eTLD+1). If no key is supplied then this
356   // behaves identically to `Load`.
357   void LoadCookiesForKey(base::optional_ref<const std::string> key,
358                          LoadedCallback loaded_callback);
359 
360   // Steps through all results of |statement|, makes a cookie from each, and
361   // adds the cookie to |cookies|. Returns true if everything loaded
362   // successfully.
363   bool MakeCookiesFromSQLStatement(
364       std::vector<std::unique_ptr<CanonicalCookie>>& cookies,
365       sql::Statement& statement,
366       std::unordered_set<std::string>& top_frame_site_keys_to_delete);
367 
368   // Batch a cookie addition.
369   void AddCookie(const CanonicalCookie& cc);
370 
371   // Batch a cookie access time update.
372   void UpdateCookieAccessTime(const CanonicalCookie& cc);
373 
374   // Batch a cookie deletion.
375   void DeleteCookie(const CanonicalCookie& cc);
376 
377   size_t GetQueueLengthForTesting();
378 
379   // Post background delete of all cookies that match |cookies|.
380   void DeleteAllInList(const std::list<CookieOrigin>& cookies);
381 
382  private:
383   // You should call Close() before destructing this object.
~Backend()384   ~Backend() override {
385     DCHECK_EQ(0u, num_pending_);
386     DCHECK(pending_.empty());
387   }
388 
389   // Database upgrade statements.
390   std::optional<int> DoMigrateDatabaseSchema() override;
391 
392   class PendingOperation {
393    public:
394     enum OperationType {
395       COOKIE_ADD,
396       COOKIE_UPDATEACCESS,
397       COOKIE_DELETE,
398     };
399 
PendingOperation(OperationType op,const CanonicalCookie & cc)400     PendingOperation(OperationType op, const CanonicalCookie& cc)
401         : op_(op), cc_(cc) {}
402 
op() const403     OperationType op() const { return op_; }
cc() const404     const CanonicalCookie& cc() const { return cc_; }
405 
406    private:
407     OperationType op_;
408     CanonicalCookie cc_;
409   };
410 
411  private:
412   // Creates or loads the SQLite database on background runner. Supply domain
413   // key (eTLD+1) to only load for this domain.
414   void LoadAndNotifyInBackground(base::optional_ref<const std::string> key,
415                                  LoadedCallback loaded_callback);
416 
417   // Notifies the CookieMonster when loading completes for a specific domain key
418   // or for all domain keys. Triggers the callback and passes it all cookies
419   // that have been loaded from DB since last IO notification.
420   void NotifyLoadCompleteInForeground(LoadedCallback loaded_callback,
421                                       bool load_success);
422 
423   // Called from Load when crypto gets obtained.
424   void CryptoHasInitFromLoad(base::optional_ref<const std::string> key,
425                              LoadedCallback loaded_callback);
426 
427   // Initialize the Cookies table.
428   bool CreateDatabaseSchema() override;
429 
430   // Initialize the data base.
431   bool DoInitializeDatabase() override;
432 
433   // Loads cookies for the next domain key from the DB, then either reschedules
434   // itself or schedules the provided callback to run on the client runner (if
435   // all domains are loaded).
436   void ChainLoadCookies(LoadedCallback loaded_callback);
437 
438   // Load all cookies for a set of domains/hosts. The error recovery code
439   // assumes |key| includes all related domains within an eTLD + 1.
440   bool LoadCookiesForDomains(const std::set<std::string>& key);
441 
442   void DeleteTopFrameSiteKeys(
443       const std::unordered_set<std::string>& top_frame_site_keys);
444 
445   // Batch a cookie operation (add or delete)
446   void BatchOperation(PendingOperation::OperationType op,
447                       const CanonicalCookie& cc);
448   // Commit our pending operations to the database.
449   void DoCommit() override;
450 
451   void DeleteSessionCookiesOnStartup();
452 
453   void BackgroundDeleteAllInList(const std::list<CookieOrigin>& cookies);
454 
455   // Shared code between the different load strategies to be used after all
456   // cookies have been loaded.
457   void FinishedLoadingCookies(LoadedCallback loaded_callback, bool success);
458 
RecordOpenDBProblem()459   void RecordOpenDBProblem() override {
460     RecordCookieLoadProblem(COOKIE_LOAD_PROBLEM_OPEN_DB);
461   }
462 
RecordDBMigrationProblem()463   void RecordDBMigrationProblem() override {
464     RecordCookieLoadProblem(COOKIE_LOAD_PROBLEM_OPEN_DB);
465   }
466 
467   typedef std::list<std::unique_ptr<PendingOperation>> PendingOperationsForKey;
468   typedef std::map<CanonicalCookie::StrictlyUniqueCookieKey,
469                    PendingOperationsForKey>
470       PendingOperationsMap;
471   PendingOperationsMap pending_ GUARDED_BY(lock_);
472   PendingOperationsMap::size_type num_pending_ GUARDED_BY(lock_) = 0;
473   // Guard |cookies_|, |pending_|, |num_pending_|.
474   base::Lock lock_;
475 
476   // Temporary buffer for cookies loaded from DB. Accumulates cookies to reduce
477   // the number of messages sent to the client runner. Sent back in response to
478   // individual load requests for domain keys or when all loading completes.
479   std::vector<std::unique_ptr<CanonicalCookie>> cookies_ GUARDED_BY(lock_);
480 
481   // Map of domain keys(eTLD+1) to domains/hosts that are to be loaded from DB.
482   std::map<std::string, std::set<std::string>> keys_to_load_;
483 
484   // If false, we should filter out session cookies when reading the DB.
485   bool restore_old_session_cookies_;
486 
487   // Crypto instance, or nullptr if encryption is disabled.
488   std::unique_ptr<CookieCryptoDelegate> crypto_;
489 };
490 
491 namespace {
492 
493 // Possible values for the 'priority' column.
494 enum DBCookiePriority {
495   kCookiePriorityLow = 0,
496   kCookiePriorityMedium = 1,
497   kCookiePriorityHigh = 2,
498 };
499 
CookiePriorityToDBCookiePriority(CookiePriority value)500 DBCookiePriority CookiePriorityToDBCookiePriority(CookiePriority value) {
501   switch (value) {
502     case COOKIE_PRIORITY_LOW:
503       return kCookiePriorityLow;
504     case COOKIE_PRIORITY_MEDIUM:
505       return kCookiePriorityMedium;
506     case COOKIE_PRIORITY_HIGH:
507       return kCookiePriorityHigh;
508   }
509 
510   NOTREACHED();
511   return kCookiePriorityMedium;
512 }
513 
DBCookiePriorityToCookiePriority(DBCookiePriority value)514 CookiePriority DBCookiePriorityToCookiePriority(DBCookiePriority value) {
515   switch (value) {
516     case kCookiePriorityLow:
517       return COOKIE_PRIORITY_LOW;
518     case kCookiePriorityMedium:
519       return COOKIE_PRIORITY_MEDIUM;
520     case kCookiePriorityHigh:
521       return COOKIE_PRIORITY_HIGH;
522   }
523 
524   NOTREACHED();
525   return COOKIE_PRIORITY_DEFAULT;
526 }
527 
528 // Possible values for the 'samesite' column
529 enum DBCookieSameSite {
530   kCookieSameSiteUnspecified = -1,
531   kCookieSameSiteNoRestriction = 0,
532   kCookieSameSiteLax = 1,
533   kCookieSameSiteStrict = 2,
534   // Deprecated, mapped to kCookieSameSiteUnspecified.
535   kCookieSameSiteExtended = 3
536 };
537 
CookieSameSiteToDBCookieSameSite(CookieSameSite value)538 DBCookieSameSite CookieSameSiteToDBCookieSameSite(CookieSameSite value) {
539   switch (value) {
540     case CookieSameSite::NO_RESTRICTION:
541       return kCookieSameSiteNoRestriction;
542     case CookieSameSite::LAX_MODE:
543       return kCookieSameSiteLax;
544     case CookieSameSite::STRICT_MODE:
545       return kCookieSameSiteStrict;
546     case CookieSameSite::UNSPECIFIED:
547       return kCookieSameSiteUnspecified;
548   }
549 }
550 
DBCookieSameSiteToCookieSameSite(DBCookieSameSite value)551 CookieSameSite DBCookieSameSiteToCookieSameSite(DBCookieSameSite value) {
552   CookieSameSite samesite = CookieSameSite::UNSPECIFIED;
553   switch (value) {
554     case kCookieSameSiteNoRestriction:
555       samesite = CookieSameSite::NO_RESTRICTION;
556       break;
557     case kCookieSameSiteLax:
558       samesite = CookieSameSite::LAX_MODE;
559       break;
560     case kCookieSameSiteStrict:
561       samesite = CookieSameSite::STRICT_MODE;
562       break;
563     // SameSite=Extended is deprecated, so we map to UNSPECIFIED.
564     case kCookieSameSiteExtended:
565     case kCookieSameSiteUnspecified:
566       samesite = CookieSameSite::UNSPECIFIED;
567       break;
568   }
569   return samesite;
570 }
571 
572 // Possible values for the `source` column
573 enum DBCookieSourceType {
574   kDBCookieSourceTypeUnknown = 0,
575   kDBCookieSourceTypeHTTP = 1,
576   kDBCookieSourceTypeScript = 2,
577   kDBCookieSourceTypeOther = 3,
578 };
579 
CookieSourceTypeToDBCookieSourceType(CookieSourceType value)580 DBCookieSourceType CookieSourceTypeToDBCookieSourceType(
581     CookieSourceType value) {
582   switch (value) {
583     case CookieSourceType::kUnknown:
584       return kDBCookieSourceTypeUnknown;
585     case CookieSourceType::kHTTP:
586       return kDBCookieSourceTypeHTTP;
587     case CookieSourceType::kScript:
588       return kDBCookieSourceTypeScript;
589     case CookieSourceType::kOther:
590       return kDBCookieSourceTypeOther;
591   }
592 }
593 
DBCookieSourceTypeToCookieSourceType(DBCookieSourceType value)594 CookieSourceType DBCookieSourceTypeToCookieSourceType(
595     DBCookieSourceType value) {
596   switch (value) {
597     case kDBCookieSourceTypeUnknown:
598       return CookieSourceType::kUnknown;
599     case kDBCookieSourceTypeHTTP:
600       return CookieSourceType::kHTTP;
601     case kDBCookieSourceTypeScript:
602       return CookieSourceType::kScript;
603     case kDBCookieSourceTypeOther:
604       return CookieSourceType::kOther;
605     default:
606       return CookieSourceType::kUnknown;
607   }
608 }
609 
DBToCookieSourceScheme(int value)610 CookieSourceScheme DBToCookieSourceScheme(int value) {
611   int enum_max_value = static_cast<int>(CookieSourceScheme::kMaxValue);
612 
613   if (value < 0 || value > enum_max_value) {
614     DLOG(WARNING) << "DB read of cookie's source scheme is invalid. Resetting "
615                      "value to unset.";
616     value = static_cast<int>(
617         CookieSourceScheme::kUnset);  // Reset value to a known, useful, state.
618   }
619 
620   return static_cast<CookieSourceScheme>(value);
621 }
622 
623 // Increments a specified TimeDelta by the duration between this object's
624 // constructor and destructor. Not thread safe. Multiple instances may be
625 // created with the same delta instance as long as their lifetimes are nested.
626 // The shortest lived instances have no impact.
627 class IncrementTimeDelta {
628  public:
IncrementTimeDelta(base::TimeDelta * delta)629   explicit IncrementTimeDelta(base::TimeDelta* delta)
630       : delta_(delta), original_value_(*delta), start_(base::Time::Now()) {}
631 
632   IncrementTimeDelta(const IncrementTimeDelta&) = delete;
633   IncrementTimeDelta& operator=(const IncrementTimeDelta&) = delete;
634 
~IncrementTimeDelta()635   ~IncrementTimeDelta() {
636     *delta_ = original_value_ + base::Time::Now() - start_;
637   }
638 
639  private:
640   raw_ptr<base::TimeDelta> delta_;
641   base::TimeDelta original_value_;
642   base::Time start_;
643 };
644 
CreateV20Schema(sql::Database * db)645 bool CreateV20Schema(sql::Database* db) {
646   CHECK(!db->DoesTableExist("cookies"));
647 
648   const char* kCreateTableQuery =
649       "CREATE TABLE cookies("
650       "creation_utc INTEGER NOT NULL,"
651       "host_key TEXT NOT NULL,"
652       "top_frame_site_key TEXT NOT NULL,"
653       "name TEXT NOT NULL,"
654       "value TEXT NOT NULL,"
655       "encrypted_value BLOB NOT NULL,"
656       "path TEXT NOT NULL,"
657       "expires_utc INTEGER NOT NULL,"
658       "is_secure INTEGER NOT NULL,"
659       "is_httponly INTEGER NOT NULL,"
660       "last_access_utc INTEGER NOT NULL,"
661       "has_expires INTEGER NOT NULL,"
662       "is_persistent INTEGER NOT NULL,"
663       "priority INTEGER NOT NULL,"
664       "samesite INTEGER NOT NULL,"
665       "source_scheme INTEGER NOT NULL,"
666       "source_port INTEGER NOT NULL,"
667       "is_same_party INTEGER NOT NULL,"
668       "last_update_utc INTEGER NOT NULL);";
669 
670   const char* kCreateIndexQuery =
671       "CREATE UNIQUE INDEX cookies_unique_index "
672       "ON cookies(host_key, top_frame_site_key, name, path, source_scheme, "
673       "source_port)";
674 
675   return db->Execute(kCreateTableQuery) && db->Execute(kCreateIndexQuery);
676 }
677 
CreateV21Schema(sql::Database * db)678 bool CreateV21Schema(sql::Database* db) {
679   CHECK(!db->DoesTableExist("cookies"));
680 
681   const char* kCreateTableQuery =
682       "CREATE TABLE cookies("
683       "creation_utc INTEGER NOT NULL,"
684       "host_key TEXT NOT NULL,"
685       "top_frame_site_key TEXT NOT NULL,"
686       "name TEXT NOT NULL,"
687       "value TEXT NOT NULL,"
688       "encrypted_value BLOB NOT NULL,"
689       "path TEXT NOT NULL,"
690       "expires_utc INTEGER NOT NULL,"
691       "is_secure INTEGER NOT NULL,"
692       "is_httponly INTEGER NOT NULL,"
693       "last_access_utc INTEGER NOT NULL,"
694       "has_expires INTEGER NOT NULL,"
695       "is_persistent INTEGER NOT NULL,"
696       "priority INTEGER NOT NULL,"
697       "samesite INTEGER NOT NULL,"
698       "source_scheme INTEGER NOT NULL,"
699       "source_port INTEGER NOT NULL,"
700       "last_update_utc INTEGER NOT NULL);";
701 
702   const char* kCreateIndexQuery =
703       "CREATE UNIQUE INDEX cookies_unique_index "
704       "ON cookies(host_key, top_frame_site_key, name, path, source_scheme, "
705       "source_port)";
706 
707   return db->Execute(kCreateTableQuery) && db->Execute(kCreateIndexQuery);
708 }
709 
CreateV22Schema(sql::Database * db)710 bool CreateV22Schema(sql::Database* db) {
711   CHECK(!db->DoesTableExist("cookies"));
712 
713   const char* kCreateTableQuery =
714       "CREATE TABLE cookies("
715       "creation_utc INTEGER NOT NULL,"
716       "host_key TEXT NOT NULL,"
717       "top_frame_site_key TEXT NOT NULL,"
718       "name TEXT NOT NULL,"
719       "value TEXT NOT NULL,"
720       "encrypted_value BLOB NOT NULL,"
721       "path TEXT NOT NULL,"
722       "expires_utc INTEGER NOT NULL,"
723       "is_secure INTEGER NOT NULL,"
724       "is_httponly INTEGER NOT NULL,"
725       "last_access_utc INTEGER NOT NULL,"
726       "has_expires INTEGER NOT NULL,"
727       "is_persistent INTEGER NOT NULL,"
728       "priority INTEGER NOT NULL,"
729       "samesite INTEGER NOT NULL,"
730       "source_scheme INTEGER NOT NULL,"
731       "source_port INTEGER NOT NULL,"
732       "last_update_utc INTEGER NOT NULL,"
733       "source_type INTEGER NOT NULL);";
734 
735   const char* kCreateIndexQuery =
736       "CREATE UNIQUE INDEX cookies_unique_index "
737       "ON cookies(host_key, top_frame_site_key, name, path, source_scheme, "
738       "source_port)";
739 
740   return db->Execute(kCreateTableQuery) && db->Execute(kCreateIndexQuery);
741 }
742 
CreateV23Schema(sql::Database * db)743 bool CreateV23Schema(sql::Database* db) {
744   CHECK(!db->DoesTableExist("cookies"));
745 
746   const char* kCreateTableQuery =
747       "CREATE TABLE cookies("
748       "creation_utc INTEGER NOT NULL,"
749       "host_key TEXT NOT NULL,"
750       "top_frame_site_key TEXT NOT NULL,"
751       "name TEXT NOT NULL,"
752       "value TEXT NOT NULL,"
753       "encrypted_value BLOB NOT NULL,"
754       "path TEXT NOT NULL,"
755       "expires_utc INTEGER NOT NULL,"
756       "is_secure INTEGER NOT NULL,"
757       "is_httponly INTEGER NOT NULL,"
758       "last_access_utc INTEGER NOT NULL,"
759       "has_expires INTEGER NOT NULL,"
760       "is_persistent INTEGER NOT NULL,"
761       "priority INTEGER NOT NULL,"
762       "samesite INTEGER NOT NULL,"
763       "source_scheme INTEGER NOT NULL,"
764       "source_port INTEGER NOT NULL,"
765       "last_update_utc INTEGER NOT NULL,"
766       "source_type INTEGER NOT NULL,"
767       "has_cross_site_ancestor INTEGER NOT NULL);";
768 
769   const char* kCreateIndexQuery =
770       "CREATE UNIQUE INDEX cookies_unique_index "
771       "ON cookies(host_key, top_frame_site_key, has_cross_site_ancestor, "
772       "name, path, source_scheme, source_port)";
773 
774   return db->Execute(kCreateTableQuery) && db->Execute(kCreateIndexQuery);
775 }
776 
777 }  // namespace
778 
Load(LoadedCallback loaded_callback)779 void SQLitePersistentCookieStore::Backend::Load(
780     LoadedCallback loaded_callback) {
781   LoadCookiesForKey(std::nullopt, std::move(loaded_callback));
782 }
783 
LoadCookiesForKey(base::optional_ref<const std::string> key,LoadedCallback loaded_callback)784 void SQLitePersistentCookieStore::Backend::LoadCookiesForKey(
785     base::optional_ref<const std::string> key,
786     LoadedCallback loaded_callback) {
787   if (crypto_) {
788     crypto_->Init(base::BindOnce(&Backend::CryptoHasInitFromLoad, this,
789                                  key.CopyAsOptional(),
790                                  std::move(loaded_callback)));
791   } else {
792     CryptoHasInitFromLoad(key, std::move(loaded_callback));
793   }
794 }
795 
CryptoHasInitFromLoad(base::optional_ref<const std::string> key,LoadedCallback loaded_callback)796 void SQLitePersistentCookieStore::Backend::CryptoHasInitFromLoad(
797     base::optional_ref<const std::string> key,
798     LoadedCallback loaded_callback) {
799   PostBackgroundTask(
800       FROM_HERE,
801       base::BindOnce(&Backend::LoadAndNotifyInBackground, this,
802                      key.CopyAsOptional(), std::move(loaded_callback)));
803 }
804 
LoadAndNotifyInBackground(base::optional_ref<const std::string> key,LoadedCallback loaded_callback)805 void SQLitePersistentCookieStore::Backend::LoadAndNotifyInBackground(
806     base::optional_ref<const std::string> key,
807     LoadedCallback loaded_callback) {
808   DCHECK(background_task_runner()->RunsTasksInCurrentSequence());
809   bool success = false;
810 
811   if (InitializeDatabase()) {
812     if (!key.has_value()) {
813       ChainLoadCookies(std::move(loaded_callback));
814       return;
815     }
816 
817     auto it = keys_to_load_.find(*key);
818     if (it != keys_to_load_.end()) {
819       success = LoadCookiesForDomains(it->second);
820       keys_to_load_.erase(it);
821     } else {
822       success = true;
823     }
824   }
825 
826   FinishedLoadingCookies(std::move(loaded_callback), success);
827 }
828 
NotifyLoadCompleteInForeground(LoadedCallback loaded_callback,bool load_success)829 void SQLitePersistentCookieStore::Backend::NotifyLoadCompleteInForeground(
830     LoadedCallback loaded_callback,
831     bool load_success) {
832   DCHECK(client_task_runner()->RunsTasksInCurrentSequence());
833 
834   std::vector<std::unique_ptr<CanonicalCookie>> cookies;
835   {
836     base::AutoLock locked(lock_);
837     cookies.swap(cookies_);
838   }
839 
840   std::move(loaded_callback).Run(std::move(cookies));
841 }
842 
CreateDatabaseSchema()843 bool SQLitePersistentCookieStore::Backend::CreateDatabaseSchema() {
844   DCHECK(db());
845 
846   return db()->DoesTableExist("cookies") || CreateV23Schema(db());
847 }
848 
DoInitializeDatabase()849 bool SQLitePersistentCookieStore::Backend::DoInitializeDatabase() {
850   DCHECK(db());
851 
852   // Retrieve all the domains
853   sql::Statement smt(
854       db()->GetUniqueStatement("SELECT DISTINCT host_key FROM cookies"));
855 
856   if (!smt.is_valid()) {
857     Reset();
858     return false;
859   }
860 
861   std::vector<std::string> host_keys;
862   while (smt.Step())
863     host_keys.push_back(smt.ColumnString(0));
864 
865   // Build a map of domain keys (always eTLD+1) to domains.
866   for (const auto& domain : host_keys) {
867     std::string key = CookieMonster::GetKey(domain);
868     keys_to_load_[key].insert(domain);
869   }
870 
871   if (!restore_old_session_cookies_)
872     DeleteSessionCookiesOnStartup();
873 
874   return true;
875 }
876 
ChainLoadCookies(LoadedCallback loaded_callback)877 void SQLitePersistentCookieStore::Backend::ChainLoadCookies(
878     LoadedCallback loaded_callback) {
879   DCHECK(background_task_runner()->RunsTasksInCurrentSequence());
880 
881   bool load_success = true;
882 
883   if (!db()) {
884     // Close() has been called on this store.
885     load_success = false;
886   } else if (keys_to_load_.size() > 0) {
887     // Load cookies for the first domain key.
888     auto it = keys_to_load_.begin();
889     load_success = LoadCookiesForDomains(it->second);
890     keys_to_load_.erase(it);
891   }
892 
893   // If load is successful and there are more domain keys to be loaded,
894   // then post a background task to continue chain-load;
895   // Otherwise notify on client runner.
896   if (load_success && keys_to_load_.size() > 0) {
897     bool success = background_task_runner()->PostTask(
898         FROM_HERE, base::BindOnce(&Backend::ChainLoadCookies, this,
899                                   std::move(loaded_callback)));
900     if (!success) {
901       LOG(WARNING) << "Failed to post task from " << FROM_HERE.ToString()
902                    << " to background_task_runner().";
903     }
904   } else {
905     FinishedLoadingCookies(std::move(loaded_callback), load_success);
906   }
907 }
908 
LoadCookiesForDomains(const std::set<std::string> & domains)909 bool SQLitePersistentCookieStore::Backend::LoadCookiesForDomains(
910     const std::set<std::string>& domains) {
911   DCHECK(background_task_runner()->RunsTasksInCurrentSequence());
912 
913   sql::Statement smt, delete_statement;
914   if (restore_old_session_cookies_) {
915     smt.Assign(db()->GetCachedStatement(
916         SQL_FROM_HERE,
917         "SELECT creation_utc, host_key, top_frame_site_key, name, value, path, "
918         "expires_utc, is_secure, is_httponly, last_access_utc, has_expires, "
919         "is_persistent, priority, encrypted_value, samesite, source_scheme, "
920         "source_port, last_update_utc, source_type, has_cross_site_ancestor "
921         "FROM cookies WHERE host_key "
922         "= "
923         "?"));
924   } else {
925     smt.Assign(db()->GetCachedStatement(
926         SQL_FROM_HERE,
927         "SELECT creation_utc, host_key, top_frame_site_key, name, value, path, "
928         "expires_utc, is_secure, is_httponly, last_access_utc, has_expires, "
929         "is_persistent, priority, encrypted_value, samesite, source_scheme, "
930         "source_port, last_update_utc, source_type, has_cross_site_ancestor "
931         "FROM cookies WHERE "
932         "host_key = ? AND "
933         "is_persistent = 1"));
934   }
935   delete_statement.Assign(db()->GetCachedStatement(
936       SQL_FROM_HERE, "DELETE FROM cookies WHERE host_key = ?"));
937   if (!smt.is_valid() || !delete_statement.is_valid()) {
938     delete_statement.Clear();
939     smt.Clear();  // Disconnect smt_ref from db_.
940     Reset();
941     return false;
942   }
943 
944   std::vector<std::unique_ptr<CanonicalCookie>> cookies;
945   std::unordered_set<std::string> top_frame_site_keys_to_delete;
946   auto it = domains.begin();
947   bool ok = true;
948   for (; it != domains.end() && ok; ++it) {
949     smt.BindString(0, *it);
950     ok = MakeCookiesFromSQLStatement(cookies, smt,
951                                      top_frame_site_keys_to_delete);
952     smt.Reset(true);
953   }
954 
955   DeleteTopFrameSiteKeys(std::move(top_frame_site_keys_to_delete));
956 
957   if (ok) {
958     base::AutoLock locked(lock_);
959     std::move(cookies.begin(), cookies.end(), std::back_inserter(cookies_));
960   } else {
961     // There were some cookies that were in database but could not be loaded
962     // and handed over to CookieMonster. This is trouble since it means that
963     // if some website tries to send them again, CookieMonster won't know to
964     // issue a delete, and then the addition would violate the uniqueness
965     // constraints and not go through.
966     //
967     // For data consistency, we drop the entire eTLD group.
968     for (const std::string& domain : domains) {
969       delete_statement.BindString(0, domain);
970       if (!delete_statement.Run()) {
971         // TODO(morlovich): Is something more drastic called for here?
972         RecordCookieLoadProblem(COOKIE_LOAD_PROBLEM_RECOVERY_FAILED);
973       }
974       delete_statement.Reset(true);
975     }
976   }
977   return true;
978 }
979 
DeleteTopFrameSiteKeys(const std::unordered_set<std::string> & top_frame_site_keys)980 void SQLitePersistentCookieStore::Backend::DeleteTopFrameSiteKeys(
981     const std::unordered_set<std::string>& top_frame_site_keys) {
982   if (top_frame_site_keys.empty())
983     return;
984 
985   sql::Statement delete_statement;
986   delete_statement.Assign(db()->GetCachedStatement(
987       SQL_FROM_HERE, "DELETE FROM cookies WHERE top_frame_site_key = ?"));
988   if (!delete_statement.is_valid())
989     return;
990 
991   for (const std::string& key : top_frame_site_keys) {
992     delete_statement.BindString(0, key);
993     if (!delete_statement.Run())
994       RecordCookieLoadProblem(COOKIE_LOAD_DELETE_COOKIE_PARTITION_FAILED);
995     delete_statement.Reset(true);
996   }
997 }
998 
MakeCookiesFromSQLStatement(std::vector<std::unique_ptr<CanonicalCookie>> & cookies,sql::Statement & statement,std::unordered_set<std::string> & top_frame_site_keys_to_delete)999 bool SQLitePersistentCookieStore::Backend::MakeCookiesFromSQLStatement(
1000     std::vector<std::unique_ptr<CanonicalCookie>>& cookies,
1001     sql::Statement& statement,
1002     std::unordered_set<std::string>& top_frame_site_keys_to_delete) {
1003   DCHECK(background_task_runner()->RunsTasksInCurrentSequence());
1004   bool ok = true;
1005   while (statement.Step()) {
1006     std::string value;
1007     std::string encrypted_value = statement.ColumnString(13);
1008     if (!encrypted_value.empty() && crypto_) {
1009       bool decrypt_ok = crypto_->DecryptString(encrypted_value, &value);
1010       if (!decrypt_ok) {
1011         RecordCookieLoadProblem(COOKIE_LOAD_PROBLEM_DECRYPT_FAILED);
1012         ok = false;
1013         continue;
1014       }
1015     } else {
1016       value = statement.ColumnString(4);
1017     }
1018 
1019     // If we can't create a CookiePartitionKey from SQL values, we delete any
1020     // cookie with the same top_frame_site_key value.
1021     base::expected<std::optional<CookiePartitionKey>, std::string>
1022         partition_key = CookiePartitionKey::FromStorage(
1023             statement.ColumnString(2), statement.ColumnBool(19));
1024     if (!partition_key.has_value()) {
1025       top_frame_site_keys_to_delete.insert(statement.ColumnString(2));
1026       continue;
1027     }
1028     // Returns nullptr if the resulting cookie is not canonical.
1029     std::unique_ptr<net::CanonicalCookie> cc = CanonicalCookie::FromStorage(
1030         /*name=*/statement.ColumnString(3),        //
1031         value,                                     //
1032         /*domain=*/statement.ColumnString(1),      //
1033         /*path=*/statement.ColumnString(5),        //
1034         /*creation=*/statement.ColumnTime(0),      //
1035         /*expiration=*/statement.ColumnTime(6),    //
1036         /*last_access=*/statement.ColumnTime(9),   //
1037         /*last_update=*/statement.ColumnTime(17),  //
1038         /*secure=*/statement.ColumnBool(7),        //
1039         /*httponly=*/statement.ColumnBool(8),      //
1040                                                    /*same_site=*/
1041         DBCookieSameSiteToCookieSameSite(
1042             static_cast<DBCookieSameSite>(statement.ColumnInt(14))),  //
1043         /*priority=*/
1044         DBCookiePriorityToCookiePriority(
1045             static_cast<DBCookiePriority>(statement.ColumnInt(12))),        //
1046         /*partition_key=*/std::move(partition_key.value()),                 //
1047         /*source_scheme=*/DBToCookieSourceScheme(statement.ColumnInt(15)),  //
1048         /*source_port=*/statement.ColumnInt(16),                            //
1049         /*source_type=*/
1050         DBCookieSourceTypeToCookieSourceType(
1051             static_cast<DBCookieSourceType>(statement.ColumnInt(18))));  //
1052     if (cc) {
1053       DLOG_IF(WARNING, cc->CreationDate() > Time::Now())
1054           << "CreationDate too recent";
1055       if (!cc->LastUpdateDate().is_null()) {
1056         DLOG_IF(WARNING, cc->LastUpdateDate() > Time::Now())
1057             << "LastUpdateDate too recent";
1058         // In order to anticipate the potential effects of the expiry limit in
1059         // rfc6265bis, we need to check how long it's been since the cookie was
1060         // refreshed (if LastUpdateDate is populated). We use 100 buckets for
1061         // the highest reasonable granularity, set 1 day as the minimum and
1062         // don't track over a 400 max (since these cookies will expire anyway).
1063         UMA_HISTOGRAM_CUSTOM_COUNTS(
1064             "Cookie.DaysSinceRefreshForRetrieval",
1065             (base::Time::Now() - cc->LastUpdateDate()).InDays(), 1, 400, 100);
1066       }
1067       HistogramCookieAge(*cc);
1068       cookies.push_back(std::move(cc));
1069     } else {
1070       RecordCookieLoadProblem(COOKIE_LOAD_PROBLEM_NON_CANONICAL);
1071       ok = false;
1072     }
1073   }
1074 
1075   return ok;
1076 }
1077 
1078 std::optional<int>
DoMigrateDatabaseSchema()1079 SQLitePersistentCookieStore::Backend::DoMigrateDatabaseSchema() {
1080   int cur_version = meta_table()->GetVersionNumber();
1081 
1082   if (cur_version == 18) {
1083     SCOPED_UMA_HISTOGRAM_TIMER("Cookie.TimeDatabaseMigrationToV19");
1084 
1085     sql::Statement update_statement(
1086         db()->GetCachedStatement(SQL_FROM_HERE,
1087                                  "UPDATE cookies SET expires_utc = ? WHERE "
1088                                  "has_expires = 1 AND expires_utc > ?"));
1089     if (!update_statement.is_valid()) {
1090       return std::nullopt;
1091     }
1092 
1093     sql::Transaction transaction(db());
1094     if (!transaction.Begin()) {
1095       return std::nullopt;
1096     }
1097 
1098     base::Time expires_cap = base::Time::Now() + base::Days(400);
1099     update_statement.BindTime(0, expires_cap);
1100     update_statement.BindTime(1, expires_cap);
1101     if (!update_statement.Run()) {
1102       return std::nullopt;
1103     }
1104 
1105     ++cur_version;
1106     if (!meta_table()->SetVersionNumber(cur_version) ||
1107         !meta_table()->SetCompatibleVersionNumber(
1108             std::min(cur_version, kCompatibleVersionNumber)) ||
1109         !transaction.Commit()) {
1110       return std::nullopt;
1111     }
1112   }
1113 
1114   if (cur_version == 19) {
1115     SCOPED_UMA_HISTOGRAM_TIMER("Cookie.TimeDatabaseMigrationToV20");
1116 
1117     sql::Transaction transaction(db());
1118     if (!transaction.Begin()) {
1119       return std::nullopt;
1120     }
1121 
1122     if (!db()->Execute("DROP TABLE IF EXISTS cookies_old")) {
1123       return std::nullopt;
1124     }
1125     if (!db()->Execute("ALTER TABLE cookies RENAME TO cookies_old")) {
1126       return std::nullopt;
1127     }
1128     if (!db()->Execute("DROP INDEX IF EXISTS cookies_unique_index")) {
1129       return std::nullopt;
1130     }
1131 
1132     if (!CreateV20Schema(db())) {
1133       return std::nullopt;
1134     }
1135 
1136     static constexpr char insert_cookies_sql[] =
1137         "INSERT OR REPLACE INTO cookies "
1138         "(creation_utc, host_key, top_frame_site_key, name, value, "
1139         "encrypted_value, path, expires_utc, is_secure, is_httponly, "
1140         "last_access_utc, has_expires, is_persistent, priority, samesite, "
1141         "source_scheme, source_port, is_same_party, last_update_utc) "
1142         "SELECT creation_utc, host_key, top_frame_site_key, name, value,"
1143         "       encrypted_value, path, expires_utc, is_secure, is_httponly,"
1144         "       last_access_utc, has_expires, is_persistent, priority, "
1145         "       samesite, source_scheme, source_port, is_same_party, "
1146         "last_update_utc "
1147         "FROM cookies_old ORDER BY creation_utc ASC";
1148     if (!db()->Execute(insert_cookies_sql)) {
1149       return std::nullopt;
1150     }
1151     if (!db()->Execute("DROP TABLE cookies_old")) {
1152       return std::nullopt;
1153     }
1154 
1155     ++cur_version;
1156     if (!meta_table()->SetVersionNumber(cur_version) ||
1157         !meta_table()->SetCompatibleVersionNumber(
1158             std::min(cur_version, kCompatibleVersionNumber)) ||
1159         !transaction.Commit()) {
1160       return std::nullopt;
1161     }
1162   }
1163 
1164   if (cur_version == 20) {
1165     SCOPED_UMA_HISTOGRAM_TIMER("Cookie.TimeDatabaseMigrationToV21");
1166 
1167     sql::Transaction transaction(db());
1168     if (!transaction.Begin()) {
1169       return std::nullopt;
1170     }
1171 
1172     if (!db()->Execute("DROP TABLE IF EXISTS cookies_old")) {
1173       return std::nullopt;
1174     }
1175     if (!db()->Execute("ALTER TABLE cookies RENAME TO cookies_old")) {
1176       return std::nullopt;
1177     }
1178     if (!db()->Execute("DROP INDEX IF EXISTS cookies_unique_index")) {
1179       return std::nullopt;
1180     }
1181 
1182     if (!CreateV21Schema(db())) {
1183       return std::nullopt;
1184     }
1185 
1186     static constexpr char insert_cookies_sql[] =
1187         "INSERT OR REPLACE INTO cookies "
1188         "(creation_utc, host_key, top_frame_site_key, name, value, "
1189         "encrypted_value, path, expires_utc, is_secure, is_httponly, "
1190         "last_access_utc, has_expires, is_persistent, priority, samesite, "
1191         "source_scheme, source_port, last_update_utc) "
1192         "SELECT creation_utc, host_key, top_frame_site_key, name, value,"
1193         "       encrypted_value, path, expires_utc, is_secure, is_httponly,"
1194         "       last_access_utc, has_expires, is_persistent, priority, "
1195         "       samesite, source_scheme, source_port, last_update_utc "
1196         "FROM cookies_old ORDER BY creation_utc ASC";
1197     if (!db()->Execute(insert_cookies_sql)) {
1198       return std::nullopt;
1199     }
1200     if (!db()->Execute("DROP TABLE cookies_old")) {
1201       return std::nullopt;
1202     }
1203 
1204     ++cur_version;
1205     if (!meta_table()->SetVersionNumber(cur_version) ||
1206         !meta_table()->SetCompatibleVersionNumber(
1207             std::min(cur_version, kCompatibleVersionNumber)) ||
1208         !transaction.Commit()) {
1209       return std::nullopt;
1210     }
1211   }
1212 
1213   if (cur_version == 21) {
1214     SCOPED_UMA_HISTOGRAM_TIMER("Cookie.TimeDatabaseMigrationToV22");
1215 
1216     sql::Transaction transaction(db());
1217     if (!transaction.Begin()) {
1218       return std::nullopt;
1219     }
1220 
1221     if (!db()->Execute("DROP TABLE IF EXISTS cookies_old")) {
1222       return std::nullopt;
1223     }
1224     if (!db()->Execute("ALTER TABLE cookies RENAME TO cookies_old")) {
1225       return std::nullopt;
1226     }
1227     if (!db()->Execute("DROP INDEX IF EXISTS cookies_unique_index")) {
1228       return std::nullopt;
1229     }
1230 
1231     if (!CreateV22Schema(db())) {
1232       return std::nullopt;
1233     }
1234 
1235     // The default `source_type` is 0 which is CookieSourceType::kUnknown.
1236     static constexpr char insert_cookies_sql[] =
1237         "INSERT OR REPLACE INTO cookies "
1238         "(creation_utc, host_key, top_frame_site_key, name, value, "
1239         "encrypted_value, path, expires_utc, is_secure, is_httponly, "
1240         "last_access_utc, has_expires, is_persistent, priority, samesite, "
1241         "source_scheme, source_port, last_update_utc, source_type) "
1242         "SELECT creation_utc, host_key, top_frame_site_key, name, value,"
1243         "       encrypted_value, path, expires_utc, is_secure, is_httponly,"
1244         "       last_access_utc, has_expires, is_persistent, priority, "
1245         "       samesite, source_scheme, source_port, last_update_utc, 0 "
1246         "FROM cookies_old ORDER BY creation_utc ASC";
1247     if (!db()->Execute(insert_cookies_sql)) {
1248       return std::nullopt;
1249     }
1250     if (!db()->Execute("DROP TABLE cookies_old")) {
1251       return std::nullopt;
1252     }
1253 
1254     ++cur_version;
1255     if (!meta_table()->SetVersionNumber(cur_version) ||
1256         !meta_table()->SetCompatibleVersionNumber(
1257             std::min(cur_version, kCompatibleVersionNumber)) ||
1258         !transaction.Commit()) {
1259       return std::nullopt;
1260     }
1261   }
1262 
1263   if (cur_version == 22) {
1264     SCOPED_UMA_HISTOGRAM_TIMER("Cookie.TimeDatabaseMigrationToV23");
1265     sql::Transaction transaction(db());
1266     if (!transaction.Begin()) {
1267       return std::nullopt;
1268     }
1269 
1270     if (!db()->Execute("DROP TABLE IF EXISTS cookies_old")) {
1271       return std::nullopt;
1272     }
1273     if (!db()->Execute("ALTER TABLE cookies RENAME TO cookies_old")) {
1274       return std::nullopt;
1275     }
1276     if (!db()->Execute("DROP INDEX IF EXISTS cookies_unique_index")) {
1277       return std::nullopt;
1278     }
1279 
1280     if (!CreateV23Schema(db())) {
1281       return std::nullopt;
1282     }
1283     /*
1284      For the case statement setting source_scheme,
1285      value of 0 reflects int value of CookieSourceScheme::kUnset
1286      value of 2 reflects int value of CookieSourceScheme::kSecure
1287 
1288      For the case statement setting has_cross_site_ancestor, it has the
1289      potential to have a origin mismatch due to substring operations.
1290       EX: the domain ample.com will appear as a substring of the domain
1291       example.com even though they are different origins.
1292      We are ok with this because the other elements of the UNIQUE INDEX
1293      will always be different preventing accidental access.
1294     */
1295 
1296     static constexpr char insert_cookies_sql[] =
1297         "INSERT OR REPLACE INTO cookies "
1298         "(creation_utc, host_key, top_frame_site_key, name, value, "
1299         "encrypted_value, path, expires_utc, is_secure, is_httponly, "
1300         "last_access_utc, has_expires, is_persistent, priority, samesite, "
1301         "source_scheme, source_port, last_update_utc, source_type, "
1302         "has_cross_site_ancestor) "
1303         "SELECT creation_utc, host_key, top_frame_site_key, name, value,"
1304         "       encrypted_value, path, expires_utc, is_secure, is_httponly,"
1305         "       last_access_utc, has_expires, is_persistent, priority, "
1306         "       samesite, "
1307         "       CASE WHEN source_scheme = 0 AND is_secure = 1 "
1308         "           THEN 2 ELSE source_scheme END, "
1309         "       source_port, last_update_utc, source_type, "
1310         "       CASE WHEN INSTR(top_frame_site_key, '://') > 0 AND host_key "
1311         "           LIKE CONCAT('%', SUBSTR(top_frame_site_key, "
1312         "           INSTR(top_frame_site_key,'://') + 3),  '%') "
1313         "           THEN 0 ELSE 1 "
1314         "           END AS has_cross_site_ancestor "
1315         "FROM cookies_old ORDER BY creation_utc ASC";
1316     if (!db()->Execute(insert_cookies_sql)) {
1317       return std::nullopt;
1318     }
1319     if (!db()->Execute("DROP TABLE cookies_old")) {
1320       return std::nullopt;
1321     }
1322 
1323     ++cur_version;
1324     if (!meta_table()->SetVersionNumber(cur_version) ||
1325         !meta_table()->SetCompatibleVersionNumber(
1326             std::min(cur_version, kCompatibleVersionNumber)) ||
1327         !transaction.Commit()) {
1328       return std::nullopt;
1329     }
1330   }
1331 
1332   // Put future migration cases here.
1333   return std::make_optional(cur_version);
1334 }
1335 
AddCookie(const CanonicalCookie & cc)1336 void SQLitePersistentCookieStore::Backend::AddCookie(
1337     const CanonicalCookie& cc) {
1338   BatchOperation(PendingOperation::COOKIE_ADD, cc);
1339 }
1340 
UpdateCookieAccessTime(const CanonicalCookie & cc)1341 void SQLitePersistentCookieStore::Backend::UpdateCookieAccessTime(
1342     const CanonicalCookie& cc) {
1343   BatchOperation(PendingOperation::COOKIE_UPDATEACCESS, cc);
1344 }
1345 
DeleteCookie(const CanonicalCookie & cc)1346 void SQLitePersistentCookieStore::Backend::DeleteCookie(
1347     const CanonicalCookie& cc) {
1348   BatchOperation(PendingOperation::COOKIE_DELETE, cc);
1349 }
1350 
BatchOperation(PendingOperation::OperationType op,const CanonicalCookie & cc)1351 void SQLitePersistentCookieStore::Backend::BatchOperation(
1352     PendingOperation::OperationType op,
1353     const CanonicalCookie& cc) {
1354   // Commit every 30 seconds.
1355   constexpr base::TimeDelta kCommitInterval = base::Seconds(30);
1356   // Commit right away if we have more than 512 outstanding operations.
1357   constexpr size_t kCommitAfterBatchSize = 512;
1358   DCHECK(!background_task_runner()->RunsTasksInCurrentSequence());
1359 
1360   // We do a full copy of the cookie here, and hopefully just here.
1361   auto po = std::make_unique<PendingOperation>(op, cc);
1362 
1363   PendingOperationsMap::size_type num_pending;
1364   {
1365     base::AutoLock locked(lock_);
1366     // When queueing the operation, see if it overwrites any already pending
1367     // ones for the same row.
1368     auto key = cc.StrictlyUniqueKey();
1369     auto iter_and_result = pending_.emplace(key, PendingOperationsForKey());
1370     PendingOperationsForKey& ops_for_key = iter_and_result.first->second;
1371     if (!iter_and_result.second) {
1372       // Insert failed -> already have ops.
1373       if (po->op() == PendingOperation::COOKIE_DELETE) {
1374         // A delete op makes all the previous ones irrelevant.
1375         ops_for_key.clear();
1376       } else if (po->op() == PendingOperation::COOKIE_UPDATEACCESS) {
1377         if (!ops_for_key.empty() &&
1378             ops_for_key.back()->op() == PendingOperation::COOKIE_UPDATEACCESS) {
1379           // If access timestamp is updated twice in a row, can dump the earlier
1380           // one.
1381           ops_for_key.pop_back();
1382         }
1383         // At most delete + add before (and no access time updates after above
1384         // conditional).
1385         DCHECK_LE(ops_for_key.size(), 2u);
1386       } else {
1387         // Nothing special is done for adds, since if they're overwriting,
1388         // they'll be preceded by deletes anyway.
1389         DCHECK_LE(ops_for_key.size(), 1u);
1390       }
1391     }
1392     ops_for_key.push_back(std::move(po));
1393     // Note that num_pending_ counts number of calls to BatchOperation(), not
1394     // the current length of the queue; this is intentional to guarantee
1395     // progress, as the length of the queue may decrease in some cases.
1396     num_pending = ++num_pending_;
1397   }
1398 
1399   if (num_pending == 1) {
1400     // We've gotten our first entry for this batch, fire off the timer.
1401     if (!background_task_runner()->PostDelayedTask(
1402             FROM_HERE, base::BindOnce(&Backend::Commit, this),
1403             kCommitInterval)) {
1404       NOTREACHED() << "background_task_runner() is not running.";
1405     }
1406   } else if (num_pending == kCommitAfterBatchSize) {
1407     // We've reached a big enough batch, fire off a commit now.
1408     PostBackgroundTask(FROM_HERE, base::BindOnce(&Backend::Commit, this));
1409   }
1410 }
1411 
DoCommit()1412 void SQLitePersistentCookieStore::Backend::DoCommit() {
1413   DCHECK(background_task_runner()->RunsTasksInCurrentSequence());
1414 
1415   PendingOperationsMap ops;
1416   {
1417     base::AutoLock locked(lock_);
1418     pending_.swap(ops);
1419     num_pending_ = 0;
1420   }
1421 
1422   // Maybe an old timer fired or we are already Close()'ed.
1423   if (!db() || ops.empty())
1424     return;
1425 
1426   sql::Statement add_statement(db()->GetCachedStatement(
1427       SQL_FROM_HERE,
1428       "INSERT INTO cookies (creation_utc, host_key, top_frame_site_key, name, "
1429       "value, encrypted_value, path, expires_utc, is_secure, is_httponly, "
1430       "last_access_utc, has_expires, is_persistent, priority, samesite, "
1431       "source_scheme, source_port, last_update_utc, source_type, "
1432       "has_cross_site_ancestor) "
1433       "VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)"));
1434   if (!add_statement.is_valid())
1435     return;
1436 
1437   sql::Statement update_access_statement(db()->GetCachedStatement(
1438       SQL_FROM_HERE,
1439       "UPDATE cookies SET last_access_utc=? WHERE "
1440       "name=? AND host_key=? AND top_frame_site_key=? AND path=? AND "
1441       "source_scheme=? AND source_port=? AND has_cross_site_ancestor=?"));
1442   if (!update_access_statement.is_valid())
1443     return;
1444 
1445   sql::Statement delete_statement(db()->GetCachedStatement(
1446       SQL_FROM_HERE,
1447       "DELETE FROM cookies WHERE "
1448       "name=? AND host_key=? AND top_frame_site_key=? AND path=? AND "
1449       "source_scheme=? AND source_port=? AND has_cross_site_ancestor=?"));
1450   if (!delete_statement.is_valid())
1451     return;
1452 
1453   sql::Transaction transaction(db());
1454   if (!transaction.Begin())
1455     return;
1456 
1457   for (auto& kv : ops) {
1458     for (std::unique_ptr<PendingOperation>& po_entry : kv.second) {
1459       // Free the cookies as we commit them to the database.
1460       std::unique_ptr<PendingOperation> po(std::move(po_entry));
1461       base::expected<CookiePartitionKey::SerializedCookiePartitionKey,
1462                      std::string>
1463           serialized_partition_key =
1464               CookiePartitionKey::Serialize(po->cc().PartitionKey());
1465       if (!serialized_partition_key.has_value()) {
1466         continue;
1467       }
1468 
1469       switch (po->op()) {
1470         case PendingOperation::COOKIE_ADD:
1471           add_statement.Reset(true);
1472           add_statement.BindTime(0, po->cc().CreationDate());
1473           add_statement.BindString(1, po->cc().Domain());
1474           add_statement.BindString(2, serialized_partition_key->TopLevelSite());
1475           add_statement.BindString(3, po->cc().Name());
1476           if (crypto_) {
1477             std::string encrypted_value;
1478             if (!crypto_->EncryptString(po->cc().Value(), &encrypted_value)) {
1479               DLOG(WARNING) << "Could not encrypt a cookie, skipping add.";
1480               RecordCookieCommitProblem(COOKIE_COMMIT_PROBLEM_ENCRYPT_FAILED);
1481               continue;
1482             }
1483             add_statement.BindCString(4, "");  // value
1484             // BindBlob() immediately makes an internal copy of the data.
1485             add_statement.BindBlob(5, encrypted_value);
1486           } else {
1487             add_statement.BindString(4, po->cc().Value());
1488             add_statement.BindBlob(5,
1489                                    base::span<uint8_t>());  // encrypted_value
1490           }
1491           add_statement.BindString(6, po->cc().Path());
1492           add_statement.BindTime(7, po->cc().ExpiryDate());
1493           add_statement.BindBool(8, po->cc().SecureAttribute());
1494           add_statement.BindBool(9, po->cc().IsHttpOnly());
1495           add_statement.BindTime(10, po->cc().LastAccessDate());
1496           add_statement.BindBool(11, po->cc().IsPersistent());
1497           add_statement.BindBool(12, po->cc().IsPersistent());
1498           add_statement.BindInt(
1499               13, CookiePriorityToDBCookiePriority(po->cc().Priority()));
1500           add_statement.BindInt(
1501               14, CookieSameSiteToDBCookieSameSite(po->cc().SameSite()));
1502           add_statement.BindInt(15, static_cast<int>(po->cc().SourceScheme()));
1503           add_statement.BindInt(16, po->cc().SourcePort());
1504           add_statement.BindTime(17, po->cc().LastUpdateDate());
1505           add_statement.BindInt(
1506               18, CookieSourceTypeToDBCookieSourceType(po->cc().SourceType()));
1507           add_statement.BindBool(
1508               19, serialized_partition_key->has_cross_site_ancestor());
1509 
1510           if (!add_statement.Run()) {
1511             DLOG(WARNING) << "Could not add a cookie to the DB.";
1512             RecordCookieCommitProblem(COOKIE_COMMIT_PROBLEM_ADD);
1513           }
1514           break;
1515 
1516         case PendingOperation::COOKIE_UPDATEACCESS:
1517           update_access_statement.Reset(true);
1518           update_access_statement.BindTime(0, po->cc().LastAccessDate());
1519           update_access_statement.BindString(1, po->cc().Name());
1520           update_access_statement.BindString(2, po->cc().Domain());
1521           update_access_statement.BindString(
1522               3, serialized_partition_key->TopLevelSite());
1523           update_access_statement.BindString(4, po->cc().Path());
1524           update_access_statement.BindInt(
1525               5, static_cast<int>(po->cc().SourceScheme()));
1526           update_access_statement.BindInt(6, po->cc().SourcePort());
1527           update_access_statement.BindBool(
1528               7, serialized_partition_key->has_cross_site_ancestor());
1529           if (!update_access_statement.Run()) {
1530             DLOG(WARNING)
1531                 << "Could not update cookie last access time in the DB.";
1532             RecordCookieCommitProblem(COOKIE_COMMIT_PROBLEM_UPDATE_ACCESS);
1533           }
1534           break;
1535 
1536         case PendingOperation::COOKIE_DELETE:
1537           delete_statement.Reset(true);
1538           delete_statement.BindString(0, po->cc().Name());
1539           delete_statement.BindString(1, po->cc().Domain());
1540           delete_statement.BindString(2,
1541                                       serialized_partition_key->TopLevelSite());
1542           delete_statement.BindString(3, po->cc().Path());
1543           delete_statement.BindInt(4,
1544                                    static_cast<int>(po->cc().SourceScheme()));
1545           delete_statement.BindInt(5, po->cc().SourcePort());
1546           delete_statement.BindBool(
1547               6, serialized_partition_key->has_cross_site_ancestor());
1548           if (!delete_statement.Run()) {
1549             DLOG(WARNING) << "Could not delete a cookie from the DB.";
1550             RecordCookieCommitProblem(COOKIE_COMMIT_PROBLEM_DELETE);
1551           }
1552           break;
1553 
1554         default:
1555           NOTREACHED();
1556           break;
1557       }
1558     }
1559   }
1560   bool commit_ok = transaction.Commit();
1561   if (!commit_ok) {
1562     RecordCookieCommitProblem(COOKIE_COMMIT_PROBLEM_TRANSACTION_COMMIT);
1563   }
1564 }
1565 
GetQueueLengthForTesting()1566 size_t SQLitePersistentCookieStore::Backend::GetQueueLengthForTesting() {
1567   DCHECK(client_task_runner()->RunsTasksInCurrentSequence());
1568   size_t total = 0u;
1569   {
1570     base::AutoLock locked(lock_);
1571     for (const auto& key_val : pending_) {
1572       total += key_val.second.size();
1573     }
1574   }
1575   return total;
1576 }
1577 
DeleteAllInList(const std::list<CookieOrigin> & cookies)1578 void SQLitePersistentCookieStore::Backend::DeleteAllInList(
1579     const std::list<CookieOrigin>& cookies) {
1580   if (cookies.empty())
1581     return;
1582 
1583   if (background_task_runner()->RunsTasksInCurrentSequence()) {
1584     BackgroundDeleteAllInList(cookies);
1585   } else {
1586     // Perform deletion on background task runner.
1587     PostBackgroundTask(
1588         FROM_HERE,
1589         base::BindOnce(&Backend::BackgroundDeleteAllInList, this, cookies));
1590   }
1591 }
1592 
DeleteSessionCookiesOnStartup()1593 void SQLitePersistentCookieStore::Backend::DeleteSessionCookiesOnStartup() {
1594   DCHECK(background_task_runner()->RunsTasksInCurrentSequence());
1595   if (!db()->Execute("DELETE FROM cookies WHERE is_persistent != 1"))
1596     LOG(WARNING) << "Unable to delete session cookies.";
1597 }
1598 
1599 // TODO(crbug.com/1225444) Investigate including top_frame_site_key in the WHERE
1600 // clause.
BackgroundDeleteAllInList(const std::list<CookieOrigin> & cookies)1601 void SQLitePersistentCookieStore::Backend::BackgroundDeleteAllInList(
1602     const std::list<CookieOrigin>& cookies) {
1603   DCHECK(background_task_runner()->RunsTasksInCurrentSequence());
1604 
1605   if (!db())
1606     return;
1607 
1608   // Force a commit of any pending writes before issuing deletes.
1609   // TODO(rohitrao): Remove the need for this Commit() by instead pruning the
1610   // list of pending operations. https://crbug.com/486742.
1611   Commit();
1612 
1613   sql::Statement delete_statement(db()->GetCachedStatement(
1614       SQL_FROM_HERE, "DELETE FROM cookies WHERE host_key=? AND is_secure=?"));
1615   if (!delete_statement.is_valid()) {
1616     LOG(WARNING) << "Unable to delete cookies on shutdown.";
1617     return;
1618   }
1619 
1620   sql::Transaction transaction(db());
1621   if (!transaction.Begin()) {
1622     LOG(WARNING) << "Unable to delete cookies on shutdown.";
1623     return;
1624   }
1625 
1626   for (const auto& cookie : cookies) {
1627     const GURL url(cookie_util::CookieOriginToURL(cookie.first, cookie.second));
1628     if (!url.is_valid())
1629       continue;
1630 
1631     delete_statement.Reset(true);
1632     delete_statement.BindString(0, cookie.first);
1633     delete_statement.BindInt(1, cookie.second);
1634     if (!delete_statement.Run()) {
1635       LOG(WARNING) << "Could not delete a cookie from the DB.";
1636     }
1637   }
1638 
1639   if (!transaction.Commit())
1640     LOG(WARNING) << "Unable to delete cookies on shutdown.";
1641 }
1642 
FinishedLoadingCookies(LoadedCallback loaded_callback,bool success)1643 void SQLitePersistentCookieStore::Backend::FinishedLoadingCookies(
1644     LoadedCallback loaded_callback,
1645     bool success) {
1646   PostClientTask(FROM_HERE,
1647                  base::BindOnce(&Backend::NotifyLoadCompleteInForeground, this,
1648                                 std::move(loaded_callback), success));
1649 }
1650 
SQLitePersistentCookieStore(const base::FilePath & path,const scoped_refptr<base::SequencedTaskRunner> & client_task_runner,const scoped_refptr<base::SequencedTaskRunner> & background_task_runner,bool restore_old_session_cookies,std::unique_ptr<CookieCryptoDelegate> crypto_delegate,bool enable_exclusive_access)1651 SQLitePersistentCookieStore::SQLitePersistentCookieStore(
1652     const base::FilePath& path,
1653     const scoped_refptr<base::SequencedTaskRunner>& client_task_runner,
1654     const scoped_refptr<base::SequencedTaskRunner>& background_task_runner,
1655     bool restore_old_session_cookies,
1656     std::unique_ptr<CookieCryptoDelegate> crypto_delegate,
1657     bool enable_exclusive_access)
1658     : backend_(base::MakeRefCounted<Backend>(path,
1659                                              client_task_runner,
1660                                              background_task_runner,
1661                                              restore_old_session_cookies,
1662                                              std::move(crypto_delegate),
1663                                              enable_exclusive_access)) {}
1664 
DeleteAllInList(const std::list<CookieOrigin> & cookies)1665 void SQLitePersistentCookieStore::DeleteAllInList(
1666     const std::list<CookieOrigin>& cookies) {
1667   backend_->DeleteAllInList(cookies);
1668 }
1669 
Load(LoadedCallback loaded_callback,const NetLogWithSource & net_log)1670 void SQLitePersistentCookieStore::Load(LoadedCallback loaded_callback,
1671                                        const NetLogWithSource& net_log) {
1672   DCHECK(!loaded_callback.is_null());
1673   net_log_ = net_log;
1674   net_log_.BeginEvent(NetLogEventType::COOKIE_PERSISTENT_STORE_LOAD);
1675   // Note that |backend_| keeps |this| alive by keeping a reference count.
1676   // If this class is ever converted over to a WeakPtr<> pattern (as TODO it
1677   // should be) this will need to be replaced by a more complex pattern that
1678   // guarantees |loaded_callback| being called even if the class has been
1679   // destroyed. |backend_| needs to outlive |this| to commit changes to disk.
1680   backend_->Load(base::BindOnce(&SQLitePersistentCookieStore::CompleteLoad,
1681                                 this, std::move(loaded_callback)));
1682 }
1683 
LoadCookiesForKey(const std::string & key,LoadedCallback loaded_callback)1684 void SQLitePersistentCookieStore::LoadCookiesForKey(
1685     const std::string& key,
1686     LoadedCallback loaded_callback) {
1687   DCHECK(!loaded_callback.is_null());
1688   net_log_.AddEvent(NetLogEventType::COOKIE_PERSISTENT_STORE_KEY_LOAD_STARTED,
1689                     [&](NetLogCaptureMode capture_mode) {
1690                       return CookieKeyedLoadNetLogParams(key, capture_mode);
1691                     });
1692   // Note that |backend_| keeps |this| alive by keeping a reference count.
1693   // If this class is ever converted over to a WeakPtr<> pattern (as TODO it
1694   // should be) this will need to be replaced by a more complex pattern that
1695   // guarantees |loaded_callback| being called even if the class has been
1696   // destroyed. |backend_| needs to outlive |this| to commit changes to disk.
1697   backend_->LoadCookiesForKey(
1698       key, base::BindOnce(&SQLitePersistentCookieStore::CompleteKeyedLoad, this,
1699                           key, std::move(loaded_callback)));
1700 }
1701 
AddCookie(const CanonicalCookie & cc)1702 void SQLitePersistentCookieStore::AddCookie(const CanonicalCookie& cc) {
1703   backend_->AddCookie(cc);
1704 }
1705 
UpdateCookieAccessTime(const CanonicalCookie & cc)1706 void SQLitePersistentCookieStore::UpdateCookieAccessTime(
1707     const CanonicalCookie& cc) {
1708   backend_->UpdateCookieAccessTime(cc);
1709 }
1710 
DeleteCookie(const CanonicalCookie & cc)1711 void SQLitePersistentCookieStore::DeleteCookie(const CanonicalCookie& cc) {
1712   backend_->DeleteCookie(cc);
1713 }
1714 
SetForceKeepSessionState()1715 void SQLitePersistentCookieStore::SetForceKeepSessionState() {
1716   // This store never discards session-only cookies, so this call has no effect.
1717 }
1718 
SetBeforeCommitCallback(base::RepeatingClosure callback)1719 void SQLitePersistentCookieStore::SetBeforeCommitCallback(
1720     base::RepeatingClosure callback) {
1721   backend_->SetBeforeCommitCallback(std::move(callback));
1722 }
1723 
Flush(base::OnceClosure callback)1724 void SQLitePersistentCookieStore::Flush(base::OnceClosure callback) {
1725   backend_->Flush(std::move(callback));
1726 }
1727 
GetQueueLengthForTesting()1728 size_t SQLitePersistentCookieStore::GetQueueLengthForTesting() {
1729   return backend_->GetQueueLengthForTesting();
1730 }
1731 
~SQLitePersistentCookieStore()1732 SQLitePersistentCookieStore::~SQLitePersistentCookieStore() {
1733   net_log_.AddEventWithStringParams(
1734       NetLogEventType::COOKIE_PERSISTENT_STORE_CLOSED, "type",
1735       "SQLitePersistentCookieStore");
1736   backend_->Close();
1737 }
1738 
CompleteLoad(LoadedCallback callback,std::vector<std::unique_ptr<CanonicalCookie>> cookie_list)1739 void SQLitePersistentCookieStore::CompleteLoad(
1740     LoadedCallback callback,
1741     std::vector<std::unique_ptr<CanonicalCookie>> cookie_list) {
1742   net_log_.EndEvent(NetLogEventType::COOKIE_PERSISTENT_STORE_LOAD);
1743   std::move(callback).Run(std::move(cookie_list));
1744 }
1745 
CompleteKeyedLoad(const std::string & key,LoadedCallback callback,std::vector<std::unique_ptr<CanonicalCookie>> cookie_list)1746 void SQLitePersistentCookieStore::CompleteKeyedLoad(
1747     const std::string& key,
1748     LoadedCallback callback,
1749     std::vector<std::unique_ptr<CanonicalCookie>> cookie_list) {
1750   net_log_.AddEventWithStringParams(
1751       NetLogEventType::COOKIE_PERSISTENT_STORE_KEY_LOAD_COMPLETED, "domain",
1752       key);
1753   std::move(callback).Run(std::move(cookie_list));
1754 }
1755 
1756 }  // namespace net
1757