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