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