Pin Chrome's shortcut to the Win10 Start menu on install and OS upgrade.
[chromium-blink-merge.git] / net / extras / sqlite / sqlite_persistent_cookie_store_unittest.cc
blobaa7efbc365ee62d2ac36ae660eed5bccc78b13d9
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"
7 #include <map>
8 #include <set>
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"
31 #include "url/gurl.h"
33 namespace net {
35 namespace {
37 const base::FilePath::CharType kCookieFilename[] = FILE_PATH_LITERAL("Cookies");
39 class CookieCryptor : public CookieCryptoDelegate {
40 public:
41 CookieCryptor();
42 bool EncryptString(const std::string& plaintext,
43 std::string* ciphertext) override;
44 bool DecryptString(const std::string& ciphertext,
45 std::string* plaintext) override;
47 private:
48 scoped_ptr<crypto::SymmetricKey> key_;
49 crypto::Encryptor encryptor_;
52 CookieCryptor::CookieCryptor()
53 : key_(
54 crypto::SymmetricKey::DeriveKeyFromPassword(crypto::SymmetricKey::AES,
55 "password",
56 "saltiest",
57 1000,
58 256)) {
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);
73 } // namespace
75 typedef std::vector<CanonicalCookie*> CanonicalCookieVector;
77 class SQLitePersistentCookieStoreTest : public testing::Test {
78 public:
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) {
86 cookies_ = cookies;
87 loaded_event_.Signal();
90 void OnKeyLoaded(const CanonicalCookieVector& cookies) {
91 cookies_ = 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)));
99 loaded_event_.Wait();
100 *cookies = cookies_;
103 void Flush() {
104 base::WaitableEvent event(false, false);
105 store_->Flush(
106 base::Bind(&base::WaitableEvent::Signal, base::Unretained(&event)));
107 event.Wait();
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() {
121 store_ = nullptr;
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) {
131 if (crypt_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);
144 Load(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),
182 &contents))
183 return std::string();
184 return contents;
187 void SetUp() override { ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); }
189 void TearDown() override {
190 DestroyStore();
191 pool_owner_->pool()->Shutdown();
194 protected:
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());
208 DestroyStore();
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());
217 DestroyStore();
218 STLDeleteElements(&cookies);
220 // Now corrupt the meta table.
222 sql::Connection db;
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"));
227 db.Close();
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());
236 DestroyStore();
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
251 // is still there.
252 DestroyStore();
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]);
263 DestroyStore();
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
273 // cookies.
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());
295 DestroyStore();
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);
313 store_->Flush(
314 base::Bind(&base::WaitableEvent::Signal, base::Unretained(&event)));
316 // Now the DB-thread queue contains:
317 // (active:)
318 // 1. Wait (on db_event)
319 // (pending:)
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();
324 event.Wait();
325 loaded_event_.Wait();
326 STLDeleteElements(&cookies_);
327 DestroyStore();
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);
354 DestroyStore();
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:
375 // (active:)
376 // 1. Wait (on db_event)
377 // (pending:)
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());
392 ASSERT_EQ(true,
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);
426 Flush();
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.
444 DestroyStore();
446 // Create a store that loads session cookies and test that the session cookie
447 // was loaded.
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.
471 DestroyStore();
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
480 // done.
481 DestroyStore();
483 // Create a store that loads old session cookies and test that the session
484 // cookie is gone.
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.
507 DestroyStore();
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.
565 DestroyStore();
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());
603 DestroyStore();
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));
624 DestroyStore();
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];
633 } else {
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());
639 DestroyStore();
640 STLDeleteElements(&cookies_);
642 // Examine the real record to make sure plaintext version doesn't exist.
643 sql::Connection db;
644 sql::Statement smt;
645 int resultcount = 0;
646 ASSERT_TRUE(db.Open(temp_dir_.path().Append(kCookieFilename)));
647 smt.Assign(db.GetCachedStatement(SQL_FROM_HERE,
648 "SELECT * "
649 "FROM cookies "
650 "WHERE host_key = 'foo.bar'"));
651 while (smt.Step()) {
652 resultcount++;
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);
667 namespace {
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());
678 DestroyStore();
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);
697 } // namespace net