Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include <map> | 5 #include <map> |
| 6 #include <set> | 6 #include <set> |
| 7 | 7 |
| 8 #include "base/bind.h" | 8 #include "base/bind.h" |
| 9 #include "base/callback.h" | 9 #include "base/callback.h" |
| 10 #include "base/file_util.h" | 10 #include "base/file_util.h" |
| 11 #include "base/files/scoped_temp_dir.h" | 11 #include "base/files/scoped_temp_dir.h" |
| 12 #include "base/memory/ref_counted.h" | 12 #include "base/memory/ref_counted.h" |
| 13 #include "base/message_loop.h" | 13 #include "base/message_loop.h" |
| 14 #include "base/sequenced_task_runner.h" | |
| 14 #include "base/stl_util.h" | 15 #include "base/stl_util.h" |
| 15 #include "base/synchronization/waitable_event.h" | 16 #include "base/synchronization/waitable_event.h" |
| 16 #include "base/test/thread_test_helper.h" | 17 #include "base/test/sequenced_worker_pool_owner.h" |
| 18 #include "base/threading/sequenced_worker_pool.h" | |
| 17 #include "base/time.h" | 19 #include "base/time.h" |
| 18 #include "chrome/browser/net/clear_on_exit_policy.h" | 20 #include "chrome/browser/net/clear_on_exit_policy.h" |
| 19 #include "chrome/browser/net/sqlite_persistent_cookie_store.h" | 21 #include "chrome/browser/net/sqlite_persistent_cookie_store.h" |
| 20 #include "chrome/common/chrome_constants.h" | 22 #include "chrome/common/chrome_constants.h" |
| 21 #include "content/public/test/test_browser_thread.h" | |
| 22 #include "googleurl/src/gurl.h" | 23 #include "googleurl/src/gurl.h" |
| 23 #include "net/cookies/canonical_cookie.h" | 24 #include "net/cookies/canonical_cookie.h" |
| 24 #include "sql/connection.h" | 25 #include "sql/connection.h" |
| 25 #include "sql/meta_table.h" | 26 #include "sql/meta_table.h" |
| 26 #include "testing/gtest/include/gtest/gtest.h" | 27 #include "testing/gtest/include/gtest/gtest.h" |
| 27 #include "webkit/quota/mock_special_storage_policy.h" | 28 #include "webkit/quota/mock_special_storage_policy.h" |
| 28 | 29 |
| 29 using content::BrowserThread; | |
| 30 | |
| 31 typedef std::vector<net::CanonicalCookie*> CanonicalCookieVector; | 30 typedef std::vector<net::CanonicalCookie*> CanonicalCookieVector; |
| 32 | 31 |
| 33 class SQLitePersistentCookieStoreTest : public testing::Test { | 32 class SQLitePersistentCookieStoreTest : public testing::Test { |
| 34 public: | 33 public: |
| 35 SQLitePersistentCookieStoreTest() | 34 SQLitePersistentCookieStoreTest() |
| 36 : ui_thread_(BrowserThread::UI), | 35 : pool_owner_(new base::SequencedWorkerPoolOwner(1, "Background Pool")), |
| 37 db_thread_(BrowserThread::DB), | |
| 38 io_thread_(BrowserThread::IO), | |
| 39 loaded_event_(false, false), | 36 loaded_event_(false, false), |
| 40 key_loaded_event_(false, false), | 37 key_loaded_event_(false, false), |
| 41 db_thread_event_(false, false) { | 38 db_thread_event_(false, false) { |
| 42 } | 39 } |
| 43 | 40 |
| 44 void OnLoaded(const CanonicalCookieVector& cookies) { | 41 void OnLoaded(const CanonicalCookieVector& cookies) { |
| 45 cookies_ = cookies; | 42 cookies_ = cookies; |
| 46 loaded_event_.Signal(); | 43 loaded_event_.Signal(); |
| 47 } | 44 } |
| 48 | 45 |
| 49 void OnKeyLoaded(const CanonicalCookieVector& cookies) { | 46 void OnKeyLoaded(const CanonicalCookieVector& cookies) { |
| 50 cookies_ = cookies; | 47 cookies_ = cookies; |
| 51 key_loaded_event_.Signal(); | 48 key_loaded_event_.Signal(); |
| 52 } | 49 } |
| 53 | 50 |
| 54 void Load(CanonicalCookieVector* cookies) { | 51 void Load(CanonicalCookieVector* cookies) { |
| 52 EXPECT_FALSE(loaded_event_.IsSignaled()); | |
| 55 store_->Load(base::Bind(&SQLitePersistentCookieStoreTest::OnLoaded, | 53 store_->Load(base::Bind(&SQLitePersistentCookieStoreTest::OnLoaded, |
| 56 base::Unretained(this))); | 54 base::Unretained(this))); |
| 57 loaded_event_.Wait(); | 55 loaded_event_.Wait(); |
| 58 *cookies = cookies_; | 56 *cookies = cookies_; |
| 59 } | 57 } |
| 60 | 58 |
| 59 void Flush() { | |
| 60 base::WaitableEvent event(false, false); | |
| 61 store_->Flush(base::Bind(&base::WaitableEvent::Signal, | |
| 62 base::Unretained(&event))); | |
| 63 event.Wait(); | |
| 64 } | |
| 65 | |
| 66 scoped_refptr<base::SequencedTaskRunner> background_task_runner() { | |
| 67 return pool_owner_->pool()->GetSequencedTaskRunner( | |
| 68 pool_owner_->pool()->GetNamedSequenceToken("background")); | |
| 69 } | |
| 70 | |
| 71 scoped_refptr<base::SequencedTaskRunner> client_task_runner() { | |
| 72 return pool_owner_->pool()->GetSequencedTaskRunner( | |
| 73 pool_owner_->pool()->GetNamedSequenceToken("client")); | |
| 74 } | |
| 75 | |
| 61 void DestroyStore() { | 76 void DestroyStore() { |
| 62 store_ = NULL; | 77 store_ = NULL; |
| 63 // Make sure we wait until the destructor has run by waiting for all pending | 78 // Make sure we wait until the destructor has run by shutting down the pool |
| 64 // tasks on the DB thread to run. | 79 // resetting the owner (whose destructor blocks on the pool completion). |
| 65 scoped_refptr<base::ThreadTestHelper> helper( | 80 pool_owner_->pool()->Shutdown(); |
| 66 new base::ThreadTestHelper( | 81 // Create a new pool for the few tests that create multiple stores. In other |
| 67 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::DB))); | 82 // cases this is wasted but harmless. |
| 68 ASSERT_TRUE(helper->Run()); | 83 pool_owner_.reset(new base::SequencedWorkerPoolOwner(1, "Background Pool")); |
| 69 } | 84 } |
| 70 | 85 |
| 71 void CreateAndLoad(bool restore_old_session_cookies, | 86 void CreateAndLoad(bool restore_old_session_cookies, |
| 72 CanonicalCookieVector* cookies) { | 87 CanonicalCookieVector* cookies) { |
| 73 store_ = new SQLitePersistentCookieStore( | 88 store_ = new SQLitePersistentCookieStore( |
| 74 temp_dir_.path().Append(chrome::kCookieFilename), | 89 temp_dir_.path().Append(chrome::kCookieFilename), |
| 90 client_task_runner(), | |
| 91 background_task_runner(), | |
| 75 restore_old_session_cookies, | 92 restore_old_session_cookies, |
| 76 NULL); | 93 NULL); |
| 77 Load(cookies); | 94 Load(cookies); |
| 78 } | 95 } |
| 79 | 96 |
| 80 void InitializeStore(bool restore_old_session_cookies) { | 97 void InitializeStore(bool restore_old_session_cookies) { |
| 81 CanonicalCookieVector cookies; | 98 CanonicalCookieVector cookies; |
| 82 CreateAndLoad(restore_old_session_cookies, &cookies); | 99 CreateAndLoad(restore_old_session_cookies, &cookies); |
| 83 ASSERT_EQ(0U, cookies.size()); | 100 EXPECT_EQ(0U, cookies.size()); |
|
Randy Smith (Not in Mondays)
2013/02/22 18:20:16
I know this is probably my cluelessness, but why t
erikwright (departed)
2013/02/25 16:25:47
ASSERT is designed to terminate a test. It does so
| |
| 84 } | 101 } |
| 85 | 102 |
| 86 // We have to create this method to wrap WaitableEvent::Wait, since we cannot | 103 // We have to create this method to wrap WaitableEvent::Wait, since we cannot |
| 87 // bind a non-void returning method as a Closure. | 104 // bind a non-void returning method as a Closure. |
| 88 void WaitOnDBEvent() { | 105 void WaitOnDBEvent() { |
| 89 db_thread_event_.Wait(); | 106 db_thread_event_.Wait(); |
| 90 } | 107 } |
| 91 | 108 |
| 92 // Adds a persistent cookie to store_. | 109 // Adds a persistent cookie to store_. |
| 93 void AddCookie(const std::string& name, | 110 void AddCookie(const std::string& name, |
| 94 const std::string& value, | 111 const std::string& value, |
| 95 const std::string& domain, | 112 const std::string& domain, |
| 96 const std::string& path, | 113 const std::string& path, |
| 97 const base::Time& creation) { | 114 const base::Time& creation) { |
| 98 store_->AddCookie( | 115 store_->AddCookie( |
| 99 net::CanonicalCookie(GURL(), name, value, domain, path, std::string(), | 116 net::CanonicalCookie(GURL(), name, value, domain, path, std::string(), |
| 100 std::string(), creation, creation, creation, false, | 117 std::string(), creation, creation, creation, false, |
| 101 false)); | 118 false)); |
| 102 } | 119 } |
| 103 | 120 |
| 104 virtual void SetUp() { | 121 virtual void SetUp() OVERRIDE { |
| 105 ui_thread_.Start(); | |
| 106 db_thread_.Start(); | |
| 107 io_thread_.Start(); | |
| 108 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); | 122 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); |
| 109 } | 123 } |
| 110 | 124 |
| 125 virtual void TearDown() OVERRIDE { | |
| 126 DestroyStore(); | |
| 127 pool_owner_->pool()->Shutdown(); | |
| 128 } | |
| 129 | |
| 111 protected: | 130 protected: |
| 112 content::TestBrowserThread ui_thread_; | 131 MessageLoop main_loop_; |
| 113 content::TestBrowserThread db_thread_; | 132 scoped_ptr<base::SequencedWorkerPoolOwner> pool_owner_; |
| 114 content::TestBrowserThread io_thread_; | |
| 115 base::WaitableEvent loaded_event_; | 133 base::WaitableEvent loaded_event_; |
| 116 base::WaitableEvent key_loaded_event_; | 134 base::WaitableEvent key_loaded_event_; |
| 117 base::WaitableEvent db_thread_event_; | 135 base::WaitableEvent db_thread_event_; |
| 118 CanonicalCookieVector cookies_; | 136 CanonicalCookieVector cookies_; |
| 119 base::ScopedTempDir temp_dir_; | 137 base::ScopedTempDir temp_dir_; |
| 120 scoped_refptr<SQLitePersistentCookieStore> store_; | 138 scoped_refptr<SQLitePersistentCookieStore> store_; |
| 121 }; | 139 }; |
| 122 | 140 |
| 123 TEST_F(SQLitePersistentCookieStoreTest, TestInvalidMetaTableRecovery) { | 141 TEST_F(SQLitePersistentCookieStoreTest, TestInvalidMetaTableRecovery) { |
| 124 InitializeStore(false); | 142 InitializeStore(false); |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 194 AddCookie("A", "B", "foo.bar", "/", t); | 212 AddCookie("A", "B", "foo.bar", "/", t); |
| 195 t += base::TimeDelta::FromInternalValue(10); | 213 t += base::TimeDelta::FromInternalValue(10); |
| 196 AddCookie("A", "B", "www.aaa.com", "/", t); | 214 AddCookie("A", "B", "www.aaa.com", "/", t); |
| 197 t += base::TimeDelta::FromInternalValue(10); | 215 t += base::TimeDelta::FromInternalValue(10); |
| 198 AddCookie("A", "B", "travel.aaa.com", "/", t); | 216 AddCookie("A", "B", "travel.aaa.com", "/", t); |
| 199 t += base::TimeDelta::FromInternalValue(10); | 217 t += base::TimeDelta::FromInternalValue(10); |
| 200 AddCookie("A", "B", "www.bbb.com", "/", t); | 218 AddCookie("A", "B", "www.bbb.com", "/", t); |
| 201 DestroyStore(); | 219 DestroyStore(); |
| 202 | 220 |
| 203 store_ = new SQLitePersistentCookieStore( | 221 store_ = new SQLitePersistentCookieStore( |
| 204 temp_dir_.path().Append(chrome::kCookieFilename), false, NULL); | 222 temp_dir_.path().Append(chrome::kCookieFilename), |
| 223 client_task_runner(), | |
| 224 background_task_runner(), | |
| 225 false, NULL); | |
| 205 // Posting a blocking task to db_thread_ makes sure that the DB thread waits | 226 // Posting a blocking task to db_thread_ makes sure that the DB thread waits |
| 206 // until both Load and LoadCookiesForKey have been posted to its task queue. | 227 // until both Load and LoadCookiesForKey have been posted to its task queue. |
| 207 BrowserThread::PostTask( | 228 background_task_runner()->PostTask( |
| 208 BrowserThread::DB, FROM_HERE, | 229 FROM_HERE, |
| 209 base::Bind(&SQLitePersistentCookieStoreTest::WaitOnDBEvent, | 230 base::Bind(&SQLitePersistentCookieStoreTest::WaitOnDBEvent, |
| 210 base::Unretained(this))); | 231 base::Unretained(this))); |
| 211 store_->Load(base::Bind(&SQLitePersistentCookieStoreTest::OnLoaded, | 232 store_->Load(base::Bind(&SQLitePersistentCookieStoreTest::OnLoaded, |
| 212 base::Unretained(this))); | 233 base::Unretained(this))); |
| 213 store_->LoadCookiesForKey("aaa.com", | 234 store_->LoadCookiesForKey("aaa.com", |
| 214 base::Bind(&SQLitePersistentCookieStoreTest::OnKeyLoaded, | 235 base::Bind(&SQLitePersistentCookieStoreTest::OnKeyLoaded, |
| 215 base::Unretained(this))); | 236 base::Unretained(this))); |
| 216 BrowserThread::PostTask( | 237 background_task_runner()->PostTask( |
| 217 BrowserThread::DB, FROM_HERE, | 238 FROM_HERE, |
| 218 base::Bind(&SQLitePersistentCookieStoreTest::WaitOnDBEvent, | 239 base::Bind(&SQLitePersistentCookieStoreTest::WaitOnDBEvent, |
| 219 base::Unretained(this))); | 240 base::Unretained(this))); |
| 220 | 241 |
| 221 // Now the DB-thread queue contains: | 242 // Now the DB-thread queue contains: |
| 222 // (active:) | 243 // (active:) |
| 223 // 1. Wait (on db_event) | 244 // 1. Wait (on db_event) |
| 224 // (pending:) | 245 // (pending:) |
| 225 // 2. "Init And Chain-Load First Domain" | 246 // 2. "Init And Chain-Load First Domain" |
| 226 // 3. Priority Load (aaa.com) | 247 // 3. Priority Load (aaa.com) |
| 227 // 4. Wait (on db_event) | 248 // 4. Wait (on db_event) |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 266 | 287 |
| 267 // Write some large cookies, so the DB will have to expand by several KB. | 288 // Write some large cookies, so the DB will have to expand by several KB. |
| 268 for (char c = 'a'; c < 'z'; ++c) { | 289 for (char c = 'a'; c < 'z'; ++c) { |
| 269 // Each cookie needs a unique timestamp for creation_utc (see DB schema). | 290 // Each cookie needs a unique timestamp for creation_utc (see DB schema). |
| 270 base::Time t = base::Time::Now() + base::TimeDelta::FromMicroseconds(c); | 291 base::Time t = base::Time::Now() + base::TimeDelta::FromMicroseconds(c); |
| 271 std::string name(1, c); | 292 std::string name(1, c); |
| 272 std::string value(1000, c); | 293 std::string value(1000, c); |
| 273 AddCookie(name, value, "foo.bar", "/", t); | 294 AddCookie(name, value, "foo.bar", "/", t); |
| 274 } | 295 } |
| 275 | 296 |
| 276 // Call Flush() and wait until the DB thread is idle. | 297 Flush(); |
| 277 store_->Flush(base::Closure()); | |
| 278 scoped_refptr<base::ThreadTestHelper> helper( | |
| 279 new base::ThreadTestHelper( | |
| 280 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::DB))); | |
| 281 ASSERT_TRUE(helper->Run()); | |
| 282 | 298 |
| 283 // We forced a write, so now the file will be bigger. | 299 // We forced a write, so now the file will be bigger. |
| 284 ASSERT_TRUE(file_util::GetFileInfo(path, &info)); | 300 ASSERT_TRUE(file_util::GetFileInfo(path, &info)); |
| 285 ASSERT_GT(info.size, base_size); | 301 ASSERT_GT(info.size, base_size); |
| 286 } | 302 } |
| 287 | 303 |
| 288 // Counts the number of times Callback() has been run. | |
| 289 class CallbackCounter : public base::RefCountedThreadSafe<CallbackCounter> { | |
| 290 public: | |
| 291 CallbackCounter() : callback_count_(0) {} | |
| 292 | |
| 293 void Callback() { | |
| 294 ++callback_count_; | |
| 295 } | |
| 296 | |
| 297 int callback_count() { | |
| 298 return callback_count_; | |
| 299 } | |
| 300 | |
| 301 private: | |
| 302 friend class base::RefCountedThreadSafe<CallbackCounter>; | |
| 303 ~CallbackCounter() {} | |
| 304 | |
| 305 volatile int callback_count_; | |
| 306 }; | |
| 307 | |
| 308 // Test that we can get a completion callback after a Flush(). | |
| 309 TEST_F(SQLitePersistentCookieStoreTest, TestFlushCompletionCallback) { | |
| 310 InitializeStore(false); | |
| 311 // Put some data - any data - on disk, so that Flush is not a no-op. | |
| 312 AddCookie("A", "B", "foo.bar", "/", base::Time::Now()); | |
| 313 | |
| 314 scoped_refptr<CallbackCounter> counter(new CallbackCounter()); | |
| 315 | |
| 316 // Callback shouldn't be invoked until we call Flush(). | |
| 317 ASSERT_EQ(0, counter->callback_count()); | |
| 318 | |
| 319 store_->Flush(base::Bind(&CallbackCounter::Callback, counter.get())); | |
| 320 | |
| 321 scoped_refptr<base::ThreadTestHelper> helper( | |
| 322 new base::ThreadTestHelper( | |
| 323 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::DB))); | |
| 324 ASSERT_TRUE(helper->Run()); | |
| 325 | |
| 326 ASSERT_EQ(1, counter->callback_count()); | |
| 327 } | |
| 328 | |
| 329 // Test loading old session cookies from the disk. | 304 // Test loading old session cookies from the disk. |
| 330 TEST_F(SQLitePersistentCookieStoreTest, TestLoadOldSessionCookies) { | 305 TEST_F(SQLitePersistentCookieStoreTest, TestLoadOldSessionCookies) { |
| 331 InitializeStore(true); | 306 InitializeStore(true); |
| 332 | 307 |
| 333 // Add a session cookie. | 308 // Add a session cookie. |
| 334 store_->AddCookie( | 309 store_->AddCookie( |
| 335 net::CanonicalCookie( | 310 net::CanonicalCookie( |
| 336 GURL(), "C", "D", "sessioncookie.com", "/", std::string(), | 311 GURL(), "C", "D", "sessioncookie.com", "/", std::string(), |
| 337 std::string(), base::Time::Now(), base::Time(), | 312 std::string(), base::Time::Now(), base::Time(), |
| 338 base::Time::Now(), false, false)); | 313 base::Time::Now(), false, false)); |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 420 cookie_map.find(kSessionName); | 395 cookie_map.find(kSessionName); |
| 421 ASSERT_TRUE(it != cookie_map.end()); | 396 ASSERT_TRUE(it != cookie_map.end()); |
| 422 EXPECT_FALSE(cookie_map[kSessionName]->IsPersistent()); | 397 EXPECT_FALSE(cookie_map[kSessionName]->IsPersistent()); |
| 423 | 398 |
| 424 it = cookie_map.find(kPersistentName); | 399 it = cookie_map.find(kPersistentName); |
| 425 ASSERT_TRUE(it != cookie_map.end()); | 400 ASSERT_TRUE(it != cookie_map.end()); |
| 426 EXPECT_TRUE(cookie_map[kPersistentName]->IsPersistent()); | 401 EXPECT_TRUE(cookie_map[kPersistentName]->IsPersistent()); |
| 427 | 402 |
| 428 STLDeleteElements(&cookies); | 403 STLDeleteElements(&cookies); |
| 429 } | 404 } |
| OLD | NEW |