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