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