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(3, "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(3, "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()); |
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 |