1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "net/extras/sqlite/sqlite_persistent_cookie_store.h"
10 #include "base/bind.h"
11 #include "base/callback.h"
12 #include "base/files/file_util.h"
13 #include "base/files/scoped_temp_dir.h"
14 #include "base/location.h"
15 #include "base/memory/ref_counted.h"
16 #include "base/sequenced_task_runner.h"
17 #include "base/stl_util.h"
18 #include "base/synchronization/waitable_event.h"
19 #include "base/test/sequenced_worker_pool_owner.h"
20 #include "base/threading/sequenced_worker_pool.h"
21 #include "base/time/time.h"
22 #include "crypto/encryptor.h"
23 #include "crypto/symmetric_key.h"
24 #include "net/cookies/canonical_cookie.h"
25 #include "net/cookies/cookie_constants.h"
26 #include "net/extras/sqlite/cookie_crypto_delegate.h"
27 #include "sql/connection.h"
28 #include "sql/meta_table.h"
29 #include "sql/statement.h"
30 #include "testing/gtest/include/gtest/gtest.h"
37 const base::FilePath::CharType kCookieFilename
[] = FILE_PATH_LITERAL("Cookies");
39 class CookieCryptor
: public CookieCryptoDelegate
{
42 bool EncryptString(const std::string
& plaintext
,
43 std::string
* ciphertext
) override
;
44 bool DecryptString(const std::string
& ciphertext
,
45 std::string
* plaintext
) override
;
48 scoped_ptr
<crypto::SymmetricKey
> key_
;
49 crypto::Encryptor encryptor_
;
52 CookieCryptor::CookieCryptor()
54 crypto::SymmetricKey::DeriveKeyFromPassword(crypto::SymmetricKey::AES
,
59 std::string
iv("the iv: 16 bytes");
60 encryptor_
.Init(key_
.get(), crypto::Encryptor::CBC
, iv
);
63 bool CookieCryptor::EncryptString(const std::string
& plaintext
,
64 std::string
* ciphertext
) {
65 return encryptor_
.Encrypt(plaintext
, ciphertext
);
68 bool CookieCryptor::DecryptString(const std::string
& ciphertext
,
69 std::string
* plaintext
) {
70 return encryptor_
.Decrypt(ciphertext
, plaintext
);
75 typedef std::vector
<CanonicalCookie
*> CanonicalCookieVector
;
77 class SQLitePersistentCookieStoreTest
: public testing::Test
{
79 SQLitePersistentCookieStoreTest()
80 : pool_owner_(new base::SequencedWorkerPoolOwner(3, "Background Pool")),
81 loaded_event_(false, false),
82 key_loaded_event_(false, false),
83 db_thread_event_(false, false) {}
85 void OnLoaded(const CanonicalCookieVector
& cookies
) {
87 loaded_event_
.Signal();
90 void OnKeyLoaded(const CanonicalCookieVector
& cookies
) {
92 key_loaded_event_
.Signal();
95 void Load(CanonicalCookieVector
* cookies
) {
96 EXPECT_FALSE(loaded_event_
.IsSignaled());
97 store_
->Load(base::Bind(&SQLitePersistentCookieStoreTest::OnLoaded
,
98 base::Unretained(this)));
104 base::WaitableEvent
event(false, false);
106 base::Bind(&base::WaitableEvent::Signal
, base::Unretained(&event
)));
110 scoped_refptr
<base::SequencedTaskRunner
> background_task_runner() {
111 return pool_owner_
->pool()->GetSequencedTaskRunner(
112 pool_owner_
->pool()->GetNamedSequenceToken("background"));
115 scoped_refptr
<base::SequencedTaskRunner
> client_task_runner() {
116 return pool_owner_
->pool()->GetSequencedTaskRunner(
117 pool_owner_
->pool()->GetNamedSequenceToken("client"));
120 void DestroyStore() {
122 // Make sure we wait until the destructor has run by shutting down the pool
123 // resetting the owner (whose destructor blocks on the pool completion).
124 pool_owner_
->pool()->Shutdown();
125 // Create a new pool for the few tests that create multiple stores. In other
126 // cases this is wasted but harmless.
127 pool_owner_
.reset(new base::SequencedWorkerPoolOwner(3, "Background Pool"));
130 void Create(bool crypt_cookies
, bool restore_old_session_cookies
) {
132 cookie_crypto_delegate_
.reset(new CookieCryptor());
134 store_
= new SQLitePersistentCookieStore(
135 temp_dir_
.path().Append(kCookieFilename
), client_task_runner(),
136 background_task_runner(), restore_old_session_cookies
,
137 cookie_crypto_delegate_
.get());
140 void CreateAndLoad(bool crypt_cookies
,
141 bool restore_old_session_cookies
,
142 CanonicalCookieVector
* cookies
) {
143 Create(crypt_cookies
, restore_old_session_cookies
);
147 void InitializeStore(bool crypt
, bool restore_old_session_cookies
) {
148 CanonicalCookieVector cookies
;
149 CreateAndLoad(crypt
, restore_old_session_cookies
, &cookies
);
150 EXPECT_EQ(0U, cookies
.size());
153 // We have to create this method to wrap WaitableEvent::Wait, since we cannot
154 // bind a non-void returning method as a Closure.
155 void WaitOnDBEvent() { db_thread_event_
.Wait(); }
157 // Adds a persistent cookie to store_.
158 void AddCookie(const std::string
& name
,
159 const std::string
& value
,
160 const std::string
& domain
,
161 const std::string
& path
,
162 const base::Time
& creation
) {
163 store_
->AddCookie(CanonicalCookie(GURL(), name
, value
, domain
, path
,
164 creation
, creation
, creation
, false,
165 false, false, COOKIE_PRIORITY_DEFAULT
));
168 void AddCookieWithExpiration(const std::string
& name
,
169 const std::string
& value
,
170 const std::string
& domain
,
171 const std::string
& path
,
172 const base::Time
& creation
,
173 const base::Time
& expiration
) {
174 store_
->AddCookie(CanonicalCookie(GURL(), name
, value
, domain
, path
,
175 creation
, expiration
, creation
, false,
176 false, false, COOKIE_PRIORITY_DEFAULT
));
179 std::string
ReadRawDBContents() {
180 std::string contents
;
181 if (!base::ReadFileToString(temp_dir_
.path().Append(kCookieFilename
),
183 return std::string();
187 void SetUp() override
{ ASSERT_TRUE(temp_dir_
.CreateUniqueTempDir()); }
189 void TearDown() override
{
191 pool_owner_
->pool()->Shutdown();
195 scoped_ptr
<base::SequencedWorkerPoolOwner
> pool_owner_
;
196 base::WaitableEvent loaded_event_
;
197 base::WaitableEvent key_loaded_event_
;
198 base::WaitableEvent db_thread_event_
;
199 CanonicalCookieVector cookies_
;
200 base::ScopedTempDir temp_dir_
;
201 scoped_refptr
<SQLitePersistentCookieStore
> store_
;
202 scoped_ptr
<CookieCryptoDelegate
> cookie_crypto_delegate_
;
205 TEST_F(SQLitePersistentCookieStoreTest
, TestInvalidMetaTableRecovery
) {
206 InitializeStore(false, false);
207 AddCookie("A", "B", "foo.bar", "/", base::Time::Now());
210 // Load up the store and verify that it has good data in it.
211 CanonicalCookieVector cookies
;
212 CreateAndLoad(false, false, &cookies
);
213 ASSERT_EQ(1U, cookies
.size());
214 ASSERT_STREQ("foo.bar", cookies
[0]->Domain().c_str());
215 ASSERT_STREQ("A", cookies
[0]->Name().c_str());
216 ASSERT_STREQ("B", cookies
[0]->Value().c_str());
218 STLDeleteElements(&cookies
);
220 // Now corrupt the meta table.
223 ASSERT_TRUE(db
.Open(temp_dir_
.path().Append(kCookieFilename
)));
224 sql::MetaTable meta_table_
;
225 meta_table_
.Init(&db
, 1, 1);
226 ASSERT_TRUE(db
.Execute("DELETE FROM meta"));
230 // Upon loading, the database should be reset to a good, blank state.
231 CreateAndLoad(false, false, &cookies
);
232 ASSERT_EQ(0U, cookies
.size());
234 // Verify that, after, recovery, the database persists properly.
235 AddCookie("X", "Y", "foo.bar", "/", base::Time::Now());
237 CreateAndLoad(false, false, &cookies
);
238 ASSERT_EQ(1U, cookies
.size());
239 ASSERT_STREQ("foo.bar", cookies
[0]->Domain().c_str());
240 ASSERT_STREQ("X", cookies
[0]->Name().c_str());
241 ASSERT_STREQ("Y", cookies
[0]->Value().c_str());
242 STLDeleteElements(&cookies
);
245 // Test if data is stored as expected in the SQLite database.
246 TEST_F(SQLitePersistentCookieStoreTest
, TestPersistance
) {
247 InitializeStore(false, false);
248 AddCookie("A", "B", "foo.bar", "/", base::Time::Now());
249 // Replace the store effectively destroying the current one and forcing it
250 // to write its data to disk. Then we can see if after loading it again it
253 // Reload and test for persistence
254 CanonicalCookieVector cookies
;
255 CreateAndLoad(false, false, &cookies
);
256 ASSERT_EQ(1U, cookies
.size());
257 ASSERT_STREQ("foo.bar", cookies
[0]->Domain().c_str());
258 ASSERT_STREQ("A", cookies
[0]->Name().c_str());
259 ASSERT_STREQ("B", cookies
[0]->Value().c_str());
261 // Now delete the cookie and check persistence again.
262 store_
->DeleteCookie(*cookies
[0]);
264 STLDeleteElements(&cookies
);
266 // Reload and check if the cookie has been removed.
267 CreateAndLoad(false, false, &cookies
);
268 ASSERT_EQ(0U, cookies
.size());
271 TEST_F(SQLitePersistentCookieStoreTest
, TestSessionCookiesDeletedOnStartup
) {
272 // Initialize the cookie store with 3 persistent cookies, 5 transient
274 InitializeStore(false, false);
276 // Add persistent cookies.
277 base::Time t
= base::Time::Now();
278 AddCookie("A", "B", "a1.com", "/", t
);
279 t
+= base::TimeDelta::FromInternalValue(10);
280 AddCookie("A", "B", "a2.com", "/", t
);
281 t
+= base::TimeDelta::FromInternalValue(10);
282 AddCookie("A", "B", "a3.com", "/", t
);
284 // Add transient cookies.
285 t
+= base::TimeDelta::FromInternalValue(10);
286 AddCookieWithExpiration("A", "B", "b1.com", "/", t
, base::Time());
287 t
+= base::TimeDelta::FromInternalValue(10);
288 AddCookieWithExpiration("A", "B", "b2.com", "/", t
, base::Time());
289 t
+= base::TimeDelta::FromInternalValue(10);
290 AddCookieWithExpiration("A", "B", "b3.com", "/", t
, base::Time());
291 t
+= base::TimeDelta::FromInternalValue(10);
292 AddCookieWithExpiration("A", "B", "b4.com", "/", t
, base::Time());
293 t
+= base::TimeDelta::FromInternalValue(10);
294 AddCookieWithExpiration("A", "B", "b5.com", "/", t
, base::Time());
297 // Load the store a second time. Before the store finishes loading, add a
298 // transient cookie and flush it to disk.
299 store_
= new SQLitePersistentCookieStore(
300 temp_dir_
.path().Append(kCookieFilename
), client_task_runner(),
301 background_task_runner(), false, nullptr);
303 // Posting a blocking task to db_thread_ makes sure that the DB thread waits
304 // until both Load and Flush have been posted to its task queue.
305 background_task_runner()->PostTask(
306 FROM_HERE
, base::Bind(&SQLitePersistentCookieStoreTest::WaitOnDBEvent
,
307 base::Unretained(this)));
308 store_
->Load(base::Bind(&SQLitePersistentCookieStoreTest::OnLoaded
,
309 base::Unretained(this)));
310 t
+= base::TimeDelta::FromInternalValue(10);
311 AddCookieWithExpiration("A", "B", "c.com", "/", t
, base::Time());
312 base::WaitableEvent
event(false, false);
314 base::Bind(&base::WaitableEvent::Signal
, base::Unretained(&event
)));
316 // Now the DB-thread queue contains:
318 // 1. Wait (on db_event)
320 // 2. "Init And Chain-Load First Domain"
321 // 3. Add Cookie (c.com)
322 // 4. Flush Cookie (c.com)
323 db_thread_event_
.Signal();
325 loaded_event_
.Wait();
326 STLDeleteElements(&cookies_
);
329 // Load the store a third time, this time restoring session cookies. The
330 // store should contain exactly 4 cookies: the 3 persistent, and "c.com",
331 // which was added during the second cookie store load.
332 store_
= new SQLitePersistentCookieStore(
333 temp_dir_
.path().Append(kCookieFilename
), client_task_runner(),
334 background_task_runner(), true, nullptr);
335 store_
->Load(base::Bind(&SQLitePersistentCookieStoreTest::OnLoaded
,
336 base::Unretained(this)));
337 loaded_event_
.Wait();
338 ASSERT_EQ(4u, cookies_
.size());
339 STLDeleteElements(&cookies_
);
342 // Test that priority load of cookies for a specfic domain key could be
343 // completed before the entire store is loaded
344 TEST_F(SQLitePersistentCookieStoreTest
, TestLoadCookiesForKey
) {
345 InitializeStore(false, false);
346 base::Time t
= base::Time::Now();
347 AddCookie("A", "B", "foo.bar", "/", t
);
348 t
+= base::TimeDelta::FromInternalValue(10);
349 AddCookie("A", "B", "www.aaa.com", "/", t
);
350 t
+= base::TimeDelta::FromInternalValue(10);
351 AddCookie("A", "B", "travel.aaa.com", "/", t
);
352 t
+= base::TimeDelta::FromInternalValue(10);
353 AddCookie("A", "B", "www.bbb.com", "/", t
);
356 store_
= new SQLitePersistentCookieStore(
357 temp_dir_
.path().Append(kCookieFilename
), client_task_runner(),
358 background_task_runner(), false, nullptr);
360 // Posting a blocking task to db_thread_ makes sure that the DB thread waits
361 // until both Load and LoadCookiesForKey have been posted to its task queue.
362 background_task_runner()->PostTask(
363 FROM_HERE
, base::Bind(&SQLitePersistentCookieStoreTest::WaitOnDBEvent
,
364 base::Unretained(this)));
365 store_
->Load(base::Bind(&SQLitePersistentCookieStoreTest::OnLoaded
,
366 base::Unretained(this)));
367 store_
->LoadCookiesForKey(
368 "aaa.com", base::Bind(&SQLitePersistentCookieStoreTest::OnKeyLoaded
,
369 base::Unretained(this)));
370 background_task_runner()->PostTask(
371 FROM_HERE
, base::Bind(&SQLitePersistentCookieStoreTest::WaitOnDBEvent
,
372 base::Unretained(this)));
374 // Now the DB-thread queue contains:
376 // 1. Wait (on db_event)
378 // 2. "Init And Chain-Load First Domain"
379 // 3. Priority Load (aaa.com)
380 // 4. Wait (on db_event)
381 db_thread_event_
.Signal();
382 key_loaded_event_
.Wait();
383 ASSERT_EQ(loaded_event_
.IsSignaled(), false);
384 std::set
<std::string
> cookies_loaded
;
385 for (CanonicalCookieVector::const_iterator it
= cookies_
.begin();
386 it
!= cookies_
.end(); ++it
) {
387 cookies_loaded
.insert((*it
)->Domain().c_str());
389 STLDeleteElements(&cookies_
);
390 ASSERT_GT(4U, cookies_loaded
.size());
391 ASSERT_EQ(true, cookies_loaded
.find("www.aaa.com") != cookies_loaded
.end());
393 cookies_loaded
.find("travel.aaa.com") != cookies_loaded
.end());
395 db_thread_event_
.Signal();
396 loaded_event_
.Wait();
397 for (CanonicalCookieVector::const_iterator it
= cookies_
.begin();
398 it
!= cookies_
.end(); ++it
) {
399 cookies_loaded
.insert((*it
)->Domain().c_str());
401 ASSERT_EQ(4U, cookies_loaded
.size());
402 ASSERT_EQ(cookies_loaded
.find("foo.bar") != cookies_loaded
.end(), true);
403 ASSERT_EQ(cookies_loaded
.find("www.bbb.com") != cookies_loaded
.end(), true);
404 STLDeleteElements(&cookies_
);
407 // Test that we can force the database to be written by calling Flush().
408 TEST_F(SQLitePersistentCookieStoreTest
, TestFlush
) {
409 InitializeStore(false, false);
410 // File timestamps don't work well on all platforms, so we'll determine
411 // whether the DB file has been modified by checking its size.
412 base::FilePath path
= temp_dir_
.path().Append(kCookieFilename
);
413 base::File::Info info
;
414 ASSERT_TRUE(base::GetFileInfo(path
, &info
));
415 int64 base_size
= info
.size
;
417 // Write some large cookies, so the DB will have to expand by several KB.
418 for (char c
= 'a'; c
< 'z'; ++c
) {
419 // Each cookie needs a unique timestamp for creation_utc (see DB schema).
420 base::Time t
= base::Time::Now() + base::TimeDelta::FromMicroseconds(c
);
421 std::string
name(1, c
);
422 std::string
value(1000, c
);
423 AddCookie(name
, value
, "foo.bar", "/", t
);
428 // We forced a write, so now the file will be bigger.
429 ASSERT_TRUE(base::GetFileInfo(path
, &info
));
430 ASSERT_GT(info
.size
, base_size
);
433 // Test loading old session cookies from the disk.
434 TEST_F(SQLitePersistentCookieStoreTest
, TestLoadOldSessionCookies
) {
435 InitializeStore(false, true);
437 // Add a session cookie.
438 store_
->AddCookie(CanonicalCookie(GURL(), "C", "D", "sessioncookie.com", "/",
439 base::Time::Now(), base::Time(),
440 base::Time::Now(), false, false, false,
441 COOKIE_PRIORITY_DEFAULT
));
443 // Force the store to write its data to the disk.
446 // Create a store that loads session cookies and test that the session cookie
448 CanonicalCookieVector cookies
;
449 CreateAndLoad(false, true, &cookies
);
451 ASSERT_EQ(1U, cookies
.size());
452 ASSERT_STREQ("sessioncookie.com", cookies
[0]->Domain().c_str());
453 ASSERT_STREQ("C", cookies
[0]->Name().c_str());
454 ASSERT_STREQ("D", cookies
[0]->Value().c_str());
455 ASSERT_EQ(COOKIE_PRIORITY_DEFAULT
, cookies
[0]->Priority());
457 STLDeleteElements(&cookies
);
460 // Test loading old session cookies from the disk.
461 TEST_F(SQLitePersistentCookieStoreTest
, TestDontLoadOldSessionCookies
) {
462 InitializeStore(false, true);
464 // Add a session cookie.
465 store_
->AddCookie(CanonicalCookie(GURL(), "C", "D", "sessioncookie.com", "/",
466 base::Time::Now(), base::Time(),
467 base::Time::Now(), false, false, false,
468 COOKIE_PRIORITY_DEFAULT
));
470 // Force the store to write its data to the disk.
473 // Create a store that doesn't load old session cookies and test that the
474 // session cookie was not loaded.
475 CanonicalCookieVector cookies
;
476 CreateAndLoad(false, false, &cookies
);
477 ASSERT_EQ(0U, cookies
.size());
479 // The store should also delete the session cookie. Wait until that has been
483 // Create a store that loads old session cookies and test that the session
485 CreateAndLoad(false, true, &cookies
);
486 ASSERT_EQ(0U, cookies
.size());
489 TEST_F(SQLitePersistentCookieStoreTest
, PersistIsPersistent
) {
490 InitializeStore(false, true);
491 static const char kSessionName
[] = "session";
492 static const char kPersistentName
[] = "persistent";
494 // Add a session cookie.
495 store_
->AddCookie(CanonicalCookie(GURL(), kSessionName
, "val",
496 "sessioncookie.com", "/", base::Time::Now(),
497 base::Time(), base::Time::Now(), false,
498 false, false, COOKIE_PRIORITY_DEFAULT
));
499 // Add a persistent cookie.
500 store_
->AddCookie(CanonicalCookie(
501 GURL(), kPersistentName
, "val", "sessioncookie.com", "/",
502 base::Time::Now() - base::TimeDelta::FromDays(1),
503 base::Time::Now() + base::TimeDelta::FromDays(1), base::Time::Now(),
504 false, false, false, COOKIE_PRIORITY_DEFAULT
));
506 // Force the store to write its data to the disk.
509 // Create a store that loads session cookie and test that the IsPersistent
510 // attribute is restored.
511 CanonicalCookieVector cookies
;
512 CreateAndLoad(false, true, &cookies
);
513 ASSERT_EQ(2U, cookies
.size());
515 std::map
<std::string
, CanonicalCookie
*> cookie_map
;
516 for (CanonicalCookieVector::const_iterator it
= cookies
.begin();
517 it
!= cookies
.end(); ++it
) {
518 cookie_map
[(*it
)->Name()] = *it
;
521 std::map
<std::string
, CanonicalCookie
*>::const_iterator it
=
522 cookie_map
.find(kSessionName
);
523 ASSERT_TRUE(it
!= cookie_map
.end());
524 EXPECT_FALSE(cookie_map
[kSessionName
]->IsPersistent());
526 it
= cookie_map
.find(kPersistentName
);
527 ASSERT_TRUE(it
!= cookie_map
.end());
528 EXPECT_TRUE(cookie_map
[kPersistentName
]->IsPersistent());
530 STLDeleteElements(&cookies
);
533 TEST_F(SQLitePersistentCookieStoreTest
, PriorityIsPersistent
) {
534 static const char kLowName
[] = "low";
535 static const char kMediumName
[] = "medium";
536 static const char kHighName
[] = "high";
537 static const char kCookieDomain
[] = "sessioncookie.com";
538 static const char kCookieValue
[] = "value";
539 static const char kCookiePath
[] = "/";
541 InitializeStore(false, true);
543 // Add a low-priority persistent cookie.
544 store_
->AddCookie(CanonicalCookie(
545 GURL(), kLowName
, kCookieValue
, kCookieDomain
, kCookiePath
,
546 base::Time::Now() - base::TimeDelta::FromMinutes(1),
547 base::Time::Now() + base::TimeDelta::FromDays(1), base::Time::Now(),
548 false, false, false, COOKIE_PRIORITY_LOW
));
550 // Add a medium-priority persistent cookie.
551 store_
->AddCookie(CanonicalCookie(
552 GURL(), kMediumName
, kCookieValue
, kCookieDomain
, kCookiePath
,
553 base::Time::Now() - base::TimeDelta::FromMinutes(2),
554 base::Time::Now() + base::TimeDelta::FromDays(1), base::Time::Now(),
555 false, false, false, COOKIE_PRIORITY_MEDIUM
));
557 // Add a high-priority peristent cookie.
558 store_
->AddCookie(CanonicalCookie(
559 GURL(), kHighName
, kCookieValue
, kCookieDomain
, kCookiePath
,
560 base::Time::Now() - base::TimeDelta::FromMinutes(3),
561 base::Time::Now() + base::TimeDelta::FromDays(1), base::Time::Now(),
562 false, false, false, COOKIE_PRIORITY_HIGH
));
564 // Force the store to write its data to the disk.
567 // Create a store that loads session cookie and test that the priority
568 // attribute values are restored.
569 CanonicalCookieVector cookies
;
570 CreateAndLoad(false, true, &cookies
);
571 ASSERT_EQ(3U, cookies
.size());
573 // Put the cookies into a map, by name, so we can easily find them.
574 std::map
<std::string
, CanonicalCookie
*> cookie_map
;
575 for (CanonicalCookieVector::const_iterator it
= cookies
.begin();
576 it
!= cookies
.end(); ++it
) {
577 cookie_map
[(*it
)->Name()] = *it
;
580 // Validate that each cookie has the correct priority.
581 std::map
<std::string
, CanonicalCookie
*>::const_iterator it
=
582 cookie_map
.find(kLowName
);
583 ASSERT_TRUE(it
!= cookie_map
.end());
584 EXPECT_EQ(COOKIE_PRIORITY_LOW
, cookie_map
[kLowName
]->Priority());
586 it
= cookie_map
.find(kMediumName
);
587 ASSERT_TRUE(it
!= cookie_map
.end());
588 EXPECT_EQ(COOKIE_PRIORITY_MEDIUM
, cookie_map
[kMediumName
]->Priority());
590 it
= cookie_map
.find(kHighName
);
591 ASSERT_TRUE(it
!= cookie_map
.end());
592 EXPECT_EQ(COOKIE_PRIORITY_HIGH
, cookie_map
[kHighName
]->Priority());
594 STLDeleteElements(&cookies
);
597 TEST_F(SQLitePersistentCookieStoreTest
, UpdateToEncryption
) {
598 CanonicalCookieVector cookies
;
600 // Create unencrypted cookie store and write something to it.
601 InitializeStore(false, false);
602 AddCookie("name", "value123XYZ", "foo.bar", "/", base::Time::Now());
605 // Verify that "value" is visible in the file. This is necessary in order to
606 // have confidence in a later test that "encrypted_value" is not visible.
607 std::string contents
= ReadRawDBContents();
608 EXPECT_NE(0U, contents
.length());
609 EXPECT_NE(contents
.find("value123XYZ"), std::string::npos
);
611 // Create encrypted cookie store and ensure old cookie still reads.
612 STLDeleteElements(&cookies_
);
613 EXPECT_EQ(0U, cookies_
.size());
614 CreateAndLoad(true, false, &cookies
);
615 EXPECT_EQ(1U, cookies_
.size());
616 EXPECT_EQ("name", cookies_
[0]->Name());
617 EXPECT_EQ("value123XYZ", cookies_
[0]->Value());
619 // Make sure we can update existing cookie and add new cookie as encrypted.
620 store_
->DeleteCookie(*(cookies_
[0]));
621 AddCookie("name", "encrypted_value123XYZ", "foo.bar", "/", base::Time::Now());
622 AddCookie("other", "something456ABC", "foo.bar", "/",
623 base::Time::Now() + base::TimeDelta::FromInternalValue(10));
625 STLDeleteElements(&cookies_
);
626 CreateAndLoad(true, false, &cookies
);
627 EXPECT_EQ(2U, cookies_
.size());
628 CanonicalCookie
* cookie_name
= nullptr;
629 CanonicalCookie
* cookie_other
= nullptr;
630 if (cookies_
[0]->Name() == "name") {
631 cookie_name
= cookies_
[0];
632 cookie_other
= cookies_
[1];
634 cookie_name
= cookies_
[1];
635 cookie_other
= cookies_
[0];
637 EXPECT_EQ("encrypted_value123XYZ", cookie_name
->Value());
638 EXPECT_EQ("something456ABC", cookie_other
->Value());
640 STLDeleteElements(&cookies_
);
642 // Examine the real record to make sure plaintext version doesn't exist.
646 ASSERT_TRUE(db
.Open(temp_dir_
.path().Append(kCookieFilename
)));
647 smt
.Assign(db
.GetCachedStatement(SQL_FROM_HERE
,
650 "WHERE host_key = 'foo.bar'"));
653 for (int i
= 0; i
< smt
.ColumnCount(); i
++) {
654 EXPECT_EQ(smt
.ColumnString(i
).find("value"), std::string::npos
);
655 EXPECT_EQ(smt
.ColumnString(i
).find("something"), std::string::npos
);
658 EXPECT_EQ(2, resultcount
);
660 // Verify that "encrypted_value" is NOT visible in the file.
661 contents
= ReadRawDBContents();
662 EXPECT_NE(0U, contents
.length());
663 EXPECT_EQ(contents
.find("encrypted_value123XYZ"), std::string::npos
);
664 EXPECT_EQ(contents
.find("something456ABC"), std::string::npos
);
668 void WasCalledWithNoCookies(bool* was_called_with_no_cookies
,
669 const std::vector
<CanonicalCookie
*>& cookies
) {
670 *was_called_with_no_cookies
= cookies
.empty();
674 TEST_F(SQLitePersistentCookieStoreTest
, EmptyLoadAfterClose
) {
675 // Create unencrypted cookie store and write something to it.
676 InitializeStore(false, false);
677 AddCookie("name", "value123XYZ", "foo.bar", "/", base::Time::Now());
680 // Create the cookie store, but immediately close it.
681 Create(false, false);
682 store_
->Close(base::Closure());
684 // Expect any attempt to call Load() to synchronously respond with an empty
685 // vector of cookies after we've Close()d the database.
686 bool was_called_with_no_cookies
= false;
687 store_
->Load(base::Bind(WasCalledWithNoCookies
, &was_called_with_no_cookies
));
688 EXPECT_TRUE(was_called_with_no_cookies
);
690 // Same with trying to load a specific cookie.
691 was_called_with_no_cookies
= false;
692 store_
->LoadCookiesForKey("foo.bar", base::Bind(WasCalledWithNoCookies
,
693 &was_called_with_no_cookies
));
694 EXPECT_TRUE(was_called_with_no_cookies
);