• 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 <stdint.h>
8 
9 #include <map>
10 #include <memory>
11 #include <set>
12 #include <utility>
13 
14 #include "base/containers/span.h"
15 #include "base/files/file.h"
16 #include "base/files/file_util.h"
17 #include "base/files/scoped_temp_dir.h"
18 #include "base/functional/bind.h"
19 #include "base/functional/callback.h"
20 #include "base/location.h"
21 #include "base/memory/ref_counted.h"
22 #include "base/run_loop.h"
23 #include "base/strings/stringprintf.h"
24 #include "base/synchronization/waitable_event.h"
25 #include "base/task/sequenced_task_runner.h"
26 #include "base/task/single_thread_task_runner.h"
27 #include "base/task/thread_pool.h"
28 #include "base/test/bind.h"
29 #include "base/test/scoped_feature_list.h"
30 #include "base/threading/thread_restrictions.h"
31 #include "base/time/time.h"
32 #include "crypto/encryptor.h"
33 #include "crypto/symmetric_key.h"
34 #include "net/base/features.h"
35 #include "net/base/test_completion_callback.h"
36 #include "net/cookies/canonical_cookie.h"
37 #include "net/cookies/cookie_constants.h"
38 #include "net/cookies/cookie_inclusion_status.h"
39 #include "net/cookies/cookie_store_test_callbacks.h"
40 #include "net/extras/sqlite/cookie_crypto_delegate.h"
41 #include "net/log/net_log_capture_mode.h"
42 #include "net/log/test_net_log.h"
43 #include "net/log/test_net_log_util.h"
44 #include "net/test/test_with_task_environment.h"
45 #include "sql/database.h"
46 #include "sql/meta_table.h"
47 #include "sql/statement.h"
48 #include "sql/transaction.h"
49 #include "testing/gtest/include/gtest/gtest.h"
50 #include "third_party/abseil-cpp/absl/types/optional.h"
51 #include "url/gurl.h"
52 #include "url/third_party/mozilla/url_parse.h"
53 
54 namespace net {
55 
56 namespace {
57 
58 const base::FilePath::CharType kCookieFilename[] = FILE_PATH_LITERAL("Cookies");
59 
60 class CookieCryptor : public CookieCryptoDelegate {
61  public:
62   CookieCryptor();
63   bool ShouldEncrypt() override;
64   bool EncryptString(const std::string& plaintext,
65                      std::string* ciphertext) override;
66   bool DecryptString(const std::string& ciphertext,
67                      std::string* plaintext) override;
68 
69   bool should_encrypt_ = true;
70 
71  private:
72   std::unique_ptr<crypto::SymmetricKey> key_;
73   crypto::Encryptor encryptor_;
74 };
75 
CookieCryptor()76 CookieCryptor::CookieCryptor()
77     : key_(crypto::SymmetricKey::DeriveKeyFromPasswordUsingPbkdf2(
78           crypto::SymmetricKey::AES,
79           "password",
80           "saltiest",
81           1000,
82           256)) {
83   std::string iv("the iv: 16 bytes");
84   encryptor_.Init(key_.get(), crypto::Encryptor::CBC, iv);
85 }
86 
ShouldEncrypt()87 bool CookieCryptor::ShouldEncrypt() {
88   return should_encrypt_;
89 }
90 
EncryptString(const std::string & plaintext,std::string * ciphertext)91 bool CookieCryptor::EncryptString(const std::string& plaintext,
92                                   std::string* ciphertext) {
93   return encryptor_.Encrypt(plaintext, ciphertext);
94 }
95 
DecryptString(const std::string & ciphertext,std::string * plaintext)96 bool CookieCryptor::DecryptString(const std::string& ciphertext,
97                                   std::string* plaintext) {
98   return encryptor_.Decrypt(ciphertext, plaintext);
99 }
100 
101 }  // namespace
102 
103 typedef std::vector<std::unique_ptr<CanonicalCookie>> CanonicalCookieVector;
104 
105 class SQLitePersistentCookieStoreTest : public TestWithTaskEnvironment {
106  public:
SQLitePersistentCookieStoreTest()107   SQLitePersistentCookieStoreTest()
108       : loaded_event_(base::WaitableEvent::ResetPolicy::AUTOMATIC,
109                       base::WaitableEvent::InitialState::NOT_SIGNALED),
110         db_thread_event_(base::WaitableEvent::ResetPolicy::AUTOMATIC,
111                          base::WaitableEvent::InitialState::NOT_SIGNALED) {}
112 
OnLoaded(CanonicalCookieVector cookies)113   void OnLoaded(CanonicalCookieVector cookies) {
114     cookies_.swap(cookies);
115     loaded_event_.Signal();
116   }
117 
OnKeyLoaded(base::OnceClosure closure,CanonicalCookieVector cookies)118   void OnKeyLoaded(base::OnceClosure closure, CanonicalCookieVector cookies) {
119     cookies_.swap(cookies);
120     std::move(closure).Run();
121   }
122 
Load(CanonicalCookieVector * cookies)123   void Load(CanonicalCookieVector* cookies) {
124     EXPECT_FALSE(loaded_event_.IsSignaled());
125     store_->Load(base::BindOnce(&SQLitePersistentCookieStoreTest::OnLoaded,
126                                 base::Unretained(this)),
127                  NetLogWithSource::Make(NetLogSourceType::NONE));
128     loaded_event_.Wait();
129     cookies->swap(cookies_);
130   }
131 
Flush()132   void Flush() {
133     base::WaitableEvent event(base::WaitableEvent::ResetPolicy::AUTOMATIC,
134                               base::WaitableEvent::InitialState::NOT_SIGNALED);
135     store_->Flush(
136         base::BindOnce(&base::WaitableEvent::Signal, base::Unretained(&event)));
137     event.Wait();
138   }
139 
DestroyStore()140   void DestroyStore() {
141     store_ = nullptr;
142     // Make sure we wait until the destructor has run by running all
143     // TaskEnvironment tasks.
144     RunUntilIdle();
145   }
146 
Create(bool crypt_cookies,bool restore_old_session_cookies,bool use_current_thread,bool enable_exclusive_access)147   void Create(bool crypt_cookies,
148               bool restore_old_session_cookies,
149               bool use_current_thread,
150               bool enable_exclusive_access) {
151     if (crypt_cookies)
152       cookie_crypto_delegate_ = std::make_unique<CookieCryptor>();
153 
154     store_ = base::MakeRefCounted<SQLitePersistentCookieStore>(
155         temp_dir_.GetPath().Append(kCookieFilename),
156         use_current_thread ? base::SingleThreadTaskRunner::GetCurrentDefault()
157                            : client_task_runner_,
158         background_task_runner_, restore_old_session_cookies,
159         cookie_crypto_delegate_.get(), enable_exclusive_access);
160   }
161 
CreateAndLoad(bool crypt_cookies,bool restore_old_session_cookies,CanonicalCookieVector * cookies)162   void CreateAndLoad(bool crypt_cookies,
163                      bool restore_old_session_cookies,
164                      CanonicalCookieVector* cookies) {
165     Create(crypt_cookies, restore_old_session_cookies,
166            false /* use_current_thread */, /*enable_exclusive_access=*/false);
167     Load(cookies);
168   }
169 
InitializeStore(bool crypt,bool restore_old_session_cookies)170   void InitializeStore(bool crypt, bool restore_old_session_cookies) {
171     CanonicalCookieVector cookies;
172     CreateAndLoad(crypt, restore_old_session_cookies, &cookies);
173     EXPECT_EQ(0U, cookies.size());
174   }
175 
WaitOnDBEvent()176   void WaitOnDBEvent() {
177     base::ScopedAllowBaseSyncPrimitivesForTesting allow_base_sync_primitives;
178     db_thread_event_.Wait();
179   }
180 
181   // Adds a persistent cookie to store_.
AddCookie(const std::string & name,const std::string & value,const std::string & domain,const std::string & path,const base::Time & creation)182   void AddCookie(const std::string& name,
183                  const std::string& value,
184                  const std::string& domain,
185                  const std::string& path,
186                  const base::Time& creation) {
187     store_->AddCookie(*CanonicalCookie::CreateUnsafeCookieForTesting(
188         name, value, domain, path, creation, creation, base::Time(),
189         base::Time(), false, false, CookieSameSite::NO_RESTRICTION,
190         COOKIE_PRIORITY_DEFAULT, false));
191   }
192 
AddCookieWithExpiration(const std::string & name,const std::string & value,const std::string & domain,const std::string & path,const base::Time & creation,const base::Time & expiration)193   void AddCookieWithExpiration(const std::string& name,
194                                const std::string& value,
195                                const std::string& domain,
196                                const std::string& path,
197                                const base::Time& creation,
198                                const base::Time& expiration) {
199     store_->AddCookie(*CanonicalCookie::CreateUnsafeCookieForTesting(
200         name, value, domain, path, creation, expiration, base::Time(),
201         base::Time(), false, false, CookieSameSite::NO_RESTRICTION,
202         COOKIE_PRIORITY_DEFAULT, false));
203   }
204 
ReadRawDBContents()205   std::string ReadRawDBContents() {
206     std::string contents;
207     if (!base::ReadFileToString(temp_dir_.GetPath().Append(kCookieFilename),
208                                 &contents))
209       return std::string();
210     return contents;
211   }
212 
SetUp()213   void SetUp() override { ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); }
214 
TearDown()215   void TearDown() override {
216     DestroyStore();
217   }
218 
219  protected:
220   const scoped_refptr<base::SequencedTaskRunner> background_task_runner_ =
221       base::ThreadPool::CreateSequencedTaskRunner({base::MayBlock()});
222   const scoped_refptr<base::SequencedTaskRunner> client_task_runner_ =
223       base::ThreadPool::CreateSequencedTaskRunner({base::MayBlock()});
224   base::WaitableEvent loaded_event_;
225   base::WaitableEvent db_thread_event_;
226   CanonicalCookieVector cookies_;
227   base::ScopedTempDir temp_dir_;
228   scoped_refptr<SQLitePersistentCookieStore> store_;
229   std::unique_ptr<CookieCryptor> cookie_crypto_delegate_;
230 };
231 
TEST_F(SQLitePersistentCookieStoreTest,TestInvalidMetaTableRecovery)232 TEST_F(SQLitePersistentCookieStoreTest, TestInvalidMetaTableRecovery) {
233   InitializeStore(false, false);
234   AddCookie("A", "B", "foo.bar", "/", base::Time::Now());
235   DestroyStore();
236 
237   // Load up the store and verify that it has good data in it.
238   CanonicalCookieVector cookies;
239   CreateAndLoad(false, false, &cookies);
240   ASSERT_EQ(1U, cookies.size());
241   ASSERT_STREQ("foo.bar", cookies[0]->Domain().c_str());
242   ASSERT_STREQ("A", cookies[0]->Name().c_str());
243   ASSERT_STREQ("B", cookies[0]->Value().c_str());
244   DestroyStore();
245   cookies.clear();
246 
247   // Now corrupt the meta table.
248   {
249     sql::Database db;
250     ASSERT_TRUE(db.Open(temp_dir_.GetPath().Append(kCookieFilename)));
251     sql::MetaTable meta_table_;
252     ASSERT_TRUE(meta_table_.Init(&db, 1, 1));
253     ASSERT_TRUE(db.Execute("DELETE FROM meta"));
254     db.Close();
255   }
256 
257   // Upon loading, the database should be reset to a good, blank state.
258   CreateAndLoad(false, false, &cookies);
259   ASSERT_EQ(0U, cookies.size());
260 
261   // Verify that, after, recovery, the database persists properly.
262   AddCookie("X", "Y", "foo.bar", "/", base::Time::Now());
263   DestroyStore();
264   CreateAndLoad(false, false, &cookies);
265   ASSERT_EQ(1U, cookies.size());
266   ASSERT_STREQ("foo.bar", cookies[0]->Domain().c_str());
267   ASSERT_STREQ("X", cookies[0]->Name().c_str());
268   ASSERT_STREQ("Y", cookies[0]->Value().c_str());
269   cookies.clear();
270 }
271 
272 // Test if data is stored as expected in the SQLite database.
TEST_F(SQLitePersistentCookieStoreTest,TestPersistance)273 TEST_F(SQLitePersistentCookieStoreTest, TestPersistance) {
274   InitializeStore(false, false);
275   AddCookie("A", "B", "foo.bar", "/", base::Time::Now());
276   // Replace the store effectively destroying the current one and forcing it
277   // to write its data to disk. Then we can see if after loading it again it
278   // is still there.
279   DestroyStore();
280   // Reload and test for persistence
281   CanonicalCookieVector cookies;
282   CreateAndLoad(false, false, &cookies);
283   ASSERT_EQ(1U, cookies.size());
284   ASSERT_STREQ("foo.bar", cookies[0]->Domain().c_str());
285   ASSERT_STREQ("A", cookies[0]->Name().c_str());
286   ASSERT_STREQ("B", cookies[0]->Value().c_str());
287 
288   // Now delete the cookie and check persistence again.
289   store_->DeleteCookie(*cookies[0]);
290   DestroyStore();
291   cookies.clear();
292 
293   // Reload and check if the cookie has been removed.
294   CreateAndLoad(false, false, &cookies);
295   ASSERT_EQ(0U, cookies.size());
296 }
297 
TEST_F(SQLitePersistentCookieStoreTest,TestSessionCookiesDeletedOnStartup)298 TEST_F(SQLitePersistentCookieStoreTest, TestSessionCookiesDeletedOnStartup) {
299   // Initialize the cookie store with 3 persistent cookies, 5 transient
300   // cookies.
301   InitializeStore(false, false);
302 
303   // Add persistent cookies.
304   base::Time t = base::Time::Now();
305   AddCookie("A", "B", "a1.com", "/", t);
306   t += base::Microseconds(10);
307   AddCookie("A", "B", "a2.com", "/", t);
308   t += base::Microseconds(10);
309   AddCookie("A", "B", "a3.com", "/", t);
310 
311   // Add transient cookies.
312   t += base::Microseconds(10);
313   AddCookieWithExpiration("A", "B", "b1.com", "/", t, base::Time());
314   t += base::Microseconds(10);
315   AddCookieWithExpiration("A", "B", "b2.com", "/", t, base::Time());
316   t += base::Microseconds(10);
317   AddCookieWithExpiration("A", "B", "b3.com", "/", t, base::Time());
318   t += base::Microseconds(10);
319   AddCookieWithExpiration("A", "B", "b4.com", "/", t, base::Time());
320   t += base::Microseconds(10);
321   AddCookieWithExpiration("A", "B", "b5.com", "/", t, base::Time());
322   DestroyStore();
323 
324   // Load the store a second time. Before the store finishes loading, add a
325   // transient cookie and flush it to disk.
326   store_ = base::MakeRefCounted<SQLitePersistentCookieStore>(
327       temp_dir_.GetPath().Append(kCookieFilename), client_task_runner_,
328       background_task_runner_, false, nullptr, false);
329 
330   // Posting a blocking task to db_thread_ makes sure that the DB thread waits
331   // until both Load and Flush have been posted to its task queue.
332   background_task_runner_->PostTask(
333       FROM_HERE, base::BindOnce(&SQLitePersistentCookieStoreTest::WaitOnDBEvent,
334                                 base::Unretained(this)));
335   store_->Load(base::BindOnce(&SQLitePersistentCookieStoreTest::OnLoaded,
336                               base::Unretained(this)),
337                NetLogWithSource());
338   t += base::Microseconds(10);
339   AddCookieWithExpiration("A", "B", "c.com", "/", t, base::Time());
340   base::WaitableEvent event(base::WaitableEvent::ResetPolicy::AUTOMATIC,
341                             base::WaitableEvent::InitialState::NOT_SIGNALED);
342   store_->Flush(
343       base::BindOnce(&base::WaitableEvent::Signal, base::Unretained(&event)));
344 
345   // Now the DB-thread queue contains:
346   // (active:)
347   // 1. Wait (on db_event)
348   // (pending:)
349   // 2. "Init And Chain-Load First Domain"
350   // 3. Add Cookie (c.com)
351   // 4. Flush Cookie (c.com)
352   db_thread_event_.Signal();
353   event.Wait();
354   loaded_event_.Wait();
355   cookies_.clear();
356   DestroyStore();
357 
358   // Load the store a third time, this time restoring session cookies. The
359   // store should contain exactly 4 cookies: the 3 persistent, and "c.com",
360   // which was added during the second cookie store load.
361   store_ = base::MakeRefCounted<SQLitePersistentCookieStore>(
362       temp_dir_.GetPath().Append(kCookieFilename), client_task_runner_,
363       background_task_runner_, true, nullptr, false);
364   store_->Load(base::BindOnce(&SQLitePersistentCookieStoreTest::OnLoaded,
365                               base::Unretained(this)),
366                NetLogWithSource());
367   loaded_event_.Wait();
368   ASSERT_EQ(4u, cookies_.size());
369   cookies_.clear();
370 }
371 
372 // Test that priority load of cookies for a specfic domain key could be
373 // completed before the entire store is loaded
TEST_F(SQLitePersistentCookieStoreTest,TestLoadCookiesForKey)374 TEST_F(SQLitePersistentCookieStoreTest, TestLoadCookiesForKey) {
375   InitializeStore(false, false);
376   base::Time t = base::Time::Now();
377   AddCookie("A", "B", "foo.bar", "/", t);
378   t += base::Microseconds(10);
379   AddCookie("A", "B", "www.aaa.com", "/", t);
380   t += base::Microseconds(10);
381   AddCookie("A", "B", "travel.aaa.com", "/", t);
382   t += base::Microseconds(10);
383   AddCookie("A", "B", "www.bbb.com", "/", t);
384   DestroyStore();
385 
386   // base::test::TaskEnvironment runs |background_task_runner_| and
387   // |client_task_runner_| on the same thread. Therefore, when a
388   // |background_task_runner_| task is blocked, |client_task_runner_| tasks
389   // can't run. To allow precise control of |background_task_runner_| without
390   // preventing client tasks to run, use
391   // base::SingleThreadTaskRunner::GetCurrentDefault() instead of
392   // |client_task_runner_| for this test.
393   Create(false /* crypt_cookies */, false /* restore_old_session_cookies */,
394          true /* use_current_thread */, false /* enable_exclusive_access */);
395 
396   // Posting a blocking task to db_thread_ makes sure that the DB thread waits
397   // until both Load and LoadCookiesForKey have been posted to its task queue.
398   background_task_runner_->PostTask(
399       FROM_HERE, base::BindOnce(&SQLitePersistentCookieStoreTest::WaitOnDBEvent,
400                                 base::Unretained(this)));
401   RecordingNetLogObserver net_log_observer;
402   store_->Load(base::BindOnce(&SQLitePersistentCookieStoreTest::OnLoaded,
403                               base::Unretained(this)),
404                NetLogWithSource::Make(NetLogSourceType::NONE));
405   base::RunLoop run_loop;
406   net_log_observer.SetObserverCaptureMode(NetLogCaptureMode::kDefault);
407   store_->LoadCookiesForKey(
408       "aaa.com",
409       base::BindOnce(&SQLitePersistentCookieStoreTest::OnKeyLoaded,
410                      base::Unretained(this), run_loop.QuitClosure()));
411   background_task_runner_->PostTask(
412       FROM_HERE, base::BindOnce(&SQLitePersistentCookieStoreTest::WaitOnDBEvent,
413                                 base::Unretained(this)));
414 
415   // Now the DB-thread queue contains:
416   // (active:)
417   // 1. Wait (on db_event)
418   // (pending:)
419   // 2. "Init And Chain-Load First Domain"
420   // 3. Priority Load (aaa.com)
421   // 4. Wait (on db_event)
422   db_thread_event_.Signal();
423 
424   // Wait until the OnKeyLoaded callback has run.
425   run_loop.Run();
426   EXPECT_FALSE(loaded_event_.IsSignaled());
427 
428   std::set<std::string> cookies_loaded;
429   for (CanonicalCookieVector::const_iterator it = cookies_.begin();
430        it != cookies_.end(); ++it) {
431     cookies_loaded.insert((*it)->Domain().c_str());
432   }
433   cookies_.clear();
434   ASSERT_GT(4U, cookies_loaded.size());
435   ASSERT_EQ(true, cookies_loaded.find("www.aaa.com") != cookies_loaded.end());
436   ASSERT_EQ(true,
437             cookies_loaded.find("travel.aaa.com") != cookies_loaded.end());
438 
439   db_thread_event_.Signal();
440 
441   RunUntilIdle();
442   EXPECT_TRUE(loaded_event_.IsSignaled());
443 
444   for (CanonicalCookieVector::const_iterator it = cookies_.begin();
445        it != cookies_.end(); ++it) {
446     cookies_loaded.insert((*it)->Domain().c_str());
447   }
448   ASSERT_EQ(4U, cookies_loaded.size());
449   ASSERT_EQ(cookies_loaded.find("foo.bar") != cookies_loaded.end(), true);
450   ASSERT_EQ(cookies_loaded.find("www.bbb.com") != cookies_loaded.end(), true);
451   cookies_.clear();
452 
453   store_ = nullptr;
454   auto entries = net_log_observer.GetEntries();
455   size_t pos = ExpectLogContainsSomewhere(
456       entries, 0, NetLogEventType::COOKIE_PERSISTENT_STORE_LOAD,
457       NetLogEventPhase::BEGIN);
458   pos = ExpectLogContainsSomewhere(
459       entries, pos, NetLogEventType::COOKIE_PERSISTENT_STORE_LOAD,
460       NetLogEventPhase::END);
461   pos = ExpectLogContainsSomewhere(
462       entries, 0, NetLogEventType::COOKIE_PERSISTENT_STORE_LOAD,
463       NetLogEventPhase::BEGIN);
464   pos = ExpectLogContainsSomewhere(
465       entries, pos, NetLogEventType::COOKIE_PERSISTENT_STORE_KEY_LOAD_STARTED,
466       NetLogEventPhase::NONE);
467   EXPECT_FALSE(GetOptionalStringValueFromParams(entries[pos], "key"));
468   pos = ExpectLogContainsSomewhere(
469       entries, pos, NetLogEventType::COOKIE_PERSISTENT_STORE_KEY_LOAD_COMPLETED,
470       NetLogEventPhase::NONE);
471   pos = ExpectLogContainsSomewhere(
472       entries, pos, NetLogEventType::COOKIE_PERSISTENT_STORE_LOAD,
473       NetLogEventPhase::END);
474   ExpectLogContainsSomewhere(entries, pos,
475                              NetLogEventType::COOKIE_PERSISTENT_STORE_CLOSED,
476                              NetLogEventPhase::NONE);
477 }
478 
TEST_F(SQLitePersistentCookieStoreTest,TestBeforeCommitCallback)479 TEST_F(SQLitePersistentCookieStoreTest, TestBeforeCommitCallback) {
480   InitializeStore(false, false);
481 
482   struct Counter {
483     int count = 0;
484     void increment() { count++; }
485   };
486 
487   Counter counter;
488   store_->SetBeforeCommitCallback(
489       base::BindRepeating(&Counter::increment, base::Unretained(&counter)));
490 
491   // The implementation of SQLitePersistentCookieStore::Backend flushes changes
492   // after 30s or 512 pending operations. Add 512 cookies to the store to test
493   // that the callback gets called when SQLitePersistentCookieStore internally
494   // flushes its store.
495   for (int i = 0; i < 512; i++) {
496     // Each cookie needs a unique timestamp for creation_utc (see DB schema).
497     base::Time t = base::Time::Now() + base::Microseconds(i);
498     AddCookie(base::StringPrintf("%d", i), "foo", "example.com", "/", t);
499   }
500 
501   RunUntilIdle();
502   EXPECT_GT(counter.count, 0);
503 
504   DestroyStore();
505 }
506 
507 // Test that we can force the database to be written by calling Flush().
TEST_F(SQLitePersistentCookieStoreTest,TestFlush)508 TEST_F(SQLitePersistentCookieStoreTest, TestFlush) {
509   InitializeStore(false, false);
510   // File timestamps don't work well on all platforms, so we'll determine
511   // whether the DB file has been modified by checking its size.
512   base::FilePath path = temp_dir_.GetPath().Append(kCookieFilename);
513   base::File::Info info;
514   ASSERT_TRUE(base::GetFileInfo(path, &info));
515   int64_t base_size = info.size;
516 
517   // Write some large cookies, so the DB will have to expand by several KB.
518   for (char c = 'a'; c < 'z'; ++c) {
519     // Each cookie needs a unique timestamp for creation_utc (see DB schema).
520     base::Time t = base::Time::Now() + base::Microseconds(c);
521     std::string name(1, c);
522     std::string value(1000, c);
523     AddCookie(name, value, "foo.bar", "/", t);
524   }
525 
526   Flush();
527 
528   // We forced a write, so now the file will be bigger.
529   ASSERT_TRUE(base::GetFileInfo(path, &info));
530   ASSERT_GT(info.size, base_size);
531 }
532 
533 // Test loading old session cookies from the disk.
TEST_F(SQLitePersistentCookieStoreTest,TestLoadOldSessionCookies)534 TEST_F(SQLitePersistentCookieStoreTest, TestLoadOldSessionCookies) {
535   InitializeStore(false, true);
536 
537   // Add a session cookie.
538   store_->AddCookie(*CanonicalCookie::CreateUnsafeCookieForTesting(
539       "C", "D", "sessioncookie.com", "/", base::Time::Now(), base::Time(),
540       base::Time(), base::Time(), false, false, CookieSameSite::NO_RESTRICTION,
541       COOKIE_PRIORITY_DEFAULT, false));
542 
543   // Force the store to write its data to the disk.
544   DestroyStore();
545 
546   // Create a store that loads session cookies and test that the session cookie
547   // was loaded.
548   CanonicalCookieVector cookies;
549   CreateAndLoad(false, true, &cookies);
550 
551   ASSERT_EQ(1U, cookies.size());
552   ASSERT_STREQ("sessioncookie.com", cookies[0]->Domain().c_str());
553   ASSERT_STREQ("C", cookies[0]->Name().c_str());
554   ASSERT_STREQ("D", cookies[0]->Value().c_str());
555   ASSERT_EQ(COOKIE_PRIORITY_DEFAULT, cookies[0]->Priority());
556 
557   cookies.clear();
558 }
559 
560 // Test refusing to load old session cookies from the disk.
TEST_F(SQLitePersistentCookieStoreTest,TestDontLoadOldSessionCookies)561 TEST_F(SQLitePersistentCookieStoreTest, TestDontLoadOldSessionCookies) {
562   InitializeStore(false, true);
563 
564   // Add a session cookie.
565   store_->AddCookie(*CanonicalCookie::CreateUnsafeCookieForTesting(
566       "C", "D", "sessioncookie.com", "/", base::Time::Now(), base::Time(),
567       base::Time(), base::Time(), false, false, CookieSameSite::NO_RESTRICTION,
568       COOKIE_PRIORITY_DEFAULT, false));
569 
570   // Force the store to write its data to the disk.
571   DestroyStore();
572 
573   // Create a store that doesn't load old session cookies and test that the
574   // session cookie was not loaded.
575   CanonicalCookieVector cookies;
576   CreateAndLoad(false, false, &cookies);
577   ASSERT_EQ(0U, cookies.size());
578 
579   // The store should also delete the session cookie. Wait until that has been
580   // done.
581   DestroyStore();
582 
583   // Create a store that loads old session cookies and test that the session
584   // cookie is gone.
585   CreateAndLoad(false, true, &cookies);
586   ASSERT_EQ(0U, cookies.size());
587 }
588 
589 // Confirm bad cookies on disk don't get looaded, and that we also remove them
590 // from the database.
TEST_F(SQLitePersistentCookieStoreTest,FilterBadCookiesAndFixupDb)591 TEST_F(SQLitePersistentCookieStoreTest, FilterBadCookiesAndFixupDb) {
592   // Create an on-disk store.
593   InitializeStore(false, true);
594   DestroyStore();
595 
596   // Add some cookies in by hand.
597   base::FilePath store_name(temp_dir_.GetPath().Append(kCookieFilename));
598   std::unique_ptr<sql::Database> db(std::make_unique<sql::Database>());
599   ASSERT_TRUE(db->Open(store_name));
600   sql::Statement stmt(db->GetUniqueStatement(
601       "INSERT INTO cookies (creation_utc, host_key, top_frame_site_key, name, "
602       "value, encrypted_value, path, expires_utc, is_secure, is_httponly, "
603       "samesite, last_access_utc, has_expires, is_persistent, priority, "
604       "source_scheme, source_port, is_same_party, last_update_utc) "
605       "VALUES (?,?,?,?,?,'',?,0,0,0,0,0,1,1,0,?,?,0,?)"));
606   ASSERT_TRUE(stmt.is_valid());
607 
608   struct CookieInfo {
609     const char* domain;
610     const char* name;
611     const char* value;
612     const char* path;
613   } cookies_info[] = {// A couple non-canonical cookies.
614                       {"google.izzle", "A=", "B", "/path"},
615                       {"google.izzle", "C ", "D", "/path"},
616 
617                       // A canonical cookie for same eTLD+1. This one will get
618                       // dropped out of precaution to avoid confusing the site,
619                       // even though there is nothing wrong with it.
620                       {"sub.google.izzle", "E", "F", "/path"},
621 
622                       // A canonical cookie for another eTLD+1
623                       {"chromium.org", "G", "H", "/dir"}};
624 
625   int64_t creation_time = 1;
626   base::Time last_update(base::Time::Now());
627   for (auto& cookie_info : cookies_info) {
628     stmt.Reset(true);
629 
630     stmt.BindInt64(0, creation_time++);
631     stmt.BindString(1, cookie_info.domain);
632     // TODO(crbug.com/1225444) Test some non-empty values when CanonicalCookie
633     // supports partition key.
634     stmt.BindString(2, net::kEmptyCookiePartitionKey);
635     stmt.BindString(3, cookie_info.name);
636     stmt.BindString(4, cookie_info.value);
637     stmt.BindString(5, cookie_info.path);
638     stmt.BindInt(6, static_cast<int>(CookieSourceScheme::kUnset));
639     stmt.BindInt(7, SQLitePersistentCookieStore::kDefaultUnknownPort);
640     stmt.BindTime(8, last_update);
641     ASSERT_TRUE(stmt.Run());
642   }
643   stmt.Clear();
644   db.reset();
645 
646   // Reopen the store and confirm that the only cookie loaded is the
647   // canonical one on an unrelated domain.
648   CanonicalCookieVector cookies;
649   CreateAndLoad(false, false, &cookies);
650   ASSERT_EQ(1U, cookies.size());
651   EXPECT_STREQ("chromium.org", cookies[0]->Domain().c_str());
652   EXPECT_STREQ("G", cookies[0]->Name().c_str());
653   EXPECT_STREQ("H", cookies[0]->Value().c_str());
654   EXPECT_STREQ("/dir", cookies[0]->Path().c_str());
655   EXPECT_EQ(last_update, cookies[0]->LastUpdateDate());
656   DestroyStore();
657 
658   // Make sure that we only have one row left.
659   db = std::make_unique<sql::Database>();
660   ASSERT_TRUE(db->Open(store_name));
661   sql::Statement verify_stmt(db->GetUniqueStatement("SELECT * FROM COOKIES"));
662   ASSERT_TRUE(verify_stmt.is_valid());
663   int found = 0;
664   while (verify_stmt.Step()) {
665     ++found;
666   }
667   EXPECT_TRUE(verify_stmt.Succeeded());
668   EXPECT_EQ(1, found);
669 }
670 
TEST_F(SQLitePersistentCookieStoreTest,PersistIsPersistent)671 TEST_F(SQLitePersistentCookieStoreTest, PersistIsPersistent) {
672   InitializeStore(false, true);
673   static const char kSessionName[] = "session";
674   static const char kPersistentName[] = "persistent";
675 
676   // Add a session cookie.
677   store_->AddCookie(*CanonicalCookie::CreateUnsafeCookieForTesting(
678       kSessionName, "val", "sessioncookie.com", "/", base::Time::Now(),
679       base::Time(), base::Time(), base::Time(), false, false,
680       CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_DEFAULT, false));
681   // Add a persistent cookie.
682   store_->AddCookie(*CanonicalCookie::CreateUnsafeCookieForTesting(
683       kPersistentName, "val", "sessioncookie.com", "/",
684       base::Time::Now() - base::Days(1), base::Time::Now() + base::Days(1),
685       base::Time(), base::Time(), false, false, CookieSameSite::NO_RESTRICTION,
686       COOKIE_PRIORITY_DEFAULT, false));
687 
688   // Force the store to write its data to the disk.
689   DestroyStore();
690 
691   // Create a store that loads session cookie and test that the IsPersistent
692   // attribute is restored.
693   CanonicalCookieVector cookies;
694   CreateAndLoad(false, true, &cookies);
695   ASSERT_EQ(2U, cookies.size());
696 
697   std::map<std::string, CanonicalCookie*> cookie_map;
698   for (const auto& cookie : cookies)
699     cookie_map[cookie->Name()] = cookie.get();
700 
701   auto it = cookie_map.find(kSessionName);
702   ASSERT_TRUE(it != cookie_map.end());
703   EXPECT_FALSE(cookie_map[kSessionName]->IsPersistent());
704 
705   it = cookie_map.find(kPersistentName);
706   ASSERT_TRUE(it != cookie_map.end());
707   EXPECT_TRUE(cookie_map[kPersistentName]->IsPersistent());
708 
709   cookies.clear();
710 }
711 
TEST_F(SQLitePersistentCookieStoreTest,PriorityIsPersistent)712 TEST_F(SQLitePersistentCookieStoreTest, PriorityIsPersistent) {
713   static const char kDomain[] = "sessioncookie.com";
714   static const char kLowName[] = "low";
715   static const char kMediumName[] = "medium";
716   static const char kHighName[] = "high";
717   static const char kCookieValue[] = "value";
718   static const char kCookiePath[] = "/";
719 
720   InitializeStore(false, true);
721 
722   // Add a low-priority persistent cookie.
723   store_->AddCookie(*CanonicalCookie::CreateUnsafeCookieForTesting(
724       kLowName, kCookieValue, kDomain, kCookiePath,
725       base::Time::Now() - base::Minutes(1), base::Time::Now() + base::Days(1),
726       base::Time(), base::Time(), false, false, CookieSameSite::NO_RESTRICTION,
727       COOKIE_PRIORITY_LOW, false));
728 
729   // Add a medium-priority persistent cookie.
730   store_->AddCookie(*CanonicalCookie::CreateUnsafeCookieForTesting(
731       kMediumName, kCookieValue, kDomain, kCookiePath,
732       base::Time::Now() - base::Minutes(2), base::Time::Now() + base::Days(1),
733       base::Time(), base::Time(), false, false, CookieSameSite::NO_RESTRICTION,
734       COOKIE_PRIORITY_MEDIUM, false));
735 
736   // Add a high-priority persistent cookie.
737   store_->AddCookie(*CanonicalCookie::CreateUnsafeCookieForTesting(
738       kHighName, kCookieValue, kDomain, kCookiePath,
739       base::Time::Now() - base::Minutes(3), base::Time::Now() + base::Days(1),
740       base::Time(), base::Time(), false, false, CookieSameSite::NO_RESTRICTION,
741       COOKIE_PRIORITY_HIGH, false));
742 
743   // Force the store to write its data to the disk.
744   DestroyStore();
745 
746   // Create a store that loads session cookie and test that the priority
747   // attribute values are restored.
748   CanonicalCookieVector cookies;
749   CreateAndLoad(false, true, &cookies);
750   ASSERT_EQ(3U, cookies.size());
751 
752   // Put the cookies into a map, by name, so we can easily find them.
753   std::map<std::string, CanonicalCookie*> cookie_map;
754   for (const auto& cookie : cookies)
755     cookie_map[cookie->Name()] = cookie.get();
756 
757   // Validate that each cookie has the correct priority.
758   auto it = cookie_map.find(kLowName);
759   ASSERT_TRUE(it != cookie_map.end());
760   EXPECT_EQ(COOKIE_PRIORITY_LOW, cookie_map[kLowName]->Priority());
761 
762   it = cookie_map.find(kMediumName);
763   ASSERT_TRUE(it != cookie_map.end());
764   EXPECT_EQ(COOKIE_PRIORITY_MEDIUM, cookie_map[kMediumName]->Priority());
765 
766   it = cookie_map.find(kHighName);
767   ASSERT_TRUE(it != cookie_map.end());
768   EXPECT_EQ(COOKIE_PRIORITY_HIGH, cookie_map[kHighName]->Priority());
769 
770   cookies.clear();
771 }
772 
TEST_F(SQLitePersistentCookieStoreTest,SameSiteIsPersistent)773 TEST_F(SQLitePersistentCookieStoreTest, SameSiteIsPersistent) {
774   const char kDomain[] = "sessioncookie.com";
775   const char kNoneName[] = "none";
776   const char kLaxName[] = "lax";
777   const char kStrictName[] = "strict";
778   const char kCookieValue[] = "value";
779   const char kCookiePath[] = "/";
780 
781   InitializeStore(false, true);
782 
783   // Add a non-samesite persistent cookie.
784   store_->AddCookie(*CanonicalCookie::CreateUnsafeCookieForTesting(
785       kNoneName, kCookieValue, kDomain, kCookiePath,
786       base::Time::Now() - base::Minutes(1), base::Time::Now() + base::Days(1),
787       base::Time(), base::Time(), false, false, CookieSameSite::NO_RESTRICTION,
788       COOKIE_PRIORITY_DEFAULT, false));
789 
790   // Add a lax-samesite persistent cookie.
791   store_->AddCookie(*CanonicalCookie::CreateUnsafeCookieForTesting(
792       kLaxName, kCookieValue, kDomain, kCookiePath,
793       base::Time::Now() - base::Minutes(2), base::Time::Now() + base::Days(1),
794       base::Time(), base::Time(), false, false, CookieSameSite::LAX_MODE,
795       COOKIE_PRIORITY_DEFAULT, false));
796 
797   // Add a strict-samesite persistent cookie.
798   store_->AddCookie(*CanonicalCookie::CreateUnsafeCookieForTesting(
799       kStrictName, kCookieValue, kDomain, kCookiePath,
800       base::Time::Now() - base::Minutes(3), base::Time::Now() + base::Days(1),
801       base::Time(), base::Time(), false, false, CookieSameSite::STRICT_MODE,
802       COOKIE_PRIORITY_DEFAULT, false));
803 
804   // Force the store to write its data to the disk.
805   DestroyStore();
806 
807   // Create a store that loads session cookie and test that the SameSite
808   // attribute values are restored.
809   CanonicalCookieVector cookies;
810   CreateAndLoad(false, true, &cookies);
811   ASSERT_EQ(3U, cookies.size());
812 
813   // Put the cookies into a map, by name, for comparison below.
814   std::map<std::string, CanonicalCookie*> cookie_map;
815   for (const auto& cookie : cookies)
816     cookie_map[cookie->Name()] = cookie.get();
817 
818   // Validate that each cookie has the correct SameSite.
819   ASSERT_EQ(1u, cookie_map.count(kNoneName));
820   EXPECT_EQ(CookieSameSite::NO_RESTRICTION, cookie_map[kNoneName]->SameSite());
821 
822   ASSERT_EQ(1u, cookie_map.count(kLaxName));
823   EXPECT_EQ(CookieSameSite::LAX_MODE, cookie_map[kLaxName]->SameSite());
824 
825   ASSERT_EQ(1u, cookie_map.count(kStrictName));
826   EXPECT_EQ(CookieSameSite::STRICT_MODE, cookie_map[kStrictName]->SameSite());
827 }
828 
TEST_F(SQLitePersistentCookieStoreTest,SameSiteExtendedTreatedAsUnspecified)829 TEST_F(SQLitePersistentCookieStoreTest, SameSiteExtendedTreatedAsUnspecified) {
830   constexpr char kDomain[] = "sessioncookie.com";
831   constexpr char kExtendedName[] = "extended";
832   constexpr char kCookieValue[] = "value";
833   constexpr char kCookiePath[] = "/";
834 
835   InitializeStore(false, true);
836 
837   // Add an extended-samesite persistent cookie by first adding a strict-same
838   // site cookie, then turning that into the legacy extended-samesite state with
839   // direct SQL DB access.
840   store_->AddCookie(*CanonicalCookie::CreateUnsafeCookieForTesting(
841       kExtendedName, kCookieValue, kDomain, kCookiePath,
842       base::Time::Now() - base::Minutes(1), base::Time::Now() + base::Days(1),
843       base::Time(), base::Time(), false, false, CookieSameSite::STRICT_MODE,
844       COOKIE_PRIORITY_DEFAULT, false));
845 
846   // Force the store to write its data to the disk.
847   DestroyStore();
848 
849   // Open db.
850   sql::Database connection;
851   ASSERT_TRUE(connection.Open(temp_dir_.GetPath().Append(kCookieFilename)));
852   std::string update_stmt(
853       "UPDATE cookies SET samesite=3"  // 3 is Extended.
854       " WHERE samesite=2"              // 2 is Strict.
855   );
856   ASSERT_TRUE(connection.Execute(update_stmt.c_str()));
857   connection.Close();
858 
859   // Create a store that loads session cookie and test that the
860   // SameSite=Extended attribute values is ignored.
861   CanonicalCookieVector cookies;
862   CreateAndLoad(false, true, &cookies);
863   ASSERT_EQ(1U, cookies.size());
864 
865   // Validate that the cookie has the correct SameSite.
866   EXPECT_EQ(kExtendedName, cookies[0]->Name());
867   EXPECT_EQ(CookieSameSite::UNSPECIFIED, cookies[0]->SameSite());
868 }
869 
TEST_F(SQLitePersistentCookieStoreTest,SamePartyIsPersistent)870 TEST_F(SQLitePersistentCookieStoreTest, SamePartyIsPersistent) {
871   const char kDomain[] = "sessioncookie.com";
872   const char kNonSamePartyCookieName[] = "no_party";
873   const char kSamePartyCookieName[] = "party";
874   const char kCookieValue[] = "value";
875   const char kCookiePath[] = "/";
876 
877   InitializeStore(false, true);
878 
879   // Add a non-SameParty persistent cookie.
880   store_->AddCookie(*CanonicalCookie::CreateUnsafeCookieForTesting(
881       kNonSamePartyCookieName, kCookieValue, kDomain, kCookiePath,
882       base::Time::Now() - base::Minutes(1), base::Time::Now() + base::Days(1),
883       base::Time(), base::Time(),
884       /*secure=*/true, false, CookieSameSite::LAX_MODE, COOKIE_PRIORITY_DEFAULT,
885       /*same_party=*/false));
886 
887   // Add a SameParty persistent cookie.
888   store_->AddCookie(*CanonicalCookie::CreateUnsafeCookieForTesting(
889       kSamePartyCookieName, kCookieValue, kDomain, kCookiePath,
890       base::Time::Now() - base::Minutes(1), base::Time::Now() + base::Days(1),
891       base::Time(), base::Time(),
892       /*secure=*/true, false, CookieSameSite::LAX_MODE, COOKIE_PRIORITY_DEFAULT,
893       /*same_party=*/true));
894 
895   // Force the store to write its data to the disk.
896   DestroyStore();
897 
898   // Create a store that loads session cookie and test that the SameParty
899   // attribute values are restored.
900   CanonicalCookieVector cookies;
901   CreateAndLoad(false, true, &cookies);
902   ASSERT_EQ(2U, cookies.size());
903 
904   // Put the cookies into a map, by name, for comparison below.
905   std::map<std::string, CanonicalCookie*> cookie_map;
906   for (const auto& cookie : cookies)
907     cookie_map[cookie->Name()] = cookie.get();
908 
909   // Validate that each cookie has the correct SameParty.
910   ASSERT_EQ(1u, cookie_map.count(kNonSamePartyCookieName));
911   EXPECT_FALSE(cookie_map[kNonSamePartyCookieName]->IsSameParty());
912 
913   ASSERT_EQ(1u, cookie_map.count(kSamePartyCookieName));
914   EXPECT_TRUE(cookie_map[kSamePartyCookieName]->IsSameParty());
915 }
916 
TEST_F(SQLitePersistentCookieStoreTest,SourcePortIsPersistent)917 TEST_F(SQLitePersistentCookieStoreTest, SourcePortIsPersistent) {
918   const char kDomain[] = "sessioncookie.com";
919   const char kCookieValue[] = "value";
920   const char kCookiePath[] = "/";
921 
922   struct CookieTestValues {
923     std::string name;
924     int port;
925   };
926 
927   const std::vector<CookieTestValues> kTestCookies = {
928       {"1", 80},
929       {"2", 443},
930       {"3", 1234},
931       {"4", url::PORT_UNSPECIFIED},
932       {"5", url::PORT_INVALID}};
933 
934   InitializeStore(false, true);
935 
936   for (const auto& input : kTestCookies) {
937     // Add some persistent cookies.
938     store_->AddCookie(*CanonicalCookie::CreateUnsafeCookieForTesting(
939         input.name, kCookieValue, kDomain, kCookiePath,
940         base::Time::Now() - base::Minutes(1), base::Time::Now() + base::Days(1),
941         base::Time(), base::Time(),
942         /*secure=*/true, false, CookieSameSite::LAX_MODE,
943         COOKIE_PRIORITY_DEFAULT,
944         /*same_party=*/false,
945         /*partition_key=*/absl::nullopt,
946         CookieSourceScheme::kUnset /* Doesn't matter for this test. */,
947         input.port));
948   }
949 
950   // Force the store to write its data to the disk.
951   DestroyStore();
952 
953   // Create a store that loads session cookie and test that the source_port
954   // attribute values are restored.
955   CanonicalCookieVector cookies;
956   CreateAndLoad(false, true, &cookies);
957   ASSERT_EQ(kTestCookies.size(), cookies.size());
958 
959   // Put the cookies into a map, by name, for comparison below.
960   std::map<std::string, CanonicalCookie*> cookie_map;
961   for (const auto& cookie : cookies)
962     cookie_map[cookie->Name()] = cookie.get();
963 
964   for (const auto& expected : kTestCookies) {
965     ASSERT_EQ(1u, cookie_map.count(expected.name));
966     ASSERT_EQ(expected.port, cookie_map[expected.name]->SourcePort());
967   }
968 }
969 
TEST_F(SQLitePersistentCookieStoreTest,UpdateToEncryption)970 TEST_F(SQLitePersistentCookieStoreTest, UpdateToEncryption) {
971   CanonicalCookieVector cookies;
972 
973   // Create unencrypted cookie store and write something to it.
974   InitializeStore(false, false);
975   AddCookie("name", "value123XYZ", "foo.bar", "/", base::Time::Now());
976   DestroyStore();
977 
978   // Verify that "value" is visible in the file.  This is necessary in order to
979   // have confidence in a later test that "encrypted_value" is not visible.
980   std::string contents = ReadRawDBContents();
981   EXPECT_NE(0U, contents.length());
982   EXPECT_NE(contents.find("value123XYZ"), std::string::npos);
983 
984   // Create encrypted cookie store and ensure old cookie still reads.
985   cookies.clear();
986   EXPECT_EQ(0U, cookies.size());
987   CreateAndLoad(true, false, &cookies);
988   EXPECT_EQ(1U, cookies.size());
989   EXPECT_EQ("name", cookies[0]->Name());
990   EXPECT_EQ("value123XYZ", cookies[0]->Value());
991 
992   // Make sure we can update existing cookie and add new cookie as encrypted.
993   store_->DeleteCookie(*(cookies[0]));
994   AddCookie("name", "encrypted_value123XYZ", "foo.bar", "/", base::Time::Now());
995   AddCookie("other", "something456ABC", "foo.bar", "/",
996             base::Time::Now() + base::Microseconds(10));
997   DestroyStore();
998   cookies.clear();
999   CreateAndLoad(true, false, &cookies);
1000   EXPECT_EQ(2U, cookies.size());
1001   CanonicalCookie* cookie_name = nullptr;
1002   CanonicalCookie* cookie_other = nullptr;
1003   if (cookies[0]->Name() == "name") {
1004     cookie_name = cookies[0].get();
1005     cookie_other = cookies[1].get();
1006   } else {
1007     cookie_name = cookies[1].get();
1008     cookie_other = cookies[0].get();
1009   }
1010   EXPECT_EQ("encrypted_value123XYZ", cookie_name->Value());
1011   EXPECT_EQ("something456ABC", cookie_other->Value());
1012   DestroyStore();
1013   cookies.clear();
1014 
1015   // Examine the real record to make sure plaintext version doesn't exist.
1016   sql::Database db;
1017   sql::Statement smt;
1018   int resultcount = 0;
1019   ASSERT_TRUE(db.Open(temp_dir_.GetPath().Append(kCookieFilename)));
1020   smt.Assign(db.GetCachedStatement(SQL_FROM_HERE,
1021                                    "SELECT * "
1022                                    "FROM cookies "
1023                                    "WHERE host_key = 'foo.bar'"));
1024   while (smt.Step()) {
1025     resultcount++;
1026     for (int i = 0; i < smt.ColumnCount(); i++) {
1027       EXPECT_EQ(smt.ColumnString(i).find("value"), std::string::npos);
1028       EXPECT_EQ(smt.ColumnString(i).find("something"), std::string::npos);
1029     }
1030   }
1031   EXPECT_EQ(2, resultcount);
1032 
1033   // Verify that "encrypted_value" is NOT visible in the file.
1034   contents = ReadRawDBContents();
1035   EXPECT_NE(0U, contents.length());
1036   EXPECT_EQ(contents.find("encrypted_value123XYZ"), std::string::npos);
1037   EXPECT_EQ(contents.find("something456ABC"), std::string::npos);
1038 }
1039 
TEST_F(SQLitePersistentCookieStoreTest,UpdateFromEncryption)1040 TEST_F(SQLitePersistentCookieStoreTest, UpdateFromEncryption) {
1041   CanonicalCookieVector cookies;
1042 
1043   // Create unencrypted cookie store and write something to it.
1044   InitializeStore(true, false);
1045   AddCookie("name", "value123XYZ", "foo.bar", "/", base::Time::Now());
1046   DestroyStore();
1047 
1048   // Verify that "value" is not visible in the file.
1049   std::string contents = ReadRawDBContents();
1050   EXPECT_NE(0U, contents.length());
1051   EXPECT_EQ(contents.find("value123XYZ"), std::string::npos);
1052 
1053   // Create encrypted cookie store and ensure old cookie still reads.
1054   cookies.clear();
1055   EXPECT_EQ(0U, cookies.size());
1056   CreateAndLoad(true, false, &cookies);
1057   EXPECT_EQ(1U, cookies.size());
1058   EXPECT_EQ("name", cookies[0]->Name());
1059   EXPECT_EQ("value123XYZ", cookies[0]->Value());
1060 
1061   // Make sure we can update existing cookie and it writes unencrypted.
1062   cookie_crypto_delegate_->should_encrypt_ = false;
1063   store_->DeleteCookie(*(cookies[0]));
1064   AddCookie("name", "plaintext_value123XYZ", "foo.bar", "/", base::Time::Now());
1065   AddCookie("other", "something456ABC", "foo.bar", "/",
1066             base::Time::Now() + base::Microseconds(10));
1067   DestroyStore();
1068   cookies.clear();
1069   CreateAndLoad(true, false, &cookies);
1070   EXPECT_EQ(2U, cookies.size());
1071   CanonicalCookie* cookie_name = nullptr;
1072   CanonicalCookie* cookie_other = nullptr;
1073   if (cookies[0]->Name() == "name") {
1074     cookie_name = cookies[0].get();
1075     cookie_other = cookies[1].get();
1076   } else {
1077     cookie_name = cookies[1].get();
1078     cookie_other = cookies[0].get();
1079   }
1080   EXPECT_EQ("plaintext_value123XYZ", cookie_name->Value());
1081   EXPECT_EQ("something456ABC", cookie_other->Value());
1082   DestroyStore();
1083   cookies.clear();
1084 
1085   // Verify that "value" is now visible in the file.
1086   contents = ReadRawDBContents();
1087   EXPECT_NE(0U, contents.length());
1088   EXPECT_NE(contents.find("value123XYZ"), std::string::npos);
1089 }
1090 
CompareCookies(const std::unique_ptr<CanonicalCookie> & a,const std::unique_ptr<CanonicalCookie> & b)1091 bool CompareCookies(const std::unique_ptr<CanonicalCookie>& a,
1092                     const std::unique_ptr<CanonicalCookie>& b) {
1093   return a->PartialCompare(*b);
1094 }
1095 
CreateV9Schema(sql::Database * db)1096 bool CreateV9Schema(sql::Database* db) {
1097   sql::MetaTable meta_table;
1098   if (!meta_table.Init(db, 9 /* version */,
1099                        3 /* earliest compatible version */)) {
1100     return false;
1101   }
1102 
1103   // Version 9 schema
1104   std::string stmt(
1105       base::StringPrintf("CREATE TABLE cookies ("
1106                          "creation_utc INTEGER NOT NULL UNIQUE PRIMARY KEY,"
1107                          "host_key TEXT NOT NULL,"
1108                          "name TEXT NOT NULL,"
1109                          "value TEXT NOT NULL,"
1110                          "path TEXT NOT NULL,"
1111                          "expires_utc INTEGER NOT NULL,"
1112                          "secure INTEGER NOT NULL,"
1113                          "httponly INTEGER NOT NULL,"
1114                          "last_access_utc INTEGER NOT NULL, "
1115                          "has_expires INTEGER NOT NULL DEFAULT 1, "
1116                          "persistent INTEGER NOT NULL DEFAULT 1,"
1117                          "priority INTEGER NOT NULL DEFAULT 0,"
1118                          "encrypted_value BLOB DEFAULT '',"
1119                          "firstpartyonly INTEGER NOT NULL DEFAULT 0)"));
1120   if (!db->Execute(stmt.c_str()))
1121     return false;
1122   if (!db->Execute("CREATE INDEX domain ON cookies(host_key)"))
1123     return false;
1124   if (!db->Execute("CREATE INDEX is_transient ON cookies(persistent) "
1125                    "where persistent != 1")) {
1126     return false;
1127   }
1128   return true;
1129 }
1130 
1131 bool AddV9CookiesToDBImpl(sql::Database* db,
1132                           const std::vector<CanonicalCookie>& cookies);
1133 
1134 // Add a selection of cookies to the DB.
AddV9CookiesToDB(sql::Database * db)1135 bool AddV9CookiesToDB(sql::Database* db) {
1136   static base::Time cookie_time(base::Time::Now());
1137 
1138   std::vector<CanonicalCookie> cookies;
1139   cookies.push_back(*CanonicalCookie::CreateUnsafeCookieForTesting(
1140       "A", "B", "example.com", "/", cookie_time, cookie_time, cookie_time,
1141       cookie_time, false, false, CookieSameSite::NO_RESTRICTION,
1142       COOKIE_PRIORITY_DEFAULT, false));
1143   cookie_time += base::Microseconds(1);
1144   cookies.push_back(*CanonicalCookie::CreateUnsafeCookieForTesting(
1145       "C", "B", "example.com", "/", cookie_time, cookie_time, cookie_time,
1146       cookie_time, false, false, CookieSameSite::NO_RESTRICTION,
1147       COOKIE_PRIORITY_DEFAULT, false));
1148   cookie_time += base::Microseconds(1);
1149   cookies.push_back(*CanonicalCookie::CreateUnsafeCookieForTesting(
1150       "A", "B", "example2.com", "/", cookie_time, cookie_time, cookie_time,
1151       cookie_time, false, false, CookieSameSite::NO_RESTRICTION,
1152       COOKIE_PRIORITY_DEFAULT, false));
1153   cookie_time += base::Microseconds(1);
1154   cookies.push_back(*CanonicalCookie::CreateUnsafeCookieForTesting(
1155       "C", "B", "example2.com", "/", cookie_time, cookie_time, cookie_time,
1156       cookie_time, false, false, CookieSameSite::NO_RESTRICTION,
1157       COOKIE_PRIORITY_DEFAULT, false));
1158   cookie_time += base::Microseconds(1);
1159   cookies.push_back(*CanonicalCookie::CreateUnsafeCookieForTesting(
1160       "A", "B", "example.com", "/path", cookie_time, cookie_time, cookie_time,
1161       cookie_time, false, false, CookieSameSite::NO_RESTRICTION,
1162       COOKIE_PRIORITY_DEFAULT, false));
1163   cookie_time += base::Microseconds(1);
1164   cookies.push_back(*CanonicalCookie::CreateUnsafeCookieForTesting(
1165       "C", "B", "example.com", "/path", cookie_time, cookie_time, cookie_time,
1166       cookie_time, false, false, CookieSameSite::NO_RESTRICTION,
1167       COOKIE_PRIORITY_DEFAULT, false));
1168   cookie_time += base::Microseconds(1);
1169   return AddV9CookiesToDBImpl(db, cookies);
1170 }
1171 
AddV9CookiesToDBImpl(sql::Database * db,const std::vector<CanonicalCookie> & cookies)1172 bool AddV9CookiesToDBImpl(sql::Database* db,
1173                           const std::vector<CanonicalCookie>& cookies) {
1174   sql::Statement statement(db->GetCachedStatement(
1175       SQL_FROM_HERE,
1176       "INSERT INTO cookies (creation_utc, host_key, name, value, "
1177       "encrypted_value, path, expires_utc, secure, httponly, firstpartyonly, "
1178       "last_access_utc, has_expires, persistent, priority) "
1179       "VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?)"));
1180   if (!statement.is_valid())
1181     return false;
1182   sql::Transaction transaction(db);
1183   if (!transaction.Begin())
1184     return false;
1185   for (const auto& cookie : cookies) {
1186     statement.Reset(true);
1187     statement.BindInt64(
1188         0, cookie.CreationDate().ToDeltaSinceWindowsEpoch().InMicroseconds());
1189     statement.BindString(1, cookie.Domain());
1190     statement.BindString(2, cookie.Name());
1191     statement.BindString(3, cookie.Value());
1192     statement.BindBlob(4, base::span<uint8_t>());  // encrypted_value
1193     statement.BindString(5, cookie.Path());
1194     statement.BindInt64(
1195         6, cookie.ExpiryDate().ToDeltaSinceWindowsEpoch().InMicroseconds());
1196     statement.BindInt(7, cookie.IsSecure());
1197     statement.BindInt(8, cookie.IsHttpOnly());
1198     // Note that this and Priority() below nominally rely on the enums in
1199     // sqlite_persistent_cookie_store.cc having the same values as the
1200     // ones in ../../cookies/cookie_constants.h.  But nothing in this test
1201     // relies on that equivalence, so it's not worth the hassle to guarantee
1202     // that.
1203     statement.BindInt(9, static_cast<int>(cookie.SameSite()));
1204     statement.BindInt64(
1205         10,
1206         cookie.LastAccessDate().ToDeltaSinceWindowsEpoch().InMicroseconds());
1207     statement.BindInt(11, cookie.IsPersistent());
1208     statement.BindInt(12, cookie.IsPersistent());
1209     statement.BindInt(13, static_cast<int>(cookie.Priority()));
1210     if (!statement.Run())
1211       return false;
1212   }
1213   if (!transaction.Commit())
1214     return false;
1215 
1216   return true;
1217 }
1218 
1219 // Confirm the cookie list passed in has the above cookies in it.
ConfirmV9CookiesFromDB(std::vector<std::unique_ptr<CanonicalCookie>> read_in_cookies)1220 void ConfirmV9CookiesFromDB(
1221     std::vector<std::unique_ptr<CanonicalCookie>> read_in_cookies) {
1222   std::sort(read_in_cookies.begin(), read_in_cookies.end(), &CompareCookies);
1223   int i = 0;
1224   EXPECT_EQ("A", read_in_cookies[i]->Name());
1225   EXPECT_EQ("B", read_in_cookies[i]->Value());
1226   EXPECT_EQ("example.com", read_in_cookies[i]->Domain());
1227   EXPECT_EQ("/", read_in_cookies[i]->Path());
1228 
1229   i++;
1230   EXPECT_EQ("A", read_in_cookies[i]->Name());
1231   EXPECT_EQ("B", read_in_cookies[i]->Value());
1232   EXPECT_EQ("example.com", read_in_cookies[i]->Domain());
1233   EXPECT_EQ("/path", read_in_cookies[i]->Path());
1234 
1235   i++;
1236   EXPECT_EQ("A", read_in_cookies[i]->Name());
1237   EXPECT_EQ("B", read_in_cookies[i]->Value());
1238   EXPECT_EQ("example2.com", read_in_cookies[i]->Domain());
1239   EXPECT_EQ("/", read_in_cookies[i]->Path());
1240 
1241   i++;
1242   EXPECT_EQ("C", read_in_cookies[i]->Name());
1243   EXPECT_EQ("B", read_in_cookies[i]->Value());
1244   EXPECT_EQ("example.com", read_in_cookies[i]->Domain());
1245   EXPECT_EQ("/", read_in_cookies[i]->Path());
1246 
1247   i++;
1248   EXPECT_EQ("C", read_in_cookies[i]->Name());
1249   EXPECT_EQ("B", read_in_cookies[i]->Value());
1250   EXPECT_EQ("example.com", read_in_cookies[i]->Domain());
1251   EXPECT_EQ("/path", read_in_cookies[i]->Path());
1252 
1253   i++;
1254   EXPECT_EQ("C", read_in_cookies[i]->Name());
1255   EXPECT_EQ("B", read_in_cookies[i]->Value());
1256   EXPECT_EQ("example2.com", read_in_cookies[i]->Domain());
1257   EXPECT_EQ("/", read_in_cookies[i]->Path());
1258 }
1259 
1260 // Confirm that upgrading from a cookie store created with the
1261 // creation time uniqueness constraint to one with the (name, domain, path)
1262 // uniqueness constraint works with a good DB.
TEST_F(SQLitePersistentCookieStoreTest,UpgradeToSchemaVersion10)1263 TEST_F(SQLitePersistentCookieStoreTest, UpgradeToSchemaVersion10) {
1264   // Open db.
1265   sql::Database connection;
1266   ASSERT_TRUE(connection.Open(temp_dir_.GetPath().Append(kCookieFilename)));
1267   ASSERT_TRUE(CreateV9Schema(&connection));
1268   ASSERT_TRUE(AddV9CookiesToDB(&connection));
1269   connection.Close();
1270 
1271   std::vector<std::unique_ptr<CanonicalCookie>> read_in_cookies;
1272   CreateAndLoad(false, false, &read_in_cookies);
1273   ConfirmV9CookiesFromDB(std::move(read_in_cookies));
1274 }
1275 
1276 // Confirm that upgrading from a cookie store created with the
1277 // creation time uniqueness constraint to one with the (name, domain, path)
1278 // uniqueness constraint works with a corrupted DB.
TEST_F(SQLitePersistentCookieStoreTest,UpgradeToSchemaVersion10Corrupted)1279 TEST_F(SQLitePersistentCookieStoreTest, UpgradeToSchemaVersion10Corrupted) {
1280   // Open db.
1281   sql::Database connection;
1282   ASSERT_TRUE(connection.Open(temp_dir_.GetPath().Append(kCookieFilename)));
1283 
1284   ASSERT_TRUE(CreateV9Schema(&connection));
1285 
1286   base::Time old_time = base::Time::Now() - base::Minutes(90);
1287   base::Time old_time2 = base::Time::Now() - base::Minutes(91);
1288   auto old_cookie1 = CanonicalCookie::CreateUnsafeCookieForTesting(
1289       "A", "old_value", "example.com", "/", old_time, old_time, old_time,
1290       old_time, false, false, CookieSameSite::NO_RESTRICTION,
1291       COOKIE_PRIORITY_DEFAULT, false);
1292   AddV9CookiesToDBImpl(&connection, {*old_cookie1});
1293 
1294   // Add the same set of cookies twice to create duplicates.
1295   ASSERT_TRUE(AddV9CookiesToDB(&connection));
1296   ASSERT_TRUE(AddV9CookiesToDB(&connection));
1297 
1298   // Add some others as well.
1299   auto old_cookie2 = CanonicalCookie::CreateUnsafeCookieForTesting(
1300       "A", "old_value", "example.com", "/path", old_time2, old_time2, old_time2,
1301       old_time2, false, false, CookieSameSite::NO_RESTRICTION,
1302       COOKIE_PRIORITY_DEFAULT, false);
1303   AddV9CookiesToDBImpl(&connection, {*old_cookie2});
1304 
1305   connection.Close();
1306 
1307   std::vector<std::unique_ptr<CanonicalCookie>> read_in_cookies;
1308   CreateAndLoad(false, false, &read_in_cookies);
1309   // Finding failures of the uniqueness constraint should resolve them by
1310   // timestamp.
1311   ConfirmV9CookiesFromDB(std::move(read_in_cookies));
1312 }
1313 
1314 // Confirm the store can handle having cookies with identical creation
1315 // times stored in it.
TEST_F(SQLitePersistentCookieStoreTest,IdenticalCreationTimes)1316 TEST_F(SQLitePersistentCookieStoreTest, IdenticalCreationTimes) {
1317   InitializeStore(false, false);
1318   base::Time cookie_time(base::Time::Now());
1319   base::Time cookie_expiry(cookie_time + base::Days(1));
1320   AddCookieWithExpiration("A", "B", "example.com", "/", cookie_time,
1321                           cookie_expiry);
1322   AddCookieWithExpiration("C", "B", "example.com", "/", cookie_time,
1323                           cookie_expiry);
1324   AddCookieWithExpiration("A", "B", "example2.com", "/", cookie_time,
1325                           cookie_expiry);
1326   AddCookieWithExpiration("C", "B", "example2.com", "/", cookie_time,
1327                           cookie_expiry);
1328   AddCookieWithExpiration("A", "B", "example.com", "/path", cookie_time,
1329                           cookie_expiry);
1330   AddCookieWithExpiration("C", "B", "example.com", "/path", cookie_time,
1331                           cookie_expiry);
1332   Flush();
1333   DestroyStore();
1334 
1335   std::vector<std::unique_ptr<CanonicalCookie>> read_in_cookies;
1336   CreateAndLoad(false, false, &read_in_cookies);
1337   ASSERT_EQ(6u, read_in_cookies.size());
1338 
1339   std::sort(read_in_cookies.begin(), read_in_cookies.end(), &CompareCookies);
1340   int i = 0;
1341   EXPECT_EQ("A", read_in_cookies[i]->Name());
1342   EXPECT_EQ("example.com", read_in_cookies[i]->Domain());
1343   EXPECT_EQ("/", read_in_cookies[i]->Path());
1344 
1345   i++;
1346   EXPECT_EQ("A", read_in_cookies[i]->Name());
1347   EXPECT_EQ("example.com", read_in_cookies[i]->Domain());
1348   EXPECT_EQ("/path", read_in_cookies[i]->Path());
1349 
1350   i++;
1351   EXPECT_EQ("A", read_in_cookies[i]->Name());
1352   EXPECT_EQ("example2.com", read_in_cookies[i]->Domain());
1353   EXPECT_EQ("/", read_in_cookies[i]->Path());
1354 
1355   i++;
1356   EXPECT_EQ("C", read_in_cookies[i]->Name());
1357   EXPECT_EQ("example.com", read_in_cookies[i]->Domain());
1358   EXPECT_EQ("/", read_in_cookies[i]->Path());
1359 
1360   i++;
1361   EXPECT_EQ("C", read_in_cookies[i]->Name());
1362   EXPECT_EQ("example.com", read_in_cookies[i]->Domain());
1363   EXPECT_EQ("/path", read_in_cookies[i]->Path());
1364 
1365   i++;
1366   EXPECT_EQ("C", read_in_cookies[i]->Name());
1367   EXPECT_EQ("example2.com", read_in_cookies[i]->Domain());
1368   EXPECT_EQ("/", read_in_cookies[i]->Path());
1369 }
1370 
TEST_F(SQLitePersistentCookieStoreTest,KeyInconsistency)1371 TEST_F(SQLitePersistentCookieStoreTest, KeyInconsistency) {
1372   // Regression testcase for previous disagreement between CookieMonster
1373   // and SQLitePersistentCookieStoreTest as to what keys to LoadCookiesForKey
1374   // mean. The particular example doesn't, of course, represent an actual in-use
1375   // scenario, but while the inconstancy could happen with chrome-extension
1376   // URLs in real life, it was irrelevant for them in practice since their
1377   // rows would get key = "" which would get sorted before actual domains,
1378   // and therefore get loaded first by CookieMonster::FetchAllCookiesIfNecessary
1379   // with the task runners involved ensuring that would finish before the
1380   // incorrect LoadCookiesForKey got the chance to run.
1381   //
1382   // This test uses a URL that used to be treated differently by the two
1383   // layers that also sorts after other rows to avoid this scenario.
1384 
1385   // SQLitePersistentCookieStore will run its callbacks on what's passed to it
1386   // as |client_task_runner|, and CookieMonster expects to get callbacks from
1387   // its PersistentCookieStore on the same thread as its methods are invoked on;
1388   // so to avoid needing to post every CookieMonster API call, this uses the
1389   // current thread for SQLitePersistentCookieStore's |client_task_runner|.
1390   Create(false, false, true /* use_current_thread */, false);
1391 
1392   // Create a cookie on a scheme that doesn't handle cookies by default,
1393   // and save it.
1394   std::unique_ptr<CookieMonster> cookie_monster =
1395       std::make_unique<CookieMonster>(store_.get(), /*net_log=*/nullptr);
1396   ResultSavingCookieCallback<bool> cookie_scheme_callback1;
1397   cookie_monster->SetCookieableSchemes({"ftp", "http"},
1398                                        cookie_scheme_callback1.MakeCallback());
1399   cookie_scheme_callback1.WaitUntilDone();
1400   EXPECT_TRUE(cookie_scheme_callback1.result());
1401   ResultSavingCookieCallback<CookieAccessResult> set_cookie_callback;
1402   GURL ftp_url("ftp://subdomain.ftperiffic.com/page/");
1403   auto cookie =
1404       CanonicalCookie::Create(ftp_url, "A=B; max-age=3600", base::Time::Now(),
1405                               absl::nullopt /* server_time */,
1406                               absl::nullopt /* cookie_partition_key */);
1407   cookie_monster->SetCanonicalCookieAsync(std::move(cookie), ftp_url,
1408                                           CookieOptions::MakeAllInclusive(),
1409                                           set_cookie_callback.MakeCallback());
1410   set_cookie_callback.WaitUntilDone();
1411   EXPECT_TRUE(set_cookie_callback.result().status.IsInclude());
1412 
1413   // Also insert a whole bunch of cookies to slow down the background loading of
1414   // all the cookies.
1415   for (int i = 0; i < 50; ++i) {
1416     ResultSavingCookieCallback<CookieAccessResult> set_cookie_callback2;
1417     GURL url(base::StringPrintf("http://example%d.com/", i));
1418     auto canonical_cookie =
1419         CanonicalCookie::Create(url, "A=B; max-age=3600", base::Time::Now(),
1420                                 absl::nullopt /* server_time */,
1421                                 absl::nullopt /* cookie_partition_key */);
1422     cookie_monster->SetCanonicalCookieAsync(
1423         std::move(canonical_cookie), url, CookieOptions::MakeAllInclusive(),
1424         set_cookie_callback2.MakeCallback());
1425     set_cookie_callback2.WaitUntilDone();
1426     EXPECT_TRUE(set_cookie_callback2.result().status.IsInclude());
1427   }
1428 
1429   net::TestClosure flush_closure;
1430   cookie_monster->FlushStore(flush_closure.closure());
1431   flush_closure.WaitForResult();
1432   cookie_monster = nullptr;
1433 
1434   // Re-create the PersistentCookieStore & CookieMonster. Note that the
1435   // destroyed store's ops will happen on same runners as the previous
1436   // instances, so they should complete before the new PersistentCookieStore
1437   // starts looking at the state on disk.
1438   Create(false, false, true /* want current thread to invoke cookie monster */,
1439          false);
1440   cookie_monster =
1441       std::make_unique<CookieMonster>(store_.get(), /*net_log=*/nullptr);
1442   ResultSavingCookieCallback<bool> cookie_scheme_callback2;
1443   cookie_monster->SetCookieableSchemes({"ftp", "http"},
1444                                        cookie_scheme_callback2.MakeCallback());
1445   cookie_scheme_callback2.WaitUntilDone();
1446   EXPECT_TRUE(cookie_scheme_callback2.result());
1447 
1448   // Now try to get the cookie back.
1449   GetCookieListCallback get_callback;
1450   cookie_monster->GetCookieListWithOptionsAsync(
1451       GURL("ftp://subdomain.ftperiffic.com/page"),
1452       CookieOptions::MakeAllInclusive(), CookiePartitionKeyCollection(),
1453       base::BindOnce(&GetCookieListCallback::Run,
1454                      base::Unretained(&get_callback)));
1455   get_callback.WaitUntilDone();
1456   ASSERT_EQ(1u, get_callback.cookies().size());
1457   EXPECT_EQ("A", get_callback.cookies()[0].Name());
1458   EXPECT_EQ("B", get_callback.cookies()[0].Value());
1459   EXPECT_EQ("subdomain.ftperiffic.com", get_callback.cookies()[0].Domain());
1460 }
1461 
TEST_F(SQLitePersistentCookieStoreTest,OpsIfInitFailed)1462 TEST_F(SQLitePersistentCookieStoreTest, OpsIfInitFailed) {
1463   // Test to make sure we don't leak pending operations when initialization
1464   // fails really hard. To inject the failure, we put a directory where the
1465   // database file ought to be. This test relies on an external leak checker
1466   // (e.g. lsan) to actual catch thing.
1467   ASSERT_TRUE(
1468       base::CreateDirectory(temp_dir_.GetPath().Append(kCookieFilename)));
1469   Create(false, false, true /* want current thread to invoke cookie monster */,
1470          false);
1471   std::unique_ptr<CookieMonster> cookie_monster =
1472       std::make_unique<CookieMonster>(store_.get(), /*net_log=*/nullptr);
1473 
1474   ResultSavingCookieCallback<CookieAccessResult> set_cookie_callback;
1475   GURL url("http://www.example.com/");
1476   auto cookie =
1477       CanonicalCookie::Create(url, "A=B; max-age=3600", base::Time::Now(),
1478                               absl::nullopt /* server_time */,
1479                               absl::nullopt /* cookie_partition_key */);
1480   cookie_monster->SetCanonicalCookieAsync(std::move(cookie), url,
1481                                           CookieOptions::MakeAllInclusive(),
1482                                           set_cookie_callback.MakeCallback());
1483   set_cookie_callback.WaitUntilDone();
1484   EXPECT_TRUE(set_cookie_callback.result().status.IsInclude());
1485 
1486   // Things should commit once going out of scope.
1487 }
1488 
TEST_F(SQLitePersistentCookieStoreTest,Coalescing)1489 TEST_F(SQLitePersistentCookieStoreTest, Coalescing) {
1490   enum class Op { kAdd, kDelete, kUpdate };
1491 
1492   struct TestCase {
1493     std::vector<Op> operations;
1494     size_t expected_queue_length;
1495   };
1496 
1497   std::vector<TestCase> testcases = {
1498       {{Op::kAdd, Op::kDelete}, 1u},
1499       {{Op::kUpdate, Op::kDelete}, 1u},
1500       {{Op::kAdd, Op::kUpdate, Op::kDelete}, 1u},
1501       {{Op::kUpdate, Op::kUpdate}, 1u},
1502       {{Op::kAdd, Op::kUpdate, Op::kUpdate}, 2u},
1503       {{Op::kDelete, Op::kAdd}, 2u},
1504       {{Op::kDelete, Op::kAdd, Op::kUpdate}, 3u},
1505       {{Op::kDelete, Op::kAdd, Op::kUpdate, Op::kUpdate}, 3u},
1506       {{Op::kDelete, Op::kDelete}, 1u},
1507       {{Op::kDelete, Op::kAdd, Op::kDelete}, 1u},
1508       {{Op::kDelete, Op::kAdd, Op::kUpdate, Op::kDelete}, 1u}};
1509 
1510   std::unique_ptr<CanonicalCookie> cookie = CanonicalCookie::Create(
1511       GURL("http://www.example.com/path"), "Tasty=Yes", base::Time::Now(),
1512       absl::nullopt /* server_time */,
1513       absl::nullopt /* cookie_partition_key */);
1514 
1515   for (const TestCase& testcase : testcases) {
1516     Create(false, false, true /* want current thread to invoke the store. */,
1517            false);
1518 
1519     base::RunLoop run_loop;
1520     store_->Load(base::BindLambdaForTesting(
1521                      [&](CanonicalCookieVector cookies) { run_loop.Quit(); }),
1522                  NetLogWithSource());
1523     run_loop.Run();
1524 
1525     // Wedge the background thread to make sure that it doesn't start consuming
1526     // the queue.
1527     background_task_runner_->PostTask(
1528         FROM_HERE,
1529         base::BindOnce(&SQLitePersistentCookieStoreTest::WaitOnDBEvent,
1530                        base::Unretained(this)));
1531 
1532     // Now run the ops, and check how much gets queued.
1533     for (const Op op : testcase.operations) {
1534       switch (op) {
1535         case Op::kAdd:
1536           store_->AddCookie(*cookie);
1537           break;
1538 
1539         case Op::kDelete:
1540           store_->DeleteCookie(*cookie);
1541           break;
1542 
1543         case Op::kUpdate:
1544           store_->UpdateCookieAccessTime(*cookie);
1545           break;
1546       }
1547     }
1548 
1549     EXPECT_EQ(testcase.expected_queue_length,
1550               store_->GetQueueLengthForTesting());
1551 
1552     db_thread_event_.Signal();
1553   }
1554 }
1555 
TEST_F(SQLitePersistentCookieStoreTest,NoCoalesceUnrelated)1556 TEST_F(SQLitePersistentCookieStoreTest, NoCoalesceUnrelated) {
1557   Create(false, false, true /* want current thread to invoke the store. */,
1558          false);
1559 
1560   base::RunLoop run_loop;
1561   store_->Load(base::BindLambdaForTesting(
1562                    [&](CanonicalCookieVector cookies) { run_loop.Quit(); }),
1563                NetLogWithSource());
1564   run_loop.Run();
1565 
1566   std::unique_ptr<CanonicalCookie> cookie1 = CanonicalCookie::Create(
1567       GURL("http://www.example.com/path"), "Tasty=Yes", base::Time::Now(),
1568       absl::nullopt /* server_time */,
1569       absl::nullopt /* cookie_partition_key */);
1570 
1571   std::unique_ptr<CanonicalCookie> cookie2 = CanonicalCookie::Create(
1572       GURL("http://not.example.com/path"), "Tasty=No", base::Time::Now(),
1573       absl::nullopt /* server_time */,
1574       absl::nullopt /* cookie_partition_key */);
1575 
1576   // Wedge the background thread to make sure that it doesn't start consuming
1577   // the queue.
1578   background_task_runner_->PostTask(
1579       FROM_HERE, base::BindOnce(&SQLitePersistentCookieStoreTest::WaitOnDBEvent,
1580                                 base::Unretained(this)));
1581 
1582   store_->AddCookie(*cookie1);
1583   store_->DeleteCookie(*cookie2);
1584   // delete on cookie2 shouldn't cancel op on unrelated cookie1.
1585   EXPECT_EQ(2u, store_->GetQueueLengthForTesting());
1586 
1587   db_thread_event_.Signal();
1588 }
1589 
1590 // Locking is only supported on Windows.
1591 #if BUILDFLAG(IS_WIN)
1592 
1593 class SQLitePersistentCookieStoreExclusiveAccessTest
1594     : public SQLitePersistentCookieStoreTest,
1595       public ::testing::WithParamInterface<bool> {
1596  protected:
ShouldBeExclusive()1597   const bool& ShouldBeExclusive() { return GetParam(); }
1598 };
1599 
TEST_P(SQLitePersistentCookieStoreExclusiveAccessTest,LockedStore)1600 TEST_P(SQLitePersistentCookieStoreExclusiveAccessTest, LockedStore) {
1601   Create(false, false, true /* want current thread to invoke the store. */,
1602          /* exclusive access */ ShouldBeExclusive());
1603 
1604   base::RunLoop run_loop;
1605   store_->Load(base::BindLambdaForTesting(
1606                    [&](CanonicalCookieVector cookies) { run_loop.Quit(); }),
1607                NetLogWithSource());
1608   run_loop.Run();
1609 
1610   std::unique_ptr<CanonicalCookie> cookie = CanonicalCookie::Create(
1611       GURL("http://www.example.com/path"), "Tasty=Yes", base::Time::Now(),
1612       absl::nullopt /* server_time */,
1613       absl::nullopt /* cookie_partition_key */);
1614 
1615   // Wedge the background thread to make sure that it doesn't start consuming
1616   // the queue.
1617   background_task_runner_->PostTask(
1618       FROM_HERE, base::BindOnce(&SQLitePersistentCookieStoreTest::WaitOnDBEvent,
1619                                 base::Unretained(this)));
1620 
1621   store_->AddCookie(*cookie);
1622 
1623   {
1624     base::File file(
1625         temp_dir_.GetPath().Append(kCookieFilename),
1626         base::File::Flags::FLAG_OPEN_ALWAYS | base::File::Flags::FLAG_READ);
1627     // If locked, should not be able to open file even for read.
1628     EXPECT_EQ(ShouldBeExclusive(), !file.IsValid());
1629   }
1630 
1631   db_thread_event_.Signal();
1632 }
1633 
1634 INSTANTIATE_TEST_SUITE_P(All,
1635                          SQLitePersistentCookieStoreExclusiveAccessTest,
1636                          ::testing::Bool(),
__anon35b64b470502(const auto& info) 1637                          [](const auto& info) {
1638                            return info.param ? "Exclusive" : "NotExclusive";
1639                          });
1640 
1641 #endif  // BUILDFLAG(IS_WIN)
1642 
CreateV10Schema(sql::Database * db)1643 bool CreateV10Schema(sql::Database* db) {
1644   sql::MetaTable meta_table;
1645   if (!meta_table.Init(db, /* version = */ 10,
1646                        /* compatible version = */ 10)) {
1647     return false;
1648   }
1649 
1650   std::string stmt(
1651       "CREATE TABLE cookies ("
1652       "creation_utc INTEGER NOT NULL,"
1653       "host_key TEXT NOT NULL,"
1654       "name TEXT NOT NULL,"
1655       "value TEXT NOT NULL,"
1656       "path TEXT NOT NULL,"
1657       "expires_utc INTEGER NOT NULL,"
1658       "is_secure INTEGER NOT NULL,"
1659       "is_httponly INTEGER NOT NULL,"
1660       "last_access_utc INTEGER NOT NULL, "
1661       "has_expires INTEGER NOT NULL DEFAULT 1, "
1662       "is_persistent INTEGER NOT NULL DEFAULT 1,"
1663       "priority INTEGER NOT NULL DEFAULT 1,"  // COOKIE_PRIORITY_DEFAULT
1664       "encrypted_value BLOB DEFAULT '',"
1665       "firstpartyonly INTEGER NOT NULL DEFAULT 0,"  // NO_RESTRICTION
1666       "UNIQUE (host_key, name, path)"
1667       ")");
1668   if (!db->Execute(stmt.c_str()))
1669     return false;
1670 
1671   return true;
1672 }
1673 
1674 bool AddV10CookiesToDBImpl(sql::Database* db,
1675                            const std::vector<CanonicalCookie>& cookies);
1676 
1677 // Add a selection of cookies to the DB.
AddV10CookiesToDB(sql::Database * db)1678 bool AddV10CookiesToDB(sql::Database* db) {
1679   static base::Time time = base::Time::Now();
1680 
1681   std::vector<CanonicalCookie> cookies;
1682   cookies.push_back(*CanonicalCookie::CreateUnsafeCookieForTesting(
1683       "A", "B", "example.com", "/", time, time, time, time, false, false,
1684       CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_DEFAULT, false));
1685   cookies.push_back(*CanonicalCookie::CreateUnsafeCookieForTesting(
1686       "C", "B", "example.com", "/", time, time, time, time, false, false,
1687       CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_DEFAULT, false));
1688   cookies.push_back(*CanonicalCookie::CreateUnsafeCookieForTesting(
1689       "A", "B", "example2.com", "/", time, time, time, time, false, false,
1690       CookieSameSite::LAX_MODE, COOKIE_PRIORITY_DEFAULT, false));
1691   cookies.push_back(*CanonicalCookie::CreateUnsafeCookieForTesting(
1692       "C", "B", "example2.com", "/", time, time, time, time, false, false,
1693       CookieSameSite::LAX_MODE, COOKIE_PRIORITY_DEFAULT, false));
1694   cookies.push_back(*CanonicalCookie::CreateUnsafeCookieForTesting(
1695       "A", "B", "example.com", "/path", time, time, time, time, false, false,
1696       CookieSameSite::STRICT_MODE, COOKIE_PRIORITY_DEFAULT, false));
1697   cookies.push_back(*CanonicalCookie::CreateUnsafeCookieForTesting(
1698       "C", "B", "example.com", "/path", time, time, time, time, false, false,
1699       CookieSameSite::STRICT_MODE, COOKIE_PRIORITY_DEFAULT, false));
1700   return AddV10CookiesToDBImpl(db, cookies);
1701 }
1702 
AddV10CookiesToDBImpl(sql::Database * db,const std::vector<CanonicalCookie> & cookies)1703 bool AddV10CookiesToDBImpl(sql::Database* db,
1704                            const std::vector<CanonicalCookie>& cookies) {
1705   sql::Statement statement(db->GetCachedStatement(
1706       SQL_FROM_HERE,
1707       "INSERT INTO cookies (creation_utc, host_key, name, value, "
1708       "encrypted_value, path, expires_utc, is_secure, is_httponly, "
1709       "firstpartyonly, last_access_utc, has_expires, is_persistent, priority) "
1710       "VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?)"));
1711   if (!statement.is_valid())
1712     return false;
1713   sql::Transaction transaction(db);
1714   if (!transaction.Begin())
1715     return false;
1716   for (const auto& cookie : cookies) {
1717     statement.Reset(true);
1718     statement.BindInt64(
1719         0, cookie.CreationDate().ToDeltaSinceWindowsEpoch().InMicroseconds());
1720     statement.BindString(1, cookie.Domain());
1721     statement.BindString(2, cookie.Name());
1722     statement.BindString(3, cookie.Value());
1723     statement.BindBlob(4, base::span<uint8_t>());  // encrypted_value
1724     statement.BindString(5, cookie.Path());
1725     statement.BindInt64(
1726         6, cookie.ExpiryDate().ToDeltaSinceWindowsEpoch().InMicroseconds());
1727     statement.BindInt(7, cookie.IsSecure());
1728     statement.BindInt(8, cookie.IsHttpOnly());
1729     // Note that this and Priority() below nominally rely on the enums in
1730     // sqlite_persistent_cookie_store.cc having the same values as the
1731     // ones in ../../cookies/cookie_constants.h.  But nothing in this test
1732     // relies on that equivalence, so it's not worth the hassle to guarantee
1733     // that.
1734     statement.BindInt(9, static_cast<int>(cookie.SameSite()));
1735     statement.BindInt64(
1736         10,
1737         cookie.LastAccessDate().ToDeltaSinceWindowsEpoch().InMicroseconds());
1738     statement.BindInt(11, cookie.IsPersistent());
1739     statement.BindInt(12, cookie.IsPersistent());
1740     statement.BindInt(13, static_cast<int>(cookie.Priority()));
1741     if (!statement.Run())
1742       return false;
1743   }
1744   if (!transaction.Commit())
1745     return false;
1746 
1747   return true;
1748 }
1749 
1750 // Confirm the cookie list passed in has the above cookies in it.
ConfirmV10CookiesFromDB(std::vector<std::unique_ptr<CanonicalCookie>> read_in_cookies)1751 void ConfirmV10CookiesFromDB(
1752     std::vector<std::unique_ptr<CanonicalCookie>> read_in_cookies) {
1753   std::sort(read_in_cookies.begin(), read_in_cookies.end(), &CompareCookies);
1754   int i = 0;
1755   EXPECT_EQ("A", read_in_cookies[i]->Name());
1756   EXPECT_EQ("B", read_in_cookies[i]->Value());
1757   EXPECT_EQ("example.com", read_in_cookies[i]->Domain());
1758   EXPECT_EQ("/", read_in_cookies[i]->Path());
1759   // NO_RESTRICTION gets changed to UNSPECIFIED upon DB migration from V10.
1760   EXPECT_EQ(CookieSameSite::UNSPECIFIED, read_in_cookies[i]->SameSite());
1761 
1762   i++;
1763   EXPECT_EQ("A", read_in_cookies[i]->Name());
1764   EXPECT_EQ("B", read_in_cookies[i]->Value());
1765   EXPECT_EQ("example.com", read_in_cookies[i]->Domain());
1766   EXPECT_EQ("/path", read_in_cookies[i]->Path());
1767   // STRICT_MODE stays the same.
1768   EXPECT_EQ(CookieSameSite::STRICT_MODE, read_in_cookies[i]->SameSite());
1769 
1770   i++;
1771   EXPECT_EQ("A", read_in_cookies[i]->Name());
1772   EXPECT_EQ("B", read_in_cookies[i]->Value());
1773   EXPECT_EQ("example2.com", read_in_cookies[i]->Domain());
1774   EXPECT_EQ("/", read_in_cookies[i]->Path());
1775   // LAX_MODE stays the same.
1776   EXPECT_EQ(CookieSameSite::LAX_MODE, read_in_cookies[i]->SameSite());
1777 
1778   i++;
1779   EXPECT_EQ("C", read_in_cookies[i]->Name());
1780   EXPECT_EQ("B", read_in_cookies[i]->Value());
1781   EXPECT_EQ("example.com", read_in_cookies[i]->Domain());
1782   EXPECT_EQ("/", read_in_cookies[i]->Path());
1783   // NO_RESTRICTION gets changed to UNSPECIFIED upon DB migration from V10.
1784   EXPECT_EQ(CookieSameSite::UNSPECIFIED, read_in_cookies[i]->SameSite());
1785 
1786   i++;
1787   EXPECT_EQ("C", read_in_cookies[i]->Name());
1788   EXPECT_EQ("B", read_in_cookies[i]->Value());
1789   EXPECT_EQ("example.com", read_in_cookies[i]->Domain());
1790   EXPECT_EQ("/path", read_in_cookies[i]->Path());
1791   // STRICT_MODE stays the same.
1792   EXPECT_EQ(CookieSameSite::STRICT_MODE, read_in_cookies[i]->SameSite());
1793 
1794   i++;
1795   EXPECT_EQ("C", read_in_cookies[i]->Name());
1796   EXPECT_EQ("B", read_in_cookies[i]->Value());
1797   EXPECT_EQ("example2.com", read_in_cookies[i]->Domain());
1798   EXPECT_EQ("/", read_in_cookies[i]->Path());
1799   // LAX_MODE stays the same.
1800   EXPECT_EQ(CookieSameSite::LAX_MODE, read_in_cookies[i]->SameSite());
1801 }
1802 
1803 // Confirm that cookies with SameSite equal to NO_RESTRICTION get changed to
1804 // UNSPECIFIED.
TEST_F(SQLitePersistentCookieStoreTest,UpgradeToSchemaVersion11)1805 TEST_F(SQLitePersistentCookieStoreTest, UpgradeToSchemaVersion11) {
1806   // Open db.
1807   sql::Database connection;
1808   ASSERT_TRUE(connection.Open(temp_dir_.GetPath().Append(kCookieFilename)));
1809   ASSERT_TRUE(CreateV10Schema(&connection));
1810   ASSERT_TRUE(AddV10CookiesToDB(&connection));
1811   connection.Close();
1812 
1813   std::vector<std::unique_ptr<CanonicalCookie>> read_in_cookies;
1814   CreateAndLoad(false, false, &read_in_cookies);
1815   ConfirmV10CookiesFromDB(std::move(read_in_cookies));
1816 }
1817 
CreateV11Schema(sql::Database * db)1818 bool CreateV11Schema(sql::Database* db) {
1819   sql::MetaTable meta_table;
1820   if (!meta_table.Init(db, /* version = */ 11,
1821                        /* earliest compatible version = */ 11)) {
1822     return false;
1823   }
1824 
1825   // Version 11 schema
1826   std::string stmt(
1827       "CREATE TABLE cookies("
1828       "creation_utc INTEGER NOT NULL,"
1829       "host_key TEXT NOT NULL,"
1830       "name TEXT NOT NULL,"
1831       "value TEXT NOT NULL,"
1832       "path TEXT NOT NULL,"
1833       "expires_utc INTEGER NOT NULL,"
1834       "is_secure INTEGER NOT NULL,"
1835       "is_httponly INTEGER NOT NULL,"
1836       "last_access_utc INTEGER NOT NULL,"
1837       "has_expires INTEGER NOT NULL DEFAULT 1,"
1838       "is_persistent INTEGER NOT NULL DEFAULT 1,"
1839       "priority INTEGER NOT NULL DEFAULT 1,"  // COOKIE_PRIORITY_DEFAULT
1840       "encrypted_value BLOB DEFAULT '',"
1841       "samesite INTEGER NOT NULL DEFAULT -1,"  // UNSPECIFIED
1842       "UNIQUE (host_key, name, path))");
1843   if (!db->Execute(stmt.c_str()))
1844     return false;
1845 
1846   return true;
1847 }
1848 
CreateV12Schema(sql::Database * db)1849 bool CreateV12Schema(sql::Database* db) {
1850   sql::MetaTable meta_table;
1851   if (!meta_table.Init(db, /* version = */ 12,
1852                        /* earliest compatible version = */ 12)) {
1853     return false;
1854   }
1855 
1856   // Version 12 schema
1857   std::string stmt(
1858       "CREATE TABLE cookies("
1859       "creation_utc INTEGER NOT NULL,"
1860       "host_key TEXT NOT NULL,"
1861       "name TEXT NOT NULL,"
1862       "value TEXT NOT NULL,"
1863       "path TEXT NOT NULL,"
1864       "expires_utc INTEGER NOT NULL,"
1865       "is_secure INTEGER NOT NULL,"
1866       "is_httponly INTEGER NOT NULL,"
1867       "last_access_utc INTEGER NOT NULL,"
1868       "has_expires INTEGER NOT NULL DEFAULT 1,"
1869       "is_persistent INTEGER NOT NULL DEFAULT 1,"
1870       "priority INTEGER NOT NULL DEFAULT 1,"  // COOKIE_PRIORITY_DEFAULT
1871       "encrypted_value BLOB DEFAULT '',"
1872       "samesite INTEGER NOT NULL DEFAULT -1,"      // UNSPECIFIED
1873       "source_scheme INTEGER NOT NULL DEFAULT 0,"  // CookieSourceScheme::kUnset
1874       "UNIQUE (host_key, name, path))");
1875   if (!db->Execute(stmt.c_str()))
1876     return false;
1877 
1878   return true;
1879 }
1880 
CreateV13Schema(sql::Database * db)1881 bool CreateV13Schema(sql::Database* db) {
1882   sql::MetaTable meta_table;
1883   if (!meta_table.Init(db, /* version = */ 13,
1884                        /* earliest compatible version = */ 13)) {
1885     return false;
1886   }
1887 
1888   // Version 13 schema
1889   static constexpr char kCreateSql[] =
1890       "CREATE TABLE cookies("
1891       "creation_utc INTEGER NOT NULL,"
1892       "host_key TEXT NOT NULL,"
1893       "name TEXT NOT NULL,"
1894       "value TEXT NOT NULL,"
1895       "path TEXT NOT NULL,"
1896       "expires_utc INTEGER NOT NULL,"
1897       "is_secure INTEGER NOT NULL,"
1898       "is_httponly INTEGER NOT NULL,"
1899       "last_access_utc INTEGER NOT NULL,"
1900       "has_expires INTEGER NOT NULL DEFAULT 1,"
1901       "is_persistent INTEGER NOT NULL DEFAULT 1,"
1902       "priority INTEGER NOT NULL DEFAULT 1,"  // COOKIE_PRIORITY_DEFAULT
1903       "encrypted_value BLOB DEFAULT '',"
1904       "samesite INTEGER NOT NULL DEFAULT -1,"      // UNSPECIFIED
1905       "source_scheme INTEGER NOT NULL DEFAULT 0,"  // CookieSourceScheme::kUnset
1906       "source_port INTEGER NOT NULL DEFAULT -1,"   // UNKNOWN
1907       "is_same_party INTEGER NOT NULL DEFAULT 0,"
1908       "UNIQUE (host_key, name, path))";
1909   if (!db->Execute(kCreateSql))
1910     return false;
1911 
1912   return true;
1913 }
1914 
CreateV15Schema(sql::Database * db)1915 bool CreateV15Schema(sql::Database* db) {
1916   sql::MetaTable meta_table;
1917   if (!meta_table.Init(db, /* version = */ 13,
1918                        /* earliest compatible version = */ 13)) {
1919     return false;
1920   }
1921 
1922   // Version 13 schema
1923   static constexpr char kCreateSql[] =
1924       "CREATE TABLE cookies("
1925       "creation_utc INTEGER NOT NULL,"
1926       "top_frame_site_key TEXT NOT NULL,"
1927       "host_key TEXT NOT NULL,"
1928       "name TEXT NOT NULL,"
1929       "value TEXT NOT NULL,"
1930       "path TEXT NOT NULL,"
1931       "expires_utc INTEGER NOT NULL,"
1932       "is_secure INTEGER NOT NULL,"
1933       "is_httponly INTEGER NOT NULL,"
1934       "last_access_utc INTEGER NOT NULL,"
1935       "has_expires INTEGER NOT NULL DEFAULT 1,"
1936       "is_persistent INTEGER NOT NULL DEFAULT 1,"
1937       "priority INTEGER NOT NULL DEFAULT 1,"  // COOKIE_PRIORITY_DEFAULT
1938       "encrypted_value BLOB DEFAULT '',"
1939       "samesite INTEGER NOT NULL DEFAULT -1,"      // UNSPECIFIED
1940       "source_scheme INTEGER NOT NULL DEFAULT 0,"  // CookieSourceScheme::kUnset
1941       "source_port INTEGER NOT NULL DEFAULT -1,"   // UNKNOWN
1942       "is_same_party INTEGER NOT NULL DEFAULT 0,"
1943       "UNIQUE (top_frame_site_key, host_key, name, path))";
1944   if (!db->Execute(kCreateSql))
1945     return false;
1946 
1947   return true;
1948 }
1949 
1950 // crbug.com/1290841
CreateFaultyV16Schema(sql::Database * db)1951 bool CreateFaultyV16Schema(sql::Database* db) {
1952   sql::MetaTable meta_table;
1953   if (!meta_table.Init(db, /* version = */ 16,
1954                        /* earliest compatible version = */ 16)) {
1955     return false;
1956   }
1957 
1958   // Version 15 schema
1959   static constexpr char kCreateSql[] =
1960       "CREATE TABLE cookies("
1961       "creation_utc INTEGER NOT NULL,"
1962       "top_frame_site_key TEXT NOT NULL,"
1963       "host_key TEXT NOT NULL,"
1964       "name TEXT NOT NULL,"
1965       "value TEXT NOT NULL,"
1966       "path TEXT NOT NULL,"
1967       "expires_utc INTEGER NOT NULL,"
1968       "is_secure INTEGER NOT NULL,"
1969       "is_httponly INTEGER NOT NULL,"
1970       "last_access_utc INTEGER NOT NULL,"
1971       "has_expires INTEGER NOT NULL DEFAULT 1,"
1972       "is_persistent INTEGER NOT NULL DEFAULT 1,"
1973       "priority INTEGER NOT NULL DEFAULT 1,"  // COOKIE_PRIORITY_DEFAULT
1974       "encrypted_value BLOB DEFAULT '',"
1975       "samesite INTEGER NOT NULL DEFAULT -1,"      // UNSPECIFIED
1976       "source_scheme INTEGER NOT NULL DEFAULT 0,"  // CookieSourceScheme::kUnset
1977       "source_port INTEGER NOT NULL DEFAULT -1,"   // UNKNOWN
1978       "is_same_party INTEGER NOT NULL DEFAULT 0,"
1979       "UNIQUE (top_frame_site_key, host_key, name, path))";
1980   if (!db->Execute(kCreateSql))
1981     return false;
1982 
1983   return true;
1984 }
1985 
CreateV16Schema(sql::Database * db,int version_override=16)1986 bool CreateV16Schema(sql::Database* db, int version_override = 16) {
1987   sql::MetaTable meta_table;
1988   if (!meta_table.Init(db, /* version = */ version_override,
1989                        /* earliest compatible version = */ version_override)) {
1990     return false;
1991   }
1992 
1993   // Version 16 schema
1994   static constexpr char kCreateSql[] =
1995       "CREATE TABLE cookies("
1996       "creation_utc INTEGER NOT NULL,"
1997       "host_key TEXT NOT NULL,"
1998       "top_frame_site_key TEXT NOT NULL,"
1999       "name TEXT NOT NULL,"
2000       "value TEXT NOT NULL,"
2001       "encrypted_value BLOB NOT NULL,"
2002       "path TEXT NOT NULL,"
2003       "expires_utc INTEGER NOT NULL,"
2004       "is_secure INTEGER NOT NULL,"
2005       "is_httponly INTEGER NOT NULL,"
2006       "last_access_utc INTEGER NOT NULL,"
2007       "has_expires INTEGER NOT NULL,"
2008       "is_persistent INTEGER NOT NULL,"
2009       "priority INTEGER NOT NULL,"
2010       "samesite INTEGER NOT NULL,"
2011       "source_scheme INTEGER NOT NULL,"
2012       "source_port INTEGER NOT NULL,"
2013       "is_same_party INTEGER NOT NULL,"
2014       "UNIQUE (host_key, top_frame_site_key, name, path))";
2015 
2016   static constexpr char kCreateIndexSql[] =
2017       "CREATE UNIQUE INDEX cookies_unique_index "
2018       "ON cookies(host_key, top_frame_site_key, name, path)";
2019 
2020   if (!db->Execute(kCreateSql))
2021     return false;
2022 
2023   if (!db->Execute(kCreateIndexSql))
2024     return false;
2025 
2026   return true;
2027 }
2028 
CreateV17Schema(sql::Database * db)2029 bool CreateV17Schema(sql::Database* db) {
2030   // v17 fixes a bad migration to v16, so it's the same schema.
2031   return CreateV16Schema(db, /*version_override=*/17);
2032 }
2033 
GetDBCurrentVersionNumber(sql::Database * db)2034 int GetDBCurrentVersionNumber(sql::Database* db) {
2035   static constexpr char kGetDBCurrentVersionQuery[] =
2036       "SELECT value FROM meta WHERE key='version'";
2037   sql::Statement statement(db->GetUniqueStatement(kGetDBCurrentVersionQuery));
2038   statement.Step();
2039   return statement.ColumnInt(0);
2040 }
2041 
CookiesForMigrationTest()2042 std::vector<CanonicalCookie> CookiesForMigrationTest() {
2043   static base::Time now = base::Time::Now();
2044 
2045   std::vector<CanonicalCookie> cookies;
2046   // Note: These are all constructed with the default value of
2047   // is_source_scheme_secure, which is false, but that doesn't matter because
2048   // v11 doesn't store that info.
2049   // Some of these are constructed with SameParty set to true, to test that in
2050   // the DB migration, the is_same_party values are all defaulted to false.
2051   cookies.push_back(*CanonicalCookie::CreateUnsafeCookieForTesting(
2052       "A", "B", "example.com", "/", now, now, now, now, true /* secure */,
2053       false /* httponly */, CookieSameSite::UNSPECIFIED,
2054       COOKIE_PRIORITY_DEFAULT, false /* same_party */));
2055   cookies.push_back(*CanonicalCookie::CreateUnsafeCookieForTesting(
2056       "C", "B", "example.com", "/", now, now, now, now, true /* secure */,
2057       false /* httponly */, CookieSameSite::UNSPECIFIED,
2058       COOKIE_PRIORITY_DEFAULT, true /* same_party */));
2059   cookies.push_back(*CanonicalCookie::CreateUnsafeCookieForTesting(
2060       "A", "B", "example2.com", "/", now, now, now, now, true /* secure */,
2061       false /* httponly */, CookieSameSite::UNSPECIFIED,
2062       COOKIE_PRIORITY_DEFAULT, true /* same_party */));
2063   cookies.push_back(*CanonicalCookie::CreateUnsafeCookieForTesting(
2064       "C", "B", "example2.com", "/", now, now, now, now, false /* secure */,
2065       false /* httponly */, CookieSameSite::UNSPECIFIED,
2066       COOKIE_PRIORITY_DEFAULT, false /* same_party */));
2067   cookies.push_back(*CanonicalCookie::CreateUnsafeCookieForTesting(
2068       "A", "B", "example.com", "/path", now, now, now, now, false /* secure */,
2069       false /* httponly */, CookieSameSite::UNSPECIFIED,
2070       COOKIE_PRIORITY_DEFAULT, false /* same_party */));
2071   cookies.push_back(*CanonicalCookie::CreateUnsafeCookieForTesting(
2072       "C", "B", "example.com", "/path", now, now, now, now, false /* secure */,
2073       false /* httponly */, CookieSameSite::UNSPECIFIED,
2074       COOKIE_PRIORITY_DEFAULT, false /* same_party */));
2075   return cookies;
2076 }
2077 
AddV11CookiesToDB(sql::Database * db)2078 bool AddV11CookiesToDB(sql::Database* db) {
2079   std::vector<CanonicalCookie> cookies = CookiesForMigrationTest();
2080   sql::Statement statement(db->GetCachedStatement(
2081       SQL_FROM_HERE,
2082       "INSERT INTO cookies (creation_utc, host_key, name, value, "
2083       "encrypted_value, path, expires_utc, is_secure, is_httponly, "
2084       "samesite, last_access_utc, has_expires, is_persistent, priority)"
2085       "VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?)"));
2086   if (!statement.is_valid())
2087     return false;
2088   sql::Transaction transaction(db);
2089   if (!transaction.Begin())
2090     return false;
2091   for (const auto& cookie : cookies) {
2092     statement.Reset(true);
2093     statement.BindInt64(
2094         0, cookie.CreationDate().ToDeltaSinceWindowsEpoch().InMicroseconds());
2095     statement.BindString(1, cookie.Domain());
2096     statement.BindString(2, cookie.Name());
2097     statement.BindString(3, cookie.Value());
2098     statement.BindBlob(4, base::span<uint8_t>());  // encrypted_value
2099     statement.BindString(5, cookie.Path());
2100     statement.BindInt64(
2101         6, cookie.ExpiryDate().ToDeltaSinceWindowsEpoch().InMicroseconds());
2102     statement.BindInt(7, cookie.IsSecure());
2103     statement.BindInt(8, cookie.IsHttpOnly());
2104     // Note that this and Priority() below nominally rely on the enums in
2105     // sqlite_persistent_cookie_store.cc having the same values as the
2106     // ones in ../../cookies/cookie_constants.h.  But nothing in this test
2107     // relies on that equivalence, so it's not worth the hassle to guarantee
2108     // that.
2109     statement.BindInt(9, static_cast<int>(cookie.SameSite()));
2110     statement.BindInt64(
2111         10,
2112         cookie.LastAccessDate().ToDeltaSinceWindowsEpoch().InMicroseconds());
2113     statement.BindInt(11, cookie.IsPersistent());
2114     statement.BindInt(12, cookie.IsPersistent());
2115     statement.BindInt(13, static_cast<int>(cookie.Priority()));
2116     if (!statement.Run())
2117       return false;
2118   }
2119   if (!transaction.Commit())
2120     return false;
2121 
2122   return true;
2123 }
2124 
AddV12CookiesToDB(sql::Database * db)2125 bool AddV12CookiesToDB(sql::Database* db) {
2126   std::vector<CanonicalCookie> cookies = CookiesForMigrationTest();
2127   sql::Statement statement(db->GetCachedStatement(
2128       SQL_FROM_HERE,
2129       "INSERT INTO cookies (creation_utc, host_key, name, value, "
2130       "encrypted_value, path, expires_utc, is_secure, is_httponly, "
2131       "samesite, last_access_utc, has_expires, is_persistent, priority, "
2132       "source_scheme)"
2133       "VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)"));
2134   if (!statement.is_valid())
2135     return false;
2136   sql::Transaction transaction(db);
2137   if (!transaction.Begin())
2138     return false;
2139   for (const CanonicalCookie& cookie : cookies) {
2140     statement.Reset(true);
2141     statement.BindInt64(
2142         0, cookie.CreationDate().ToDeltaSinceWindowsEpoch().InMicroseconds());
2143     statement.BindString(1, cookie.Domain());
2144     statement.BindString(2, cookie.Name());
2145     statement.BindString(3, cookie.Value());
2146     statement.BindBlob(4, base::span<uint8_t>());  // encrypted_value
2147     statement.BindString(5, cookie.Path());
2148     statement.BindInt64(
2149         6, cookie.ExpiryDate().ToDeltaSinceWindowsEpoch().InMicroseconds());
2150     statement.BindInt(7, cookie.IsSecure());
2151     statement.BindInt(8, cookie.IsHttpOnly());
2152     // Note that this, Priority(), and SourceScheme() below nominally rely on
2153     // the enums in sqlite_persistent_cookie_store.cc having the same values as
2154     // the ones in ../../cookies/cookie_constants.h.  But nothing in this test
2155     // relies on that equivalence, so it's not worth the hassle to guarantee
2156     // that.
2157     statement.BindInt(9, static_cast<int>(cookie.SameSite()));
2158     statement.BindInt64(
2159         10,
2160         cookie.LastAccessDate().ToDeltaSinceWindowsEpoch().InMicroseconds());
2161     statement.BindInt(11, cookie.IsPersistent());
2162     statement.BindInt(12, cookie.IsPersistent());
2163     statement.BindInt(13, static_cast<int>(cookie.Priority()));
2164     statement.BindInt(14, static_cast<int>(cookie.SourceScheme()));
2165     if (!statement.Run())
2166       return false;
2167   }
2168   if (!transaction.Commit())
2169     return false;
2170 
2171   return true;
2172 }
2173 
AddV13CookiesToDB(sql::Database * db)2174 bool AddV13CookiesToDB(sql::Database* db) {
2175   std::vector<CanonicalCookie> cookies = CookiesForMigrationTest();
2176   sql::Statement statement(db->GetCachedStatement(
2177       SQL_FROM_HERE,
2178       "INSERT INTO cookies (creation_utc, host_key, name, value, "
2179       "encrypted_value, path, expires_utc, is_secure, is_httponly, "
2180       "samesite, last_access_utc, has_expires, is_persistent, priority, "
2181       "source_scheme, source_port, is_same_party)"
2182       "VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)"));
2183   if (!statement.is_valid())
2184     return false;
2185   sql::Transaction transaction(db);
2186   if (!transaction.Begin())
2187     return false;
2188   for (const CanonicalCookie& cookie : cookies) {
2189     statement.Reset(true);
2190     statement.BindInt64(
2191         0, cookie.CreationDate().ToDeltaSinceWindowsEpoch().InMicroseconds());
2192     statement.BindString(1, cookie.Domain());
2193     statement.BindString(2, cookie.Name());
2194     statement.BindString(3, cookie.Value());
2195     statement.BindBlob(4, base::span<uint8_t>());  // encrypted_value
2196     statement.BindString(5, cookie.Path());
2197     statement.BindInt64(
2198         6, cookie.ExpiryDate().ToDeltaSinceWindowsEpoch().InMicroseconds());
2199     statement.BindInt(7, cookie.IsSecure());
2200     statement.BindInt(8, cookie.IsHttpOnly());
2201     // Note that this, Priority(), and SourceScheme() below nominally rely on
2202     // the enums in sqlite_persistent_cookie_store.cc having the same values as
2203     // the ones in ../../cookies/cookie_constants.h.  But nothing in this test
2204     // relies on that equivalence, so it's not worth the hassle to guarantee
2205     // that.
2206     statement.BindInt(9, static_cast<int>(cookie.SameSite()));
2207     statement.BindInt64(
2208         10,
2209         cookie.LastAccessDate().ToDeltaSinceWindowsEpoch().InMicroseconds());
2210     statement.BindInt(11, cookie.IsPersistent());
2211     statement.BindInt(12, cookie.IsPersistent());
2212     statement.BindInt(13, static_cast<int>(cookie.Priority()));
2213     statement.BindInt(14, static_cast<int>(cookie.SourceScheme()));
2214     statement.BindInt(15, cookie.SourcePort());
2215     statement.BindInt(16, cookie.IsSameParty());
2216     if (!statement.Run())
2217       return false;
2218   }
2219   if (!transaction.Commit())
2220     return false;
2221 
2222   return true;
2223 }
2224 
AddV15CookiesToDB(sql::Database * db)2225 bool AddV15CookiesToDB(sql::Database* db) {
2226   std::vector<CanonicalCookie> cookies = CookiesForMigrationTest();
2227   sql::Statement statement(db->GetCachedStatement(
2228       SQL_FROM_HERE,
2229       "INSERT INTO cookies (creation_utc, top_frame_site_key, host_key, name, "
2230       "value, encrypted_value, path, expires_utc, is_secure, is_httponly, "
2231       "samesite, last_access_utc, has_expires, is_persistent, priority, "
2232       "source_scheme, source_port, is_same_party) "
2233       "VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)"));
2234   if (!statement.is_valid())
2235     return false;
2236   sql::Transaction transaction(db);
2237   if (!transaction.Begin())
2238     return false;
2239   for (const CanonicalCookie& cookie : cookies) {
2240     statement.Reset(true);
2241     statement.BindInt64(
2242         0, cookie.CreationDate().ToDeltaSinceWindowsEpoch().InMicroseconds());
2243     std::string top_frame_site_key;
2244     EXPECT_TRUE(CookiePartitionKey::Serialize(cookie.PartitionKey(),
2245                                               top_frame_site_key));
2246     statement.BindString(1, top_frame_site_key);
2247     statement.BindString(2, cookie.Domain());
2248     statement.BindString(3, cookie.Name());
2249     statement.BindString(4, cookie.Value());
2250     statement.BindBlob(5, base::span<uint8_t>());  // encrypted_value
2251     statement.BindString(6, cookie.Path());
2252     statement.BindInt64(
2253         7, cookie.ExpiryDate().ToDeltaSinceWindowsEpoch().InMicroseconds());
2254     statement.BindInt(8, cookie.IsSecure());
2255     statement.BindInt(9, cookie.IsHttpOnly());
2256     // Note that this, Priority(), and SourceScheme() below nominally rely on
2257     // the enums in sqlite_persistent_cookie_store.cc having the same values as
2258     // the ones in ../../cookies/cookie_constants.h.  But nothing in this test
2259     // relies on that equivalence, so it's not worth the hassle to guarantee
2260     // that.
2261     statement.BindInt(10, static_cast<int>(cookie.SameSite()));
2262     statement.BindInt64(
2263         11,
2264         cookie.LastAccessDate().ToDeltaSinceWindowsEpoch().InMicroseconds());
2265     statement.BindInt(12, cookie.IsPersistent());
2266     statement.BindInt(13, cookie.IsPersistent());
2267     statement.BindInt(14, static_cast<int>(cookie.Priority()));
2268     statement.BindInt(15, static_cast<int>(cookie.SourceScheme()));
2269     statement.BindInt(16, cookie.SourcePort());
2270     statement.BindInt(17, cookie.IsSameParty());
2271     if (!statement.Run())
2272       return false;
2273   }
2274   if (!transaction.Commit())
2275     return false;
2276 
2277   return true;
2278 }
2279 
AddV16CookiesToDB(sql::Database * db)2280 bool AddV16CookiesToDB(sql::Database* db) {
2281   // The difference between schemas is mainly the index.
2282   return AddV15CookiesToDB(db);
2283 }
2284 
AddV17CookiesToDB(sql::Database * db)2285 bool AddV17CookiesToDB(sql::Database* db) {
2286   // This version fixed a bad migration to v16.
2287   return AddV16CookiesToDB(db);
2288 }
2289 
2290 // Confirm the cookie list passed in has the above cookies in it.
ConfirmCookiesAfterMigrationTest(std::vector<std::unique_ptr<CanonicalCookie>> read_in_cookies,bool expect_same_party_cookies=false)2291 void ConfirmCookiesAfterMigrationTest(
2292     std::vector<std::unique_ptr<CanonicalCookie>> read_in_cookies,
2293     bool expect_same_party_cookies = false) {
2294   std::sort(read_in_cookies.begin(), read_in_cookies.end(), &CompareCookies);
2295   int i = 0;
2296   EXPECT_EQ("A", read_in_cookies[i]->Name());
2297   EXPECT_EQ("B", read_in_cookies[i]->Value());
2298   EXPECT_EQ("example.com", read_in_cookies[i]->Domain());
2299   EXPECT_EQ("/", read_in_cookies[i]->Path());
2300   EXPECT_TRUE(read_in_cookies[i]->IsSecure());
2301   EXPECT_EQ(CookieSourceScheme::kUnset, read_in_cookies[i]->SourceScheme());
2302   EXPECT_FALSE(read_in_cookies[i]->IsSameParty());
2303   EXPECT_TRUE(read_in_cookies[i]->LastUpdateDate().is_null());
2304 
2305   i++;
2306   EXPECT_EQ("A", read_in_cookies[i]->Name());
2307   EXPECT_EQ("B", read_in_cookies[i]->Value());
2308   EXPECT_EQ("example.com", read_in_cookies[i]->Domain());
2309   EXPECT_EQ("/path", read_in_cookies[i]->Path());
2310   EXPECT_FALSE(read_in_cookies[i]->IsSecure());
2311   EXPECT_EQ(CookieSourceScheme::kUnset, read_in_cookies[i]->SourceScheme());
2312   EXPECT_FALSE(read_in_cookies[i]->IsSameParty());
2313   EXPECT_TRUE(read_in_cookies[i]->LastUpdateDate().is_null());
2314 
2315   i++;
2316   EXPECT_EQ("A", read_in_cookies[i]->Name());
2317   EXPECT_EQ("B", read_in_cookies[i]->Value());
2318   EXPECT_EQ("example2.com", read_in_cookies[i]->Domain());
2319   EXPECT_EQ("/", read_in_cookies[i]->Path());
2320   EXPECT_TRUE(read_in_cookies[i]->IsSecure());
2321   EXPECT_EQ(CookieSourceScheme::kUnset, read_in_cookies[i]->SourceScheme());
2322   EXPECT_EQ(expect_same_party_cookies, read_in_cookies[i]->IsSameParty());
2323   EXPECT_TRUE(read_in_cookies[i]->LastUpdateDate().is_null());
2324 
2325   i++;
2326   EXPECT_EQ("C", read_in_cookies[i]->Name());
2327   EXPECT_EQ("B", read_in_cookies[i]->Value());
2328   EXPECT_EQ("example.com", read_in_cookies[i]->Domain());
2329   EXPECT_EQ("/", read_in_cookies[i]->Path());
2330   EXPECT_TRUE(read_in_cookies[i]->IsSecure());
2331   EXPECT_EQ(CookieSourceScheme::kUnset, read_in_cookies[i]->SourceScheme());
2332   EXPECT_EQ(expect_same_party_cookies, read_in_cookies[i]->IsSameParty());
2333   EXPECT_TRUE(read_in_cookies[i]->LastUpdateDate().is_null());
2334 
2335   i++;
2336   EXPECT_EQ("C", read_in_cookies[i]->Name());
2337   EXPECT_EQ("B", read_in_cookies[i]->Value());
2338   EXPECT_EQ("example.com", read_in_cookies[i]->Domain());
2339   EXPECT_EQ("/path", read_in_cookies[i]->Path());
2340   EXPECT_FALSE(read_in_cookies[i]->IsSecure());
2341   EXPECT_EQ(CookieSourceScheme::kUnset, read_in_cookies[i]->SourceScheme());
2342   EXPECT_FALSE(read_in_cookies[i]->IsSameParty());
2343   EXPECT_TRUE(read_in_cookies[i]->LastUpdateDate().is_null());
2344 
2345   i++;
2346   EXPECT_EQ("C", read_in_cookies[i]->Name());
2347   EXPECT_EQ("B", read_in_cookies[i]->Value());
2348   EXPECT_EQ("example2.com", read_in_cookies[i]->Domain());
2349   EXPECT_EQ("/", read_in_cookies[i]->Path());
2350   EXPECT_FALSE(read_in_cookies[i]->IsSecure());
2351   EXPECT_EQ(CookieSourceScheme::kUnset, read_in_cookies[i]->SourceScheme());
2352   EXPECT_FALSE(read_in_cookies[i]->IsSameParty());
2353   EXPECT_TRUE(read_in_cookies[i]->LastUpdateDate().is_null());
2354 }
2355 
2356 // Confirm that source_scheme gets added and is set to "Unset".
TEST_F(SQLitePersistentCookieStoreTest,UpgradeToSchemaVersion12)2357 TEST_F(SQLitePersistentCookieStoreTest, UpgradeToSchemaVersion12) {
2358   // Open db.
2359   sql::Database connection;
2360   ASSERT_TRUE(connection.Open(temp_dir_.GetPath().Append(kCookieFilename)));
2361   ASSERT_TRUE(CreateV11Schema(&connection));
2362   ASSERT_TRUE(AddV11CookiesToDB(&connection));
2363   connection.Close();
2364 
2365   std::vector<std::unique_ptr<CanonicalCookie>> read_in_cookies;
2366   CreateAndLoad(false, false, &read_in_cookies);
2367   ConfirmCookiesAfterMigrationTest(std::move(read_in_cookies));
2368 }
2369 
TEST_F(SQLitePersistentCookieStoreTest,UpgradeToSchemaVersion13)2370 TEST_F(SQLitePersistentCookieStoreTest, UpgradeToSchemaVersion13) {
2371   // Open db.
2372   sql::Database connection;
2373   ASSERT_TRUE(connection.Open(temp_dir_.GetPath().Append(kCookieFilename)));
2374   ASSERT_TRUE(CreateV12Schema(&connection));
2375   ASSERT_TRUE(AddV12CookiesToDB(&connection));
2376   connection.Close();
2377 
2378   std::vector<std::unique_ptr<CanonicalCookie>> read_in_cookies;
2379   CreateAndLoad(false, false, &read_in_cookies);
2380   ConfirmCookiesAfterMigrationTest(std::move(read_in_cookies));
2381 }
2382 
TEST_F(SQLitePersistentCookieStoreTest,UpgradeToSchemaVersion15)2383 TEST_F(SQLitePersistentCookieStoreTest, UpgradeToSchemaVersion15) {
2384   // Open db.
2385   sql::Database connection;
2386   ASSERT_TRUE(connection.Open(temp_dir_.GetPath().Append(kCookieFilename)));
2387   ASSERT_TRUE(CreateV13Schema(&connection));
2388   ASSERT_TRUE(AddV13CookiesToDB(&connection));
2389   connection.Close();
2390 
2391   std::vector<std::unique_ptr<CanonicalCookie>> read_in_cookies;
2392   CreateAndLoad(false, false, &read_in_cookies);
2393   ConfirmCookiesAfterMigrationTest(std::move(read_in_cookies), true);
2394 }
2395 
TEST_F(SQLitePersistentCookieStoreTest,UpgradeToSchemaVersion16)2396 TEST_F(SQLitePersistentCookieStoreTest, UpgradeToSchemaVersion16) {
2397   // Open db.
2398   sql::Database connection;
2399   ASSERT_TRUE(connection.Open(temp_dir_.GetPath().Append(kCookieFilename)));
2400   ASSERT_TRUE(CreateV15Schema(&connection));
2401   ASSERT_TRUE(AddV15CookiesToDB(&connection));
2402   connection.Close();
2403 
2404   std::vector<std::unique_ptr<CanonicalCookie>> read_in_cookies;
2405   CreateAndLoad(false, false, &read_in_cookies);
2406   ConfirmCookiesAfterMigrationTest(std::move(read_in_cookies), true);
2407 }
2408 
TEST_F(SQLitePersistentCookieStoreTest,UpgradeToSchemaVersion17)2409 TEST_F(SQLitePersistentCookieStoreTest, UpgradeToSchemaVersion17) {
2410   // Open db.
2411   sql::Database connection;
2412   ASSERT_TRUE(connection.Open(temp_dir_.GetPath().Append(kCookieFilename)));
2413   ASSERT_TRUE(CreateV16Schema(&connection));
2414   ASSERT_EQ(GetDBCurrentVersionNumber(&connection), 16);
2415   ASSERT_TRUE(AddV16CookiesToDB(&connection));
2416 
2417   std::vector<std::unique_ptr<CanonicalCookie>> read_in_cookies;
2418   CreateAndLoad(false, false, &read_in_cookies);
2419   ConfirmCookiesAfterMigrationTest(std::move(read_in_cookies), true);
2420   ASSERT_GE(GetDBCurrentVersionNumber(&connection), 17);
2421   connection.Close();
2422 }
2423 
2424 // Testing bug: 1290841
TEST_F(SQLitePersistentCookieStoreTest,UpgradeToSchemaVersion17FromFaultyV16)2425 TEST_F(SQLitePersistentCookieStoreTest, UpgradeToSchemaVersion17FromFaultyV16) {
2426   // Open db.
2427   sql::Database connection;
2428   ASSERT_TRUE(connection.Open(temp_dir_.GetPath().Append(kCookieFilename)));
2429   ASSERT_TRUE(CreateFaultyV16Schema(&connection));
2430   ASSERT_EQ(GetDBCurrentVersionNumber(&connection), 16);
2431   ASSERT_TRUE(
2432       AddV15CookiesToDB(&connection));  // Intentional, this is part of the bug
2433 
2434   std::vector<std::unique_ptr<CanonicalCookie>> read_in_cookies;
2435   CreateAndLoad(false, false, &read_in_cookies);
2436   ConfirmCookiesAfterMigrationTest(std::move(read_in_cookies), true);
2437   ASSERT_GE(GetDBCurrentVersionNumber(&connection), 17);
2438   connection.Close();
2439 }
2440 
TEST_F(SQLitePersistentCookieStoreTest,UpgradeToSchemaVersion18)2441 TEST_F(SQLitePersistentCookieStoreTest, UpgradeToSchemaVersion18) {
2442   // Open db.
2443   sql::Database connection;
2444   ASSERT_TRUE(connection.Open(temp_dir_.GetPath().Append(kCookieFilename)));
2445   ASSERT_TRUE(CreateV17Schema(&connection));
2446   ASSERT_EQ(GetDBCurrentVersionNumber(&connection), 17);
2447   ASSERT_TRUE(AddV17CookiesToDB(&connection));
2448 
2449   std::vector<std::unique_ptr<CanonicalCookie>> read_in_cookies;
2450   CreateAndLoad(false, false, &read_in_cookies);
2451   ConfirmCookiesAfterMigrationTest(std::move(read_in_cookies), true);
2452   ASSERT_GE(GetDBCurrentVersionNumber(&connection), 18);
2453   connection.Close();
2454 }
2455 
2456 class PartitionedCookiesSQLitePersistentCookieStoreTest
2457     : public SQLitePersistentCookieStoreTest,
2458       public testing::WithParamInterface<bool> {
2459  protected:
2460   // testing::Test
SetUp()2461   void SetUp() override {
2462     scoped_feature_list_.InitWithFeatureState(features::kPartitionedCookies,
2463                                               PartitionedCookiesEnabled());
2464     SQLitePersistentCookieStoreTest::SetUp();
2465   }
2466 
PartitionedCookiesEnabled()2467   bool PartitionedCookiesEnabled() { return GetParam(); }
2468 
2469  private:
2470   base::test::ScopedFeatureList scoped_feature_list_;
2471 };
2472 
2473 INSTANTIATE_TEST_SUITE_P(/* no label */,
2474                          PartitionedCookiesSQLitePersistentCookieStoreTest,
2475                          testing::Bool());
2476 
TEST_P(PartitionedCookiesSQLitePersistentCookieStoreTest,SavingPartitionedCookies)2477 TEST_P(PartitionedCookiesSQLitePersistentCookieStoreTest,
2478        SavingPartitionedCookies) {
2479   InitializeStore(false, false);
2480 
2481   store_->AddCookie(*CanonicalCookie::CreateUnsafeCookieForTesting(
2482       "__Host-foo", "bar", GURL("https://example.com/").host(), "/",
2483       base::Time::Now(), base::Time::Now() + base::Days(1), base::Time::Now(),
2484       base::Time::Now(), true /* secure */, false /* httponly */,
2485       CookieSameSite::UNSPECIFIED, COOKIE_PRIORITY_DEFAULT,
2486       false /* sameparty */,
2487       CookiePartitionKey::FromURLForTesting(GURL("https://toplevelsite.com"))));
2488   Flush();
2489 
2490   std::string got_db_content(ReadRawDBContents());
2491   EXPECT_EQ(PartitionedCookiesEnabled(),
2492             got_db_content.find("__Host-foo") != std::string::npos);
2493 
2494   DestroyStore();
2495 }
2496 
TEST_P(PartitionedCookiesSQLitePersistentCookieStoreTest,LoadingPartitionedCookies)2497 TEST_P(PartitionedCookiesSQLitePersistentCookieStoreTest,
2498        LoadingPartitionedCookies) {
2499   InitializeStore(false, false);
2500   DestroyStore();
2501 
2502   // Insert a partitioned cookie into the database manually.
2503   base::FilePath store_name(temp_dir_.GetPath().Append(kCookieFilename));
2504   std::unique_ptr<sql::Database> db(std::make_unique<sql::Database>());
2505   ASSERT_TRUE(db->Open(store_name));
2506 
2507   sql::Statement stmt(db->GetUniqueStatement(
2508       "INSERT INTO cookies (creation_utc, host_key, top_frame_site_key, name, "
2509       "value, encrypted_value, path, expires_utc, is_secure, is_httponly, "
2510       "samesite, last_access_utc, has_expires, is_persistent, priority, "
2511       "source_scheme, source_port, is_same_party, last_update_utc) "
2512       "VALUES (?,?,?,?,?,'',?,?,1,0,0,?,1,1,0,?,?,0,?)"));
2513   ASSERT_TRUE(stmt.is_valid());
2514 
2515   base::Time creation(base::Time::Now());
2516   base::Time expiration(creation + base::Days(1));
2517   base::Time last_access(base::Time::Now());
2518   base::Time last_update(base::Time::Now());
2519 
2520   stmt.BindTime(0, creation);
2521   stmt.BindString(1, GURL("https://www.example.com/").host());
2522   stmt.BindString(2, "https://toplevelsite.com");
2523   stmt.BindString(3, "__Host-foo");
2524   stmt.BindString(4, "bar");
2525   stmt.BindString(5, "/");
2526   stmt.BindTime(6, expiration);
2527   stmt.BindTime(7, last_access);
2528   stmt.BindInt(8, static_cast<int>(CookieSourceScheme::kUnset));
2529   stmt.BindInt(9, SQLitePersistentCookieStore::kDefaultUnknownPort);
2530   stmt.BindTime(10, last_update);
2531   ASSERT_TRUE(stmt.Run());
2532   stmt.Clear();
2533 
2534   CanonicalCookieVector cookies;
2535   CreateAndLoad(false, false, &cookies);
2536 
2537   if (PartitionedCookiesEnabled()) {
2538     EXPECT_EQ(1u, cookies.size());
2539     auto cc = std::move(cookies[0]);
2540     EXPECT_EQ("__Host-foo", cc->Name());
2541     EXPECT_EQ("bar", cc->Value());
2542     EXPECT_EQ(GURL("https://www.example.com/").host(), cc->Domain());
2543     EXPECT_TRUE(cc->IsPartitioned());
2544     EXPECT_EQ(
2545         CookiePartitionKey::FromURLForTesting(GURL("https://toplevelsite.com")),
2546         cc->PartitionKey());
2547     EXPECT_EQ(last_update, cc->LastUpdateDate());
2548   } else {
2549     EXPECT_EQ(0u, cookies.size());
2550     // If Partitioned cookies are disabled, then we should delete any
2551     // Partitioned cookie we tried to load.
2552     std::string db_content(ReadRawDBContents());
2553     EXPECT_EQ(db_content.find("__Host-foo"), std::string::npos);
2554   }
2555 }
2556 
2557 }  // namespace net
2558