OLD | NEW |
| (Empty) |
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. | |
4 | |
5 #include "content/browser/net/sqlite_persistent_cookie_store.h" | |
6 | |
7 #include <map> | |
8 #include <set> | |
9 | |
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/memory/ref_counted.h" | |
15 #include "base/message_loop/message_loop.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 "content/public/browser/cookie_store_factory.h" | |
23 #include "crypto/encryptor.h" | |
24 #include "crypto/symmetric_key.h" | |
25 #include "net/cookies/canonical_cookie.h" | |
26 #include "net/cookies/cookie_constants.h" | |
27 #include "net/extras/sqlite/cookie_crypto_delegate.h" | |
28 #include "sql/connection.h" | |
29 #include "sql/meta_table.h" | |
30 #include "sql/statement.h" | |
31 #include "testing/gtest/include/gtest/gtest.h" | |
32 #include "url/gurl.h" | |
33 | |
34 namespace content { | |
35 | |
36 namespace { | |
37 | |
38 const base::FilePath::CharType kCookieFilename[] = FILE_PATH_LITERAL("Cookies"); | |
39 | |
40 class CookieCryptor : public net::CookieCryptoDelegate { | |
41 public: | |
42 CookieCryptor(); | |
43 bool EncryptString(const std::string& plaintext, | |
44 std::string* ciphertext) override; | |
45 bool DecryptString(const std::string& ciphertext, | |
46 std::string* plaintext) override; | |
47 | |
48 private: | |
49 scoped_ptr<crypto::SymmetricKey> key_; | |
50 crypto::Encryptor encryptor_; | |
51 }; | |
52 | |
53 CookieCryptor::CookieCryptor() : key_( | |
54 crypto::SymmetricKey::DeriveKeyFromPassword( | |
55 crypto::SymmetricKey::AES, "password", "saltiest", 1000, 256)) { | |
56 std::string iv("the iv: 16 bytes"); | |
57 encryptor_.Init(key_.get(), crypto::Encryptor::CBC, iv); | |
58 } | |
59 | |
60 bool CookieCryptor::EncryptString(const std::string& plaintext, | |
61 std::string* ciphertext) { | |
62 return encryptor_.Encrypt(plaintext, ciphertext); | |
63 } | |
64 | |
65 bool CookieCryptor::DecryptString(const std::string& ciphertext, | |
66 std::string* plaintext) { | |
67 return encryptor_.Decrypt(ciphertext, plaintext); | |
68 } | |
69 | |
70 } // namespace | |
71 | |
72 typedef std::vector<net::CanonicalCookie*> CanonicalCookieVector; | |
73 | |
74 class SQLitePersistentCookieStoreTest : public testing::Test { | |
75 public: | |
76 SQLitePersistentCookieStoreTest() | |
77 : pool_owner_(new base::SequencedWorkerPoolOwner(3, "Background Pool")), | |
78 loaded_event_(false, false), | |
79 key_loaded_event_(false, false), | |
80 db_thread_event_(false, false) { | |
81 } | |
82 | |
83 void OnLoaded(const CanonicalCookieVector& cookies) { | |
84 cookies_ = cookies; | |
85 loaded_event_.Signal(); | |
86 } | |
87 | |
88 void OnKeyLoaded(const CanonicalCookieVector& cookies) { | |
89 cookies_ = cookies; | |
90 key_loaded_event_.Signal(); | |
91 } | |
92 | |
93 void Load(CanonicalCookieVector* cookies) { | |
94 EXPECT_FALSE(loaded_event_.IsSignaled()); | |
95 store_->Load(base::Bind(&SQLitePersistentCookieStoreTest::OnLoaded, | |
96 base::Unretained(this))); | |
97 loaded_event_.Wait(); | |
98 *cookies = cookies_; | |
99 } | |
100 | |
101 void Flush() { | |
102 base::WaitableEvent event(false, false); | |
103 store_->Flush(base::Bind(&base::WaitableEvent::Signal, | |
104 base::Unretained(&event))); | |
105 event.Wait(); | |
106 } | |
107 | |
108 scoped_refptr<base::SequencedTaskRunner> background_task_runner() { | |
109 return pool_owner_->pool()->GetSequencedTaskRunner( | |
110 pool_owner_->pool()->GetNamedSequenceToken("background")); | |
111 } | |
112 | |
113 scoped_refptr<base::SequencedTaskRunner> client_task_runner() { | |
114 return pool_owner_->pool()->GetSequencedTaskRunner( | |
115 pool_owner_->pool()->GetNamedSequenceToken("client")); | |
116 } | |
117 | |
118 void DestroyStore() { | |
119 store_ = NULL; | |
120 // Make sure we wait until the destructor has run by shutting down the pool | |
121 // resetting the owner (whose destructor blocks on the pool completion). | |
122 pool_owner_->pool()->Shutdown(); | |
123 // Create a new pool for the few tests that create multiple stores. In other | |
124 // cases this is wasted but harmless. | |
125 pool_owner_.reset(new base::SequencedWorkerPoolOwner(3, "Background Pool")); | |
126 } | |
127 | |
128 void CreateAndLoad(bool crypt_cookies, | |
129 bool restore_old_session_cookies, | |
130 CanonicalCookieVector* cookies) { | |
131 if (crypt_cookies) | |
132 cookie_crypto_delegate_.reset(new CookieCryptor()); | |
133 | |
134 store_ = new SQLitePersistentCookieStore( | |
135 temp_dir_.path().Append(kCookieFilename), | |
136 client_task_runner(), | |
137 background_task_runner(), | |
138 restore_old_session_cookies, | |
139 NULL, | |
140 cookie_crypto_delegate_.get()); | |
141 Load(cookies); | |
142 } | |
143 | |
144 void InitializeStore(bool crypt, bool restore_old_session_cookies) { | |
145 CanonicalCookieVector cookies; | |
146 CreateAndLoad(crypt, restore_old_session_cookies, &cookies); | |
147 EXPECT_EQ(0U, cookies.size()); | |
148 } | |
149 | |
150 // We have to create this method to wrap WaitableEvent::Wait, since we cannot | |
151 // bind a non-void returning method as a Closure. | |
152 void WaitOnDBEvent() { | |
153 db_thread_event_.Wait(); | |
154 } | |
155 | |
156 // Adds a persistent cookie to store_. | |
157 void AddCookie(const std::string& name, | |
158 const std::string& value, | |
159 const std::string& domain, | |
160 const std::string& path, | |
161 const base::Time& creation) { | |
162 store_->AddCookie(net::CanonicalCookie( | |
163 GURL(), name, value, domain, path, creation, creation, creation, false, | |
164 false, false, net::COOKIE_PRIORITY_DEFAULT)); | |
165 } | |
166 | |
167 std::string ReadRawDBContents() { | |
168 std::string contents; | |
169 if (!base::ReadFileToString(temp_dir_.path().Append(kCookieFilename), | |
170 &contents)) | |
171 return std::string(); | |
172 return contents; | |
173 } | |
174 | |
175 void SetUp() override { ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); } | |
176 | |
177 void TearDown() override { | |
178 DestroyStore(); | |
179 pool_owner_->pool()->Shutdown(); | |
180 } | |
181 | |
182 protected: | |
183 base::MessageLoop main_loop_; | |
184 scoped_ptr<base::SequencedWorkerPoolOwner> pool_owner_; | |
185 base::WaitableEvent loaded_event_; | |
186 base::WaitableEvent key_loaded_event_; | |
187 base::WaitableEvent db_thread_event_; | |
188 CanonicalCookieVector cookies_; | |
189 base::ScopedTempDir temp_dir_; | |
190 scoped_refptr<SQLitePersistentCookieStore> store_; | |
191 scoped_ptr<net::CookieCryptoDelegate> cookie_crypto_delegate_; | |
192 }; | |
193 | |
194 TEST_F(SQLitePersistentCookieStoreTest, TestInvalidMetaTableRecovery) { | |
195 InitializeStore(false, false); | |
196 AddCookie("A", "B", "foo.bar", "/", base::Time::Now()); | |
197 DestroyStore(); | |
198 | |
199 // Load up the store and verify that it has good data in it. | |
200 CanonicalCookieVector cookies; | |
201 CreateAndLoad(false, false, &cookies); | |
202 ASSERT_EQ(1U, cookies.size()); | |
203 ASSERT_STREQ("foo.bar", cookies[0]->Domain().c_str()); | |
204 ASSERT_STREQ("A", cookies[0]->Name().c_str()); | |
205 ASSERT_STREQ("B", cookies[0]->Value().c_str()); | |
206 DestroyStore(); | |
207 STLDeleteElements(&cookies); | |
208 | |
209 // Now corrupt the meta table. | |
210 { | |
211 sql::Connection db; | |
212 ASSERT_TRUE(db.Open(temp_dir_.path().Append(kCookieFilename))); | |
213 sql::MetaTable meta_table_; | |
214 meta_table_.Init(&db, 1, 1); | |
215 ASSERT_TRUE(db.Execute("DELETE FROM meta")); | |
216 db.Close(); | |
217 } | |
218 | |
219 // Upon loading, the database should be reset to a good, blank state. | |
220 CreateAndLoad(false, false, &cookies); | |
221 ASSERT_EQ(0U, cookies.size()); | |
222 | |
223 // Verify that, after, recovery, the database persists properly. | |
224 AddCookie("X", "Y", "foo.bar", "/", base::Time::Now()); | |
225 DestroyStore(); | |
226 CreateAndLoad(false, false, &cookies); | |
227 ASSERT_EQ(1U, cookies.size()); | |
228 ASSERT_STREQ("foo.bar", cookies[0]->Domain().c_str()); | |
229 ASSERT_STREQ("X", cookies[0]->Name().c_str()); | |
230 ASSERT_STREQ("Y", cookies[0]->Value().c_str()); | |
231 STLDeleteElements(&cookies); | |
232 } | |
233 | |
234 // Test if data is stored as expected in the SQLite database. | |
235 TEST_F(SQLitePersistentCookieStoreTest, TestPersistance) { | |
236 InitializeStore(false, false); | |
237 AddCookie("A", "B", "foo.bar", "/", base::Time::Now()); | |
238 // Replace the store effectively destroying the current one and forcing it | |
239 // to write its data to disk. Then we can see if after loading it again it | |
240 // is still there. | |
241 DestroyStore(); | |
242 // Reload and test for persistence | |
243 CanonicalCookieVector cookies; | |
244 CreateAndLoad(false, false, &cookies); | |
245 ASSERT_EQ(1U, cookies.size()); | |
246 ASSERT_STREQ("foo.bar", cookies[0]->Domain().c_str()); | |
247 ASSERT_STREQ("A", cookies[0]->Name().c_str()); | |
248 ASSERT_STREQ("B", cookies[0]->Value().c_str()); | |
249 | |
250 // Now delete the cookie and check persistence again. | |
251 store_->DeleteCookie(*cookies[0]); | |
252 DestroyStore(); | |
253 STLDeleteElements(&cookies); | |
254 | |
255 // Reload and check if the cookie has been removed. | |
256 CreateAndLoad(false, false, &cookies); | |
257 ASSERT_EQ(0U, cookies.size()); | |
258 } | |
259 | |
260 // Test that priority load of cookies for a specfic domain key could be | |
261 // completed before the entire store is loaded | |
262 TEST_F(SQLitePersistentCookieStoreTest, TestLoadCookiesForKey) { | |
263 InitializeStore(false, false); | |
264 base::Time t = base::Time::Now(); | |
265 AddCookie("A", "B", "foo.bar", "/", t); | |
266 t += base::TimeDelta::FromInternalValue(10); | |
267 AddCookie("A", "B", "www.aaa.com", "/", t); | |
268 t += base::TimeDelta::FromInternalValue(10); | |
269 AddCookie("A", "B", "travel.aaa.com", "/", t); | |
270 t += base::TimeDelta::FromInternalValue(10); | |
271 AddCookie("A", "B", "www.bbb.com", "/", t); | |
272 DestroyStore(); | |
273 | |
274 store_ = new SQLitePersistentCookieStore( | |
275 temp_dir_.path().Append(kCookieFilename), | |
276 client_task_runner(), | |
277 background_task_runner(), | |
278 false, NULL, NULL); | |
279 | |
280 // Posting a blocking task to db_thread_ makes sure that the DB thread waits | |
281 // until both Load and LoadCookiesForKey have been posted to its task queue. | |
282 background_task_runner()->PostTask( | |
283 FROM_HERE, | |
284 base::Bind(&SQLitePersistentCookieStoreTest::WaitOnDBEvent, | |
285 base::Unretained(this))); | |
286 store_->Load(base::Bind(&SQLitePersistentCookieStoreTest::OnLoaded, | |
287 base::Unretained(this))); | |
288 store_->LoadCookiesForKey("aaa.com", | |
289 base::Bind(&SQLitePersistentCookieStoreTest::OnKeyLoaded, | |
290 base::Unretained(this))); | |
291 background_task_runner()->PostTask( | |
292 FROM_HERE, | |
293 base::Bind(&SQLitePersistentCookieStoreTest::WaitOnDBEvent, | |
294 base::Unretained(this))); | |
295 | |
296 // Now the DB-thread queue contains: | |
297 // (active:) | |
298 // 1. Wait (on db_event) | |
299 // (pending:) | |
300 // 2. "Init And Chain-Load First Domain" | |
301 // 3. Priority Load (aaa.com) | |
302 // 4. Wait (on db_event) | |
303 db_thread_event_.Signal(); | |
304 key_loaded_event_.Wait(); | |
305 ASSERT_EQ(loaded_event_.IsSignaled(), false); | |
306 std::set<std::string> cookies_loaded; | |
307 for (CanonicalCookieVector::const_iterator it = cookies_.begin(); | |
308 it != cookies_.end(); | |
309 ++it) { | |
310 cookies_loaded.insert((*it)->Domain().c_str()); | |
311 } | |
312 STLDeleteElements(&cookies_); | |
313 ASSERT_GT(4U, cookies_loaded.size()); | |
314 ASSERT_EQ(true, cookies_loaded.find("www.aaa.com") != cookies_loaded.end()); | |
315 ASSERT_EQ(true, | |
316 cookies_loaded.find("travel.aaa.com") != cookies_loaded.end()); | |
317 | |
318 db_thread_event_.Signal(); | |
319 loaded_event_.Wait(); | |
320 for (CanonicalCookieVector::const_iterator it = cookies_.begin(); | |
321 it != cookies_.end(); | |
322 ++it) { | |
323 cookies_loaded.insert((*it)->Domain().c_str()); | |
324 } | |
325 ASSERT_EQ(4U, cookies_loaded.size()); | |
326 ASSERT_EQ(cookies_loaded.find("foo.bar") != cookies_loaded.end(), | |
327 true); | |
328 ASSERT_EQ(cookies_loaded.find("www.bbb.com") != cookies_loaded.end(), true); | |
329 STLDeleteElements(&cookies_); | |
330 } | |
331 | |
332 // Test that we can force the database to be written by calling Flush(). | |
333 TEST_F(SQLitePersistentCookieStoreTest, TestFlush) { | |
334 InitializeStore(false, false); | |
335 // File timestamps don't work well on all platforms, so we'll determine | |
336 // whether the DB file has been modified by checking its size. | |
337 base::FilePath path = temp_dir_.path().Append(kCookieFilename); | |
338 base::File::Info info; | |
339 ASSERT_TRUE(base::GetFileInfo(path, &info)); | |
340 int64 base_size = info.size; | |
341 | |
342 // Write some large cookies, so the DB will have to expand by several KB. | |
343 for (char c = 'a'; c < 'z'; ++c) { | |
344 // Each cookie needs a unique timestamp for creation_utc (see DB schema). | |
345 base::Time t = base::Time::Now() + base::TimeDelta::FromMicroseconds(c); | |
346 std::string name(1, c); | |
347 std::string value(1000, c); | |
348 AddCookie(name, value, "foo.bar", "/", t); | |
349 } | |
350 | |
351 Flush(); | |
352 | |
353 // We forced a write, so now the file will be bigger. | |
354 ASSERT_TRUE(base::GetFileInfo(path, &info)); | |
355 ASSERT_GT(info.size, base_size); | |
356 } | |
357 | |
358 // Test loading old session cookies from the disk. | |
359 TEST_F(SQLitePersistentCookieStoreTest, TestLoadOldSessionCookies) { | |
360 InitializeStore(false, true); | |
361 | |
362 // Add a session cookie. | |
363 store_->AddCookie(net::CanonicalCookie(GURL(), "C", "D", "sessioncookie.com", | |
364 "/", base::Time::Now(), base::Time(), | |
365 base::Time::Now(), false, false, false, | |
366 net::COOKIE_PRIORITY_DEFAULT)); | |
367 | |
368 // Force the store to write its data to the disk. | |
369 DestroyStore(); | |
370 | |
371 // Create a store that loads session cookies and test that the session cookie | |
372 // was loaded. | |
373 CanonicalCookieVector cookies; | |
374 CreateAndLoad(false, true, &cookies); | |
375 | |
376 ASSERT_EQ(1U, cookies.size()); | |
377 ASSERT_STREQ("sessioncookie.com", cookies[0]->Domain().c_str()); | |
378 ASSERT_STREQ("C", cookies[0]->Name().c_str()); | |
379 ASSERT_STREQ("D", cookies[0]->Value().c_str()); | |
380 ASSERT_EQ(net::COOKIE_PRIORITY_DEFAULT, cookies[0]->Priority()); | |
381 | |
382 STLDeleteElements(&cookies); | |
383 } | |
384 | |
385 // Test loading old session cookies from the disk. | |
386 TEST_F(SQLitePersistentCookieStoreTest, TestDontLoadOldSessionCookies) { | |
387 InitializeStore(false, true); | |
388 | |
389 // Add a session cookie. | |
390 store_->AddCookie(net::CanonicalCookie(GURL(), "C", "D", "sessioncookie.com", | |
391 "/", base::Time::Now(), base::Time(), | |
392 base::Time::Now(), false, false, false, | |
393 net::COOKIE_PRIORITY_DEFAULT)); | |
394 | |
395 // Force the store to write its data to the disk. | |
396 DestroyStore(); | |
397 | |
398 // Create a store that doesn't load old session cookies and test that the | |
399 // session cookie was not loaded. | |
400 CanonicalCookieVector cookies; | |
401 CreateAndLoad(false, false, &cookies); | |
402 ASSERT_EQ(0U, cookies.size()); | |
403 | |
404 // The store should also delete the session cookie. Wait until that has been | |
405 // done. | |
406 DestroyStore(); | |
407 | |
408 // Create a store that loads old session cookies and test that the session | |
409 // cookie is gone. | |
410 CreateAndLoad(false, true, &cookies); | |
411 ASSERT_EQ(0U, cookies.size()); | |
412 } | |
413 | |
414 TEST_F(SQLitePersistentCookieStoreTest, PersistIsPersistent) { | |
415 InitializeStore(false, true); | |
416 static const char kSessionName[] = "session"; | |
417 static const char kPersistentName[] = "persistent"; | |
418 | |
419 // Add a session cookie. | |
420 store_->AddCookie(net::CanonicalCookie( | |
421 GURL(), kSessionName, "val", "sessioncookie.com", "/", base::Time::Now(), | |
422 base::Time(), base::Time::Now(), false, false, false, | |
423 net::COOKIE_PRIORITY_DEFAULT)); | |
424 // Add a persistent cookie. | |
425 store_->AddCookie(net::CanonicalCookie( | |
426 GURL(), kPersistentName, "val", "sessioncookie.com", "/", | |
427 base::Time::Now() - base::TimeDelta::FromDays(1), | |
428 base::Time::Now() + base::TimeDelta::FromDays(1), base::Time::Now(), | |
429 false, false, false, net::COOKIE_PRIORITY_DEFAULT)); | |
430 | |
431 // Force the store to write its data to the disk. | |
432 DestroyStore(); | |
433 | |
434 // Create a store that loads session cookie and test that the IsPersistent | |
435 // attribute is restored. | |
436 CanonicalCookieVector cookies; | |
437 CreateAndLoad(false, true, &cookies); | |
438 ASSERT_EQ(2U, cookies.size()); | |
439 | |
440 std::map<std::string, net::CanonicalCookie*> cookie_map; | |
441 for (CanonicalCookieVector::const_iterator it = cookies.begin(); | |
442 it != cookies.end(); | |
443 ++it) { | |
444 cookie_map[(*it)->Name()] = *it; | |
445 } | |
446 | |
447 std::map<std::string, net::CanonicalCookie*>::const_iterator it = | |
448 cookie_map.find(kSessionName); | |
449 ASSERT_TRUE(it != cookie_map.end()); | |
450 EXPECT_FALSE(cookie_map[kSessionName]->IsPersistent()); | |
451 | |
452 it = cookie_map.find(kPersistentName); | |
453 ASSERT_TRUE(it != cookie_map.end()); | |
454 EXPECT_TRUE(cookie_map[kPersistentName]->IsPersistent()); | |
455 | |
456 STLDeleteElements(&cookies); | |
457 } | |
458 | |
459 TEST_F(SQLitePersistentCookieStoreTest, PriorityIsPersistent) { | |
460 static const char kLowName[] = "low"; | |
461 static const char kMediumName[] = "medium"; | |
462 static const char kHighName[] = "high"; | |
463 static const char kCookieDomain[] = "sessioncookie.com"; | |
464 static const char kCookieValue[] = "value"; | |
465 static const char kCookiePath[] = "/"; | |
466 | |
467 InitializeStore(false, true); | |
468 | |
469 // Add a low-priority persistent cookie. | |
470 store_->AddCookie(net::CanonicalCookie( | |
471 GURL(), kLowName, kCookieValue, kCookieDomain, kCookiePath, | |
472 base::Time::Now() - base::TimeDelta::FromMinutes(1), | |
473 base::Time::Now() + base::TimeDelta::FromDays(1), base::Time::Now(), | |
474 false, false, false, net::COOKIE_PRIORITY_LOW)); | |
475 | |
476 // Add a medium-priority persistent cookie. | |
477 store_->AddCookie(net::CanonicalCookie( | |
478 GURL(), kMediumName, kCookieValue, kCookieDomain, kCookiePath, | |
479 base::Time::Now() - base::TimeDelta::FromMinutes(2), | |
480 base::Time::Now() + base::TimeDelta::FromDays(1), base::Time::Now(), | |
481 false, false, false, net::COOKIE_PRIORITY_MEDIUM)); | |
482 | |
483 // Add a high-priority peristent cookie. | |
484 store_->AddCookie(net::CanonicalCookie( | |
485 GURL(), kHighName, kCookieValue, kCookieDomain, kCookiePath, | |
486 base::Time::Now() - base::TimeDelta::FromMinutes(3), | |
487 base::Time::Now() + base::TimeDelta::FromDays(1), base::Time::Now(), | |
488 false, false, false, net::COOKIE_PRIORITY_HIGH)); | |
489 | |
490 // Force the store to write its data to the disk. | |
491 DestroyStore(); | |
492 | |
493 // Create a store that loads session cookie and test that the priority | |
494 // attribute values are restored. | |
495 CanonicalCookieVector cookies; | |
496 CreateAndLoad(false, true, &cookies); | |
497 ASSERT_EQ(3U, cookies.size()); | |
498 | |
499 // Put the cookies into a map, by name, so we can easily find them. | |
500 std::map<std::string, net::CanonicalCookie*> cookie_map; | |
501 for (CanonicalCookieVector::const_iterator it = cookies.begin(); | |
502 it != cookies.end(); | |
503 ++it) { | |
504 cookie_map[(*it)->Name()] = *it; | |
505 } | |
506 | |
507 // Validate that each cookie has the correct priority. | |
508 std::map<std::string, net::CanonicalCookie*>::const_iterator it = | |
509 cookie_map.find(kLowName); | |
510 ASSERT_TRUE(it != cookie_map.end()); | |
511 EXPECT_EQ(net::COOKIE_PRIORITY_LOW, cookie_map[kLowName]->Priority()); | |
512 | |
513 it = cookie_map.find(kMediumName); | |
514 ASSERT_TRUE(it != cookie_map.end()); | |
515 EXPECT_EQ(net::COOKIE_PRIORITY_MEDIUM, cookie_map[kMediumName]->Priority()); | |
516 | |
517 it = cookie_map.find(kHighName); | |
518 ASSERT_TRUE(it != cookie_map.end()); | |
519 EXPECT_EQ(net::COOKIE_PRIORITY_HIGH, cookie_map[kHighName]->Priority()); | |
520 | |
521 STLDeleteElements(&cookies); | |
522 } | |
523 | |
524 TEST_F(SQLitePersistentCookieStoreTest, UpdateToEncryption) { | |
525 CanonicalCookieVector cookies; | |
526 | |
527 // Create unencrypted cookie store and write something to it. | |
528 InitializeStore(false, false); | |
529 AddCookie("name", "value123XYZ", "foo.bar", "/", base::Time::Now()); | |
530 DestroyStore(); | |
531 | |
532 // Verify that "value" is visible in the file. This is necessary in order to | |
533 // have confidence in a later test that "encrypted_value" is not visible. | |
534 std::string contents = ReadRawDBContents(); | |
535 EXPECT_NE(0U, contents.length()); | |
536 EXPECT_NE(contents.find("value123XYZ"), std::string::npos); | |
537 | |
538 // Create encrypted cookie store and ensure old cookie still reads. | |
539 STLDeleteElements(&cookies_); | |
540 EXPECT_EQ(0U, cookies_.size()); | |
541 CreateAndLoad(true, false, &cookies); | |
542 EXPECT_EQ(1U, cookies_.size()); | |
543 EXPECT_EQ("name", cookies_[0]->Name()); | |
544 EXPECT_EQ("value123XYZ", cookies_[0]->Value()); | |
545 | |
546 // Make sure we can update existing cookie and add new cookie as encrypted. | |
547 store_->DeleteCookie(*(cookies_[0])); | |
548 AddCookie("name", "encrypted_value123XYZ", "foo.bar", "/", base::Time::Now()); | |
549 AddCookie("other", "something456ABC", "foo.bar", "/", | |
550 base::Time::Now() + base::TimeDelta::FromInternalValue(10)); | |
551 DestroyStore(); | |
552 STLDeleteElements(&cookies_); | |
553 CreateAndLoad(true, false, &cookies); | |
554 EXPECT_EQ(2U, cookies_.size()); | |
555 net::CanonicalCookie* cookie_name = NULL; | |
556 net::CanonicalCookie* cookie_other = NULL; | |
557 if (cookies_[0]->Name() == "name") { | |
558 cookie_name = cookies_[0]; | |
559 cookie_other = cookies_[1]; | |
560 } else { | |
561 cookie_name = cookies_[1]; | |
562 cookie_other = cookies_[0]; | |
563 } | |
564 EXPECT_EQ("encrypted_value123XYZ", cookie_name->Value()); | |
565 EXPECT_EQ("something456ABC", cookie_other->Value()); | |
566 DestroyStore(); | |
567 STLDeleteElements(&cookies_); | |
568 | |
569 // Examine the real record to make sure plaintext version doesn't exist. | |
570 sql::Connection db; | |
571 sql::Statement smt; | |
572 int resultcount = 0; | |
573 ASSERT_TRUE(db.Open(temp_dir_.path().Append(kCookieFilename))); | |
574 smt.Assign(db.GetCachedStatement(SQL_FROM_HERE, | |
575 "SELECT * " | |
576 "FROM cookies " | |
577 "WHERE host_key = 'foo.bar'")); | |
578 while (smt.Step()) { | |
579 resultcount++; | |
580 for (int i=0; i < smt.ColumnCount(); i++) { | |
581 EXPECT_EQ(smt.ColumnString(i).find("value"), std::string::npos); | |
582 EXPECT_EQ(smt.ColumnString(i).find("something"), std::string::npos); | |
583 } | |
584 } | |
585 EXPECT_EQ(2, resultcount); | |
586 | |
587 // Verify that "encrypted_value" is NOT visible in the file. | |
588 contents = ReadRawDBContents(); | |
589 EXPECT_NE(0U, contents.length()); | |
590 EXPECT_EQ(contents.find("encrypted_value123XYZ"), std::string::npos); | |
591 EXPECT_EQ(contents.find("something456ABC"), std::string::npos); | |
592 } | |
593 | |
594 } // namespace content | |
OLD | NEW |