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 |