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