OLD | NEW |
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 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 "base/basictypes.h" | 5 #include "base/basictypes.h" |
| 6 #include "base/scoped_temp_dir.h" |
6 #include "base/stl_util-inl.h" | 7 #include "base/stl_util-inl.h" |
7 #include "base/string_util.h" | 8 #include "base/string_util.h" |
8 #include "base/scoped_temp_dir.h" | |
9 #include "base/time.h" | 9 #include "base/time.h" |
10 #include "base/waitable_event.h" | 10 #include "base/waitable_event.h" |
| 11 #include "chrome/browser/password_manager/password_form_data.h" |
11 #include "chrome/browser/password_manager/password_store_change.h" | 12 #include "chrome/browser/password_manager/password_store_change.h" |
12 #include "chrome/browser/password_manager/password_store_default.h" | 13 #include "chrome/browser/password_manager/password_store_x.h" |
13 #include "chrome/browser/password_manager/password_form_data.h" | |
14 #include "chrome/browser/webdata/web_data_service.h" | 14 #include "chrome/browser/webdata/web_data_service.h" |
15 #include "chrome/common/notification_service.h" | 15 #include "chrome/common/notification_service.h" |
16 #include "chrome/common/pref_names.h" | 16 #include "chrome/common/pref_names.h" |
17 #include "chrome/test/testing_profile.h" | 17 #include "chrome/test/testing_profile.h" |
18 #include "testing/gmock/include/gmock/gmock.h" | 18 #include "testing/gmock/include/gmock/gmock.h" |
19 #include "testing/gtest/include/gtest/gtest.h" | 19 #include "testing/gtest/include/gtest/gtest.h" |
20 | 20 |
21 using base::WaitableEvent; | 21 using base::WaitableEvent; |
22 using testing::_; | 22 using testing::_; |
23 using testing::DoAll; | 23 using testing::DoAll; |
24 using testing::ElementsAreArray; | 24 using testing::ElementsAreArray; |
25 using testing::Pointee; | 25 using testing::Pointee; |
26 using testing::Property; | 26 using testing::Property; |
27 using testing::WithArg; | 27 using testing::WithArg; |
28 using webkit_glue::PasswordForm; | 28 using webkit_glue::PasswordForm; |
29 | 29 |
30 namespace { | 30 namespace { |
31 | 31 |
32 class MockPasswordStoreConsumer : public PasswordStoreConsumer { | 32 class MockPasswordStoreConsumer : public PasswordStoreConsumer { |
33 public: | 33 public: |
34 MOCK_METHOD2(OnPasswordStoreRequestDone, | 34 MOCK_METHOD2(OnPasswordStoreRequestDone, |
35 void(int, const std::vector<webkit_glue::PasswordForm*>&)); | 35 void(int, const std::vector<PasswordForm*>&)); |
36 }; | 36 }; |
37 | 37 |
38 class MockWebDataServiceConsumer : public WebDataServiceConsumer { | 38 class MockWebDataServiceConsumer : public WebDataServiceConsumer { |
39 public: | 39 public: |
40 MOCK_METHOD2(OnWebDataServiceRequestDone, void(WebDataService::Handle, | 40 MOCK_METHOD2(OnWebDataServiceRequestDone, void(WebDataService::Handle, |
41 const WDTypedResult*)); | 41 const WDTypedResult*)); |
42 }; | 42 }; |
43 | 43 |
44 class SignalingTask : public Task { | 44 class SignalingTask : public Task { |
45 public: | 45 public: |
46 explicit SignalingTask(WaitableEvent* event) : event_(event) { | 46 explicit SignalingTask(WaitableEvent* event) : event_(event) { |
47 } | 47 } |
48 virtual void Run() { | 48 virtual void Run() { |
49 event_->Signal(); | 49 event_->Signal(); |
50 } | 50 } |
51 private: | 51 private: |
52 WaitableEvent* event_; | 52 WaitableEvent* event_; |
53 }; | 53 }; |
54 | 54 |
55 class MockNotificationObserver : public NotificationObserver { | 55 class MockNotificationObserver : public NotificationObserver { |
56 public: | 56 public: |
57 MOCK_METHOD3(Observe, void(NotificationType, | 57 MOCK_METHOD3(Observe, void(NotificationType, |
58 const NotificationSource&, | 58 const NotificationSource&, |
59 const NotificationDetails&)); | 59 const NotificationDetails&)); |
60 }; | 60 }; |
61 | 61 |
62 // This class will add and remove a mock notification observer from | 62 // This class will add and remove a mock notification observer from |
63 // the DB thread. | 63 // the DB thread. |
64 class DBThreadObserverHelper : | 64 class DBThreadObserverHelper |
65 public base::RefCountedThreadSafe<DBThreadObserverHelper, | 65 : public base::RefCountedThreadSafe<DBThreadObserverHelper, |
66 ChromeThread::DeleteOnDBThread> { | 66 ChromeThread::DeleteOnDBThread> { |
67 public: | 67 public: |
68 DBThreadObserverHelper() : done_event_(true, false) {} | 68 DBThreadObserverHelper() : done_event_(true, false) {} |
69 | 69 |
70 void Init() { | 70 void Init() { |
71 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI)); | 71 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI)); |
72 ChromeThread::PostTask( | 72 ChromeThread::PostTask( |
73 ChromeThread::DB, | 73 ChromeThread::DB, |
74 FROM_HERE, | 74 FROM_HERE, |
75 NewRunnableMethod(this, &DBThreadObserverHelper::AddObserverTask)); | 75 NewRunnableMethod(this, &DBThreadObserverHelper::AddObserverTask)); |
76 done_event_.Wait(); | 76 done_event_.Wait(); |
(...skipping 17 matching lines...) Expand all Loading... |
94 NotificationType::LOGINS_CHANGED, | 94 NotificationType::LOGINS_CHANGED, |
95 NotificationService::AllSources()); | 95 NotificationService::AllSources()); |
96 done_event_.Signal(); | 96 done_event_.Signal(); |
97 } | 97 } |
98 | 98 |
99 WaitableEvent done_event_; | 99 WaitableEvent done_event_; |
100 NotificationRegistrar registrar_; | 100 NotificationRegistrar registrar_; |
101 MockNotificationObserver observer_; | 101 MockNotificationObserver observer_; |
102 }; | 102 }; |
103 | 103 |
| 104 class FailingBackend : public PasswordStoreX::NativeBackend { |
| 105 public: |
| 106 virtual bool Init() { return true; } |
| 107 |
| 108 virtual bool AddLogin(const PasswordForm& form) { return false; } |
| 109 virtual bool UpdateLogin(const PasswordForm& form) { return false; } |
| 110 virtual bool RemoveLogin(const PasswordForm& form) { return false; } |
| 111 |
| 112 virtual bool RemoveLoginsCreatedBetween(const base::Time& delete_begin, |
| 113 const base::Time& delete_end) { |
| 114 return false; |
| 115 } |
| 116 |
| 117 virtual bool GetLogins(const PasswordForm& form, PasswordFormList* forms) { |
| 118 return false; |
| 119 } |
| 120 |
| 121 virtual bool GetLoginsCreatedBetween(const base::Time& get_begin, |
| 122 const base::Time& get_end, |
| 123 PasswordFormList* forms) { |
| 124 return false; |
| 125 } |
| 126 |
| 127 virtual bool GetAutofillableLogins(PasswordFormList* forms) { return false; } |
| 128 virtual bool GetBlacklistLogins(PasswordFormList* forms) { return false; } |
| 129 }; |
| 130 |
| 131 class MockBackend : public PasswordStoreX::NativeBackend { |
| 132 public: |
| 133 virtual bool Init() { return true; } |
| 134 |
| 135 virtual bool AddLogin(const PasswordForm& form) { |
| 136 all_forms_.push_back(form); |
| 137 return true; |
| 138 } |
| 139 |
| 140 virtual bool UpdateLogin(const PasswordForm& form) { |
| 141 for (size_t i = 0; i < all_forms_.size(); ++i) |
| 142 if (CompareForms(all_forms_[i], form, true)) |
| 143 all_forms_[i] = form; |
| 144 return true; |
| 145 } |
| 146 |
| 147 virtual bool RemoveLogin(const PasswordForm& form) { |
| 148 for (size_t i = 0; i < all_forms_.size(); ++i) |
| 149 if (CompareForms(all_forms_[i], form, false)) |
| 150 erase(i--); |
| 151 return true; |
| 152 } |
| 153 |
| 154 virtual bool RemoveLoginsCreatedBetween(const base::Time& delete_begin, |
| 155 const base::Time& delete_end) { |
| 156 for (size_t i = 0; i < all_forms_.size(); ++i) { |
| 157 if (delete_begin <= all_forms_[i].date_created && |
| 158 (delete_end.is_null() || all_forms_[i].date_created < delete_end)) |
| 159 erase(i--); |
| 160 } |
| 161 return true; |
| 162 } |
| 163 |
| 164 virtual bool GetLogins(const PasswordForm& form, PasswordFormList* forms) { |
| 165 for (size_t i = 0; i < all_forms_.size(); ++i) |
| 166 if (all_forms_[i].signon_realm == form.signon_realm) |
| 167 forms->push_back(new PasswordForm(all_forms_[i])); |
| 168 return true; |
| 169 } |
| 170 |
| 171 virtual bool GetLoginsCreatedBetween(const base::Time& get_begin, |
| 172 const base::Time& get_end, |
| 173 PasswordFormList* forms) { |
| 174 for (size_t i = 0; i < all_forms_.size(); ++i) |
| 175 if (get_begin <= all_forms_[i].date_created && |
| 176 (get_end.is_null() || all_forms_[i].date_created < get_end)) |
| 177 forms->push_back(new PasswordForm(all_forms_[i])); |
| 178 return true; |
| 179 } |
| 180 |
| 181 virtual bool GetAutofillableLogins(PasswordFormList* forms) { |
| 182 for (size_t i = 0; i < all_forms_.size(); ++i) |
| 183 if (!all_forms_[i].blacklisted_by_user) |
| 184 forms->push_back(new PasswordForm(all_forms_[i])); |
| 185 return true; |
| 186 } |
| 187 |
| 188 virtual bool GetBlacklistLogins(PasswordFormList* forms) { |
| 189 for (size_t i = 0; i < all_forms_.size(); ++i) |
| 190 if (all_forms_[i].blacklisted_by_user) |
| 191 forms->push_back(new PasswordForm(all_forms_[i])); |
| 192 return true; |
| 193 } |
| 194 |
| 195 private: |
| 196 void erase(size_t index) { |
| 197 if (index < all_forms_.size() - 1) |
| 198 all_forms_[index] = all_forms_[all_forms_.size() - 1]; |
| 199 all_forms_.pop_back(); |
| 200 } |
| 201 |
| 202 bool CompareForms(const PasswordForm& a, const PasswordForm& b, bool update) { |
| 203 // An update check doesn't care about the submit element. |
| 204 if (!update && a.submit_element != b.submit_element) |
| 205 return false; |
| 206 return a.origin == b.origin && |
| 207 a.password_element == b.password_element && |
| 208 a.signon_realm == b.signon_realm && |
| 209 a.username_element == b.username_element && |
| 210 a.username_value == b.username_value; |
| 211 } |
| 212 |
| 213 std::vector<PasswordForm> all_forms_; |
| 214 }; |
| 215 |
| 216 class MockLoginDatabaseReturn { |
| 217 public: |
| 218 MOCK_METHOD1(OnLoginDatabaseQueryDone, |
| 219 void(const std::vector<PasswordForm*>&)); |
| 220 }; |
| 221 |
| 222 class LoginDatabaseQueryTask : public Task { |
| 223 public: |
| 224 LoginDatabaseQueryTask(LoginDatabase* login_db, |
| 225 bool autofillable, |
| 226 MockLoginDatabaseReturn* mock_return) |
| 227 : login_db_(login_db), autofillable_(autofillable), |
| 228 mock_return_(mock_return) { |
| 229 } |
| 230 |
| 231 virtual void Run() { |
| 232 std::vector<PasswordForm*> forms; |
| 233 if (autofillable_) |
| 234 login_db_->GetAutofillableLogins(&forms); |
| 235 else |
| 236 login_db_->GetBlacklistLogins(&forms); |
| 237 mock_return_->OnLoginDatabaseQueryDone(forms); |
| 238 } |
| 239 |
| 240 private: |
| 241 LoginDatabase* login_db_; |
| 242 bool autofillable_; |
| 243 MockLoginDatabaseReturn* mock_return_; |
| 244 }; |
| 245 |
| 246 const PasswordFormData g_autofillable_data[] = { |
| 247 { PasswordForm::SCHEME_HTML, |
| 248 "http://foo.example.com", |
| 249 "http://foo.example.com/origin", |
| 250 "http://foo.example.com/action", |
| 251 L"submit_element", |
| 252 L"username_element", |
| 253 L"password_element", |
| 254 L"username_value", |
| 255 L"password_value", |
| 256 true, false, 1 }, |
| 257 { PasswordForm::SCHEME_HTML, |
| 258 "http://bar.example.com", |
| 259 "http://bar.example.com/origin", |
| 260 "http://bar.example.com/action", |
| 261 L"submit_element", |
| 262 L"username_element", |
| 263 L"password_element", |
| 264 L"username_value", |
| 265 L"password_value", |
| 266 true, false, 2 }, |
| 267 { PasswordForm::SCHEME_HTML, |
| 268 "http://baz.example.com", |
| 269 "http://baz.example.com/origin", |
| 270 "http://baz.example.com/action", |
| 271 L"submit_element", |
| 272 L"username_element", |
| 273 L"password_element", |
| 274 L"username_value", |
| 275 L"password_value", |
| 276 true, false, 3 }, |
| 277 }; |
| 278 const PasswordFormData g_blacklisted_data[] = { |
| 279 { PasswordForm::SCHEME_HTML, |
| 280 "http://blacklisted.example.com", |
| 281 "http://blacklisted.example.com/origin", |
| 282 "http://blacklisted.example.com/action", |
| 283 L"submit_element", |
| 284 L"username_element", |
| 285 L"password_element", |
| 286 NULL, |
| 287 NULL, |
| 288 false, false, 1 }, |
| 289 { PasswordForm::SCHEME_HTML, |
| 290 "http://blacklisted2.example.com", |
| 291 "http://blacklisted2.example.com/origin", |
| 292 "http://blacklisted2.example.com/action", |
| 293 L"submit_element", |
| 294 L"username_element", |
| 295 L"password_element", |
| 296 NULL, |
| 297 NULL, |
| 298 false, false, 2 }, |
| 299 }; |
| 300 |
104 } // anonymous namespace | 301 } // anonymous namespace |
105 | 302 |
106 typedef std::vector<PasswordForm*> VectorOfForms; | 303 typedef std::vector<PasswordForm*> VectorOfForms; |
107 | 304 |
108 class PasswordStoreDefaultTest : public testing::Test { | 305 // LoginDatabase isn't reference counted, but in these unit tests that won't be |
| 306 // a problem as it always outlives the threads we post tasks to. |
| 307 template<> |
| 308 struct RunnableMethodTraits<LoginDatabase> { |
| 309 void RetainCallee(LoginDatabase*) {} |
| 310 void ReleaseCallee(LoginDatabase*) {} |
| 311 }; |
| 312 |
| 313 enum BackendType { |
| 314 NO_BACKEND, |
| 315 FAILING_BACKEND, |
| 316 WORKING_BACKEND |
| 317 }; |
| 318 |
| 319 class PasswordStoreXTest : public testing::TestWithParam<BackendType> { |
109 protected: | 320 protected: |
110 PasswordStoreDefaultTest() | 321 PasswordStoreXTest() |
111 : ui_thread_(ChromeThread::UI, &message_loop_), | 322 : ui_thread_(ChromeThread::UI, &message_loop_), |
112 db_thread_(ChromeThread::DB) { | 323 db_thread_(ChromeThread::DB) { |
113 } | 324 } |
114 | 325 |
115 virtual void SetUp() { | 326 virtual void SetUp() { |
116 ASSERT_TRUE(db_thread_.Start()); | 327 ASSERT_TRUE(db_thread_.Start()); |
117 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); | 328 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); |
118 | 329 |
119 profile_.reset(new TestingProfile()); | 330 profile_.reset(new TestingProfile()); |
120 | 331 |
121 login_db_.reset(new LoginDatabase()); | 332 login_db_.reset(new LoginDatabase()); |
122 ASSERT_TRUE(login_db_->Init(temp_dir_.path().Append( | 333 ASSERT_TRUE(login_db_->Init(temp_dir_.path().Append( |
123 FILE_PATH_LITERAL("login_test")))); | 334 FILE_PATH_LITERAL("login_test")))); |
124 | 335 |
125 wds_ = new WebDataService(); | 336 wds_ = new WebDataService(); |
126 ASSERT_TRUE(wds_->Init(temp_dir_.path())); | 337 ASSERT_TRUE(wds_->Init(temp_dir_.path())); |
127 } | 338 } |
128 | 339 |
129 virtual void TearDown() { | 340 virtual void TearDown() { |
130 wds_->Shutdown(); | 341 wds_->Shutdown(); |
131 MessageLoop::current()->PostTask(FROM_HERE, new MessageLoop::QuitTask); | 342 MessageLoop::current()->PostTask(FROM_HERE, new MessageLoop::QuitTask); |
132 MessageLoop::current()->Run(); | 343 MessageLoop::current()->Run(); |
133 db_thread_.Stop(); | 344 db_thread_.Stop(); |
134 } | 345 } |
135 | 346 |
| 347 PasswordStoreX::NativeBackend* GetBackend() { |
| 348 switch (GetParam()) { |
| 349 case FAILING_BACKEND: |
| 350 return new FailingBackend(); |
| 351 case WORKING_BACKEND: |
| 352 return new MockBackend(); |
| 353 default: |
| 354 return NULL; |
| 355 } |
| 356 } |
| 357 |
136 MessageLoopForUI message_loop_; | 358 MessageLoopForUI message_loop_; |
137 ChromeThread ui_thread_; | 359 ChromeThread ui_thread_; |
138 ChromeThread db_thread_; // PasswordStore, WDS schedule work on this thread. | 360 ChromeThread db_thread_; // PasswordStore, WDS schedule work on this thread. |
139 | 361 |
140 scoped_ptr<LoginDatabase> login_db_; | 362 scoped_ptr<LoginDatabase> login_db_; |
141 scoped_ptr<TestingProfile> profile_; | 363 scoped_ptr<TestingProfile> profile_; |
142 scoped_refptr<WebDataService> wds_; | 364 scoped_refptr<WebDataService> wds_; |
143 ScopedTempDir temp_dir_; | 365 ScopedTempDir temp_dir_; |
144 }; | 366 }; |
145 | 367 |
146 ACTION(STLDeleteElements0) { | 368 ACTION(STLDeleteElements0) { |
147 STLDeleteContainerPointers(arg0.begin(), arg0.end()); | 369 STLDeleteContainerPointers(arg0.begin(), arg0.end()); |
148 } | 370 } |
149 | 371 |
150 ACTION(QuitUIMessageLoop) { | 372 ACTION(QuitUIMessageLoop) { |
151 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI)); | 373 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI)); |
152 MessageLoop::current()->Quit(); | 374 MessageLoop::current()->Quit(); |
153 } | 375 } |
154 | 376 |
155 MATCHER(EmptyWDResult, "") { | 377 MATCHER(EmptyWDResult, "") { |
156 return static_cast<const WDResult<std::vector<PasswordForm*> >*>( | 378 return static_cast<const WDResult<std::vector<PasswordForm*> >*>( |
157 arg)->GetValue().empty(); | 379 arg)->GetValue().empty(); |
158 } | 380 } |
159 | 381 |
160 TEST_F(PasswordStoreDefaultTest, Migration) { | 382 TEST_P(PasswordStoreXTest, WDSMigration) { |
161 PasswordFormData autofillable_data[] = { | |
162 { PasswordForm::SCHEME_HTML, | |
163 "http://foo.example.com", | |
164 "http://foo.example.com/origin", | |
165 "http://foo.example.com/action", | |
166 L"submit_element", | |
167 L"username_element", | |
168 L"password_element", | |
169 L"username_value", | |
170 L"password_value", | |
171 true, false, 1 }, | |
172 { PasswordForm::SCHEME_HTML, | |
173 "http://bar.example.com", | |
174 "http://bar.example.com/origin", | |
175 "http://bar.example.com/action", | |
176 L"submit_element", | |
177 L"username_element", | |
178 L"password_element", | |
179 L"username_value", | |
180 L"password_value", | |
181 true, false, 2 }, | |
182 { PasswordForm::SCHEME_HTML, | |
183 "http://baz.example.com", | |
184 "http://baz.example.com/origin", | |
185 "http://baz.example.com/action", | |
186 L"submit_element", | |
187 L"username_element", | |
188 L"password_element", | |
189 L"username_value", | |
190 L"password_value", | |
191 true, false, 3 }, | |
192 }; | |
193 PasswordFormData blacklisted_data[] = { | |
194 { PasswordForm::SCHEME_HTML, | |
195 "http://blacklisted.example.com", | |
196 "http://blacklisted.example.com/origin", | |
197 "http://blacklisted.example.com/action", | |
198 L"submit_element", | |
199 L"username_element", | |
200 L"password_element", | |
201 NULL, | |
202 NULL, | |
203 false, false, 1 }, | |
204 { PasswordForm::SCHEME_HTML, | |
205 "http://blacklisted2.example.com", | |
206 "http://blacklisted2.example.com/origin", | |
207 "http://blacklisted2.example.com/action", | |
208 L"submit_element", | |
209 L"username_element", | |
210 L"password_element", | |
211 NULL, | |
212 NULL, | |
213 false, false, 2 }, | |
214 }; | |
215 | |
216 VectorOfForms expected_autofillable; | 383 VectorOfForms expected_autofillable; |
217 for (unsigned int i = 0; i < ARRAYSIZE_UNSAFE(autofillable_data); ++i) { | 384 for (unsigned int i = 0; i < ARRAYSIZE_UNSAFE(g_autofillable_data); ++i) { |
218 expected_autofillable.push_back( | 385 expected_autofillable.push_back( |
219 CreatePasswordFormFromData(autofillable_data[i])); | 386 CreatePasswordFormFromData(g_autofillable_data[i])); |
220 } | 387 } |
221 | 388 |
222 VectorOfForms expected_blacklisted; | 389 VectorOfForms expected_blacklisted; |
223 for (unsigned int i = 0; i < ARRAYSIZE_UNSAFE(blacklisted_data); ++i) { | 390 for (unsigned int i = 0; i < ARRAYSIZE_UNSAFE(g_blacklisted_data); ++i) { |
224 expected_blacklisted.push_back( | 391 expected_blacklisted.push_back( |
225 CreatePasswordFormFromData(blacklisted_data[i])); | 392 CreatePasswordFormFromData(g_blacklisted_data[i])); |
226 } | 393 } |
227 | 394 |
228 // Populate the WDS with logins that should be migrated. | 395 // Populate the WDS with logins that should be migrated. |
229 for (VectorOfForms::iterator it = expected_autofillable.begin(); | 396 for (VectorOfForms::iterator it = expected_autofillable.begin(); |
230 it != expected_autofillable.end(); ++it) { | 397 it != expected_autofillable.end(); ++it) { |
231 wds_->AddLogin(**it); | 398 wds_->AddLogin(**it); |
232 } | 399 } |
233 for (VectorOfForms::iterator it = expected_blacklisted.begin(); | 400 for (VectorOfForms::iterator it = expected_blacklisted.begin(); |
234 it != expected_blacklisted.end(); ++it) { | 401 it != expected_blacklisted.end(); ++it) { |
235 wds_->AddLogin(**it); | 402 wds_->AddLogin(**it); |
236 } | 403 } |
237 | 404 |
238 // The WDS schedules tasks to run on the DB thread so we schedule yet another | 405 // The WDS schedules tasks to run on the DB thread so we schedule yet another |
239 // task to notify us that it's safe to carry on with the test. | 406 // task to notify us that it's safe to carry on with the test. |
240 WaitableEvent done(false, false); | 407 WaitableEvent done(false, false); |
241 ChromeThread::PostTask(ChromeThread::DB, FROM_HERE, new SignalingTask(&done)); | 408 ChromeThread::PostTask(ChromeThread::DB, FROM_HERE, new SignalingTask(&done)); |
242 done.Wait(); | 409 done.Wait(); |
243 | 410 |
244 // Initializing the PasswordStore should trigger a migration. | 411 // Initializing the PasswordStore should trigger a migration. |
245 scoped_refptr<PasswordStoreDefault> store( | 412 scoped_refptr<PasswordStoreX> store( |
246 new PasswordStoreDefault(login_db_.release(), profile_.get(), wds_.get()))
; | 413 new PasswordStoreX(login_db_.release(), |
| 414 profile_.get(), |
| 415 wds_.get(), |
| 416 GetBackend())); |
247 store->Init(); | 417 store->Init(); |
248 | 418 |
249 // Check that the migration preference has not been initialized; | 419 // Check that the migration preference has not been initialized. |
250 ASSERT_TRUE(NULL == profile_->GetPrefs()->FindPreference( | 420 ASSERT_TRUE(NULL == profile_->GetPrefs()->FindPreference( |
251 prefs::kLoginDatabaseMigrated)); | 421 prefs::kLoginDatabaseMigrated)); |
252 | 422 |
253 // Again, the WDS schedules tasks to run on the DB thread, so schedule a task | 423 // Again, the WDS schedules tasks to run on the DB thread, so schedule a task |
254 // to signal us when it is safe to continue. | 424 // to signal us when it is safe to continue. |
255 ChromeThread::PostTask(ChromeThread::DB, FROM_HERE, new SignalingTask(&done)); | 425 ChromeThread::PostTask(ChromeThread::DB, FROM_HERE, new SignalingTask(&done)); |
256 done.Wait(); | 426 done.Wait(); |
257 | 427 |
258 // Let the WDS callbacks proceed so the logins can be migrated. | 428 // Let the WDS callbacks proceed so the logins can be migrated. |
259 MessageLoop::current()->RunAllPending(); | 429 MessageLoop::current()->RunAllPending(); |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
312 ChromeThread::PostTask(ChromeThread::DB, FROM_HERE, new SignalingTask(&done)); | 482 ChromeThread::PostTask(ChromeThread::DB, FROM_HERE, new SignalingTask(&done)); |
313 done.Wait(); | 483 done.Wait(); |
314 | 484 |
315 // Handle the callback from the WDS. | 485 // Handle the callback from the WDS. |
316 MessageLoop::current()->RunAllPending(); | 486 MessageLoop::current()->RunAllPending(); |
317 | 487 |
318 STLDeleteElements(&expected_autofillable); | 488 STLDeleteElements(&expected_autofillable); |
319 STLDeleteElements(&expected_blacklisted); | 489 STLDeleteElements(&expected_blacklisted); |
320 } | 490 } |
321 | 491 |
322 TEST_F(PasswordStoreDefaultTest, MigrationAlreadyDone) { | 492 TEST_P(PasswordStoreXTest, WDSMigrationAlreadyDone) { |
323 PasswordFormData wds_data[] = { | 493 PasswordFormData wds_data[] = { |
324 { PasswordForm::SCHEME_HTML, | 494 { PasswordForm::SCHEME_HTML, |
325 "http://bar.example.com", | 495 "http://bar.example.com", |
326 "http://bar.example.com/origin", | 496 "http://bar.example.com/origin", |
327 "http://bar.example.com/action", | 497 "http://bar.example.com/action", |
328 L"submit_element", | 498 L"submit_element", |
329 L"username_element", | 499 L"username_element", |
330 L"password_element", | 500 L"password_element", |
331 L"username_value", | 501 L"username_value", |
332 L"password_value", | 502 L"password_value", |
(...skipping 16 matching lines...) Expand all Loading... |
349 // task to notify us that it's safe to carry on with the test. | 519 // task to notify us that it's safe to carry on with the test. |
350 WaitableEvent done(false, false); | 520 WaitableEvent done(false, false); |
351 ChromeThread::PostTask(ChromeThread::DB, FROM_HERE, new SignalingTask(&done)); | 521 ChromeThread::PostTask(ChromeThread::DB, FROM_HERE, new SignalingTask(&done)); |
352 done.Wait(); | 522 done.Wait(); |
353 | 523 |
354 // Prentend that the migration has already taken place. | 524 // Prentend that the migration has already taken place. |
355 profile_->GetPrefs()->RegisterBooleanPref(prefs::kLoginDatabaseMigrated, | 525 profile_->GetPrefs()->RegisterBooleanPref(prefs::kLoginDatabaseMigrated, |
356 true); | 526 true); |
357 | 527 |
358 // Initializing the PasswordStore shouldn't trigger a migration. | 528 // Initializing the PasswordStore shouldn't trigger a migration. |
359 scoped_refptr<PasswordStoreDefault> store( | 529 scoped_refptr<PasswordStoreX> store( |
360 new PasswordStoreDefault(login_db_.release(), profile_.get(), | 530 new PasswordStoreX(login_db_.release(), |
361 wds_.get())); | 531 profile_.get(), |
| 532 wds_.get(), |
| 533 GetBackend())); |
362 store->Init(); | 534 store->Init(); |
363 | 535 |
364 MockPasswordStoreConsumer consumer; | 536 MockPasswordStoreConsumer consumer; |
365 // Make sure we quit the MessageLoop even if the test fails. | 537 // Make sure we quit the MessageLoop even if the test fails. |
366 ON_CALL(consumer, OnPasswordStoreRequestDone(_, _)) | 538 ON_CALL(consumer, OnPasswordStoreRequestDone(_, _)) |
367 .WillByDefault(QuitUIMessageLoop()); | 539 .WillByDefault(QuitUIMessageLoop()); |
368 | 540 |
369 // No forms should be migrated. | 541 // No forms should be migrated. |
370 VectorOfForms empty; | 542 VectorOfForms empty; |
371 EXPECT_CALL(consumer, | 543 EXPECT_CALL(consumer, |
372 OnPasswordStoreRequestDone(_, | 544 OnPasswordStoreRequestDone(_, |
373 ContainsAllPasswordForms(empty))) | 545 ContainsAllPasswordForms(empty))) |
374 .WillOnce(QuitUIMessageLoop()); | 546 .WillOnce(QuitUIMessageLoop()); |
375 | 547 |
376 store->GetAutofillableLogins(&consumer); | 548 store->GetAutofillableLogins(&consumer); |
377 MessageLoop::current()->Run(); | 549 MessageLoop::current()->Run(); |
378 | 550 |
379 STLDeleteElements(&unexpected_autofillable); | 551 STLDeleteElements(&unexpected_autofillable); |
380 } | 552 } |
381 | 553 |
382 TEST_F(PasswordStoreDefaultTest, Notifications) { | 554 TEST_P(PasswordStoreXTest, Notifications) { |
383 // Prentend that the migration has already taken place. | 555 // Pretend that the migration has already taken place. |
384 profile_->GetPrefs()->RegisterBooleanPref(prefs::kLoginDatabaseMigrated, | 556 profile_->GetPrefs()->RegisterBooleanPref(prefs::kLoginDatabaseMigrated, |
385 true); | 557 true); |
386 | 558 |
387 // Initializing the PasswordStore shouldn't trigger a migration. | 559 // Initializing the PasswordStore shouldn't trigger a migration. |
388 scoped_refptr<PasswordStoreDefault> store( | 560 scoped_refptr<PasswordStoreX> store( |
389 new PasswordStoreDefault(login_db_.release(), profile_.get(), | 561 new PasswordStoreX(login_db_.release(), |
390 wds_.get())); | 562 profile_.get(), |
| 563 wds_.get(), |
| 564 GetBackend())); |
391 store->Init(); | 565 store->Init(); |
392 | 566 |
393 PasswordFormData form_data = | 567 PasswordFormData form_data = |
394 { PasswordForm::SCHEME_HTML, | 568 { PasswordForm::SCHEME_HTML, |
395 "http://bar.example.com", | 569 "http://bar.example.com", |
396 "http://bar.example.com/origin", | 570 "http://bar.example.com/origin", |
397 "http://bar.example.com/action", | 571 "http://bar.example.com/action", |
398 L"submit_element", | 572 L"submit_element", |
399 L"username_element", | 573 L"username_element", |
400 L"password_element", | 574 L"password_element", |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
458 Pointee(ElementsAreArray( | 632 Pointee(ElementsAreArray( |
459 expected_delete_changes))))); | 633 expected_delete_changes))))); |
460 | 634 |
461 // Deleting the login should trigger a notification. | 635 // Deleting the login should trigger a notification. |
462 store->RemoveLogin(*form); | 636 store->RemoveLogin(*form); |
463 | 637 |
464 // Wait for PasswordStore to send the notification. | 638 // Wait for PasswordStore to send the notification. |
465 ChromeThread::PostTask(ChromeThread::DB, FROM_HERE, new SignalingTask(&done)); | 639 ChromeThread::PostTask(ChromeThread::DB, FROM_HERE, new SignalingTask(&done)); |
466 done.Wait(); | 640 done.Wait(); |
467 } | 641 } |
| 642 |
| 643 TEST_P(PasswordStoreXTest, NativeMigration) { |
| 644 VectorOfForms expected_autofillable; |
| 645 for (unsigned int i = 0; i < ARRAYSIZE_UNSAFE(g_autofillable_data); ++i) { |
| 646 expected_autofillable.push_back( |
| 647 CreatePasswordFormFromData(g_autofillable_data[i])); |
| 648 } |
| 649 |
| 650 VectorOfForms expected_blacklisted; |
| 651 for (unsigned int i = 0; i < ARRAYSIZE_UNSAFE(g_blacklisted_data); ++i) { |
| 652 expected_blacklisted.push_back( |
| 653 CreatePasswordFormFromData(g_blacklisted_data[i])); |
| 654 } |
| 655 |
| 656 LoginDatabase* login_db = login_db_.get(); |
| 657 |
| 658 // Populate the login DB with logins that should be migrated. |
| 659 for (VectorOfForms::iterator it = expected_autofillable.begin(); |
| 660 it != expected_autofillable.end(); ++it) { |
| 661 ChromeThread::PostTask(ChromeThread::DB, |
| 662 FROM_HERE, |
| 663 NewRunnableMethod(login_db, |
| 664 &LoginDatabase::AddLogin, |
| 665 **it)); |
| 666 } |
| 667 for (VectorOfForms::iterator it = expected_blacklisted.begin(); |
| 668 it != expected_blacklisted.end(); ++it) { |
| 669 ChromeThread::PostTask(ChromeThread::DB, |
| 670 FROM_HERE, |
| 671 NewRunnableMethod(login_db, |
| 672 &LoginDatabase::AddLogin, |
| 673 **it)); |
| 674 } |
| 675 |
| 676 // Schedule another task on the DB thread to notify us that it's safe to |
| 677 // carry on with the test. |
| 678 WaitableEvent done(false, false); |
| 679 ChromeThread::PostTask(ChromeThread::DB, FROM_HERE, new SignalingTask(&done)); |
| 680 done.Wait(); |
| 681 |
| 682 // Pretend that the WDS migration has already taken place. |
| 683 profile_->GetPrefs()->RegisterBooleanPref(prefs::kLoginDatabaseMigrated, |
| 684 true); |
| 685 |
| 686 // Initializing the PasswordStore shouldn't trigger a native migration (yet). |
| 687 scoped_refptr<PasswordStoreX> store( |
| 688 new PasswordStoreX(login_db_.release(), |
| 689 profile_.get(), |
| 690 wds_.get(), |
| 691 GetBackend())); |
| 692 store->Init(); |
| 693 |
| 694 MockPasswordStoreConsumer consumer; |
| 695 |
| 696 // Make sure we quit the MessageLoop even if the test fails. |
| 697 ON_CALL(consumer, OnPasswordStoreRequestDone(_, _)) |
| 698 .WillByDefault(QuitUIMessageLoop()); |
| 699 |
| 700 // The autofillable forms should have been migrated to the native backend. |
| 701 EXPECT_CALL(consumer, |
| 702 OnPasswordStoreRequestDone(_, |
| 703 ContainsAllPasswordForms(expected_autofillable))) |
| 704 .WillOnce(DoAll(WithArg<1>(STLDeleteElements0()), QuitUIMessageLoop())); |
| 705 |
| 706 store->GetAutofillableLogins(&consumer); |
| 707 MessageLoop::current()->Run(); |
| 708 |
| 709 // The blacklisted forms should have been migrated to the native backend. |
| 710 EXPECT_CALL(consumer, |
| 711 OnPasswordStoreRequestDone(_, |
| 712 ContainsAllPasswordForms(expected_blacklisted))) |
| 713 .WillOnce(DoAll(WithArg<1>(STLDeleteElements0()), QuitUIMessageLoop())); |
| 714 |
| 715 store->GetBlacklistLogins(&consumer); |
| 716 MessageLoop::current()->Run(); |
| 717 |
| 718 VectorOfForms empty; |
| 719 MockLoginDatabaseReturn ld_return; |
| 720 |
| 721 if (GetParam() == WORKING_BACKEND) { |
| 722 // No autofillable logins should be left in the login DB. |
| 723 EXPECT_CALL(ld_return, |
| 724 OnLoginDatabaseQueryDone(ContainsAllPasswordForms(empty))); |
| 725 } else { |
| 726 // The autofillable logins should still be in the login DB. |
| 727 EXPECT_CALL(ld_return, |
| 728 OnLoginDatabaseQueryDone( |
| 729 ContainsAllPasswordForms(expected_autofillable))) |
| 730 .WillOnce(WithArg<0>(STLDeleteElements0())); |
| 731 } |
| 732 |
| 733 ChromeThread::PostTask(ChromeThread::DB, FROM_HERE, |
| 734 new LoginDatabaseQueryTask(login_db, true, &ld_return)); |
| 735 |
| 736 // Wait for the login DB methods to execute on the DB thread. |
| 737 ChromeThread::PostTask(ChromeThread::DB, FROM_HERE, new SignalingTask(&done)); |
| 738 done.Wait(); |
| 739 |
| 740 if (GetParam() == WORKING_BACKEND) { |
| 741 // Likewise, no blacklisted logins should be left in the login DB. |
| 742 EXPECT_CALL(ld_return, |
| 743 OnLoginDatabaseQueryDone(ContainsAllPasswordForms(empty))); |
| 744 } else { |
| 745 // The blacklisted logins should still be in the login DB. |
| 746 EXPECT_CALL(ld_return, |
| 747 OnLoginDatabaseQueryDone( |
| 748 ContainsAllPasswordForms(expected_blacklisted))) |
| 749 .WillOnce(WithArg<0>(STLDeleteElements0())); |
| 750 } |
| 751 |
| 752 ChromeThread::PostTask(ChromeThread::DB, FROM_HERE, |
| 753 new LoginDatabaseQueryTask(login_db, false, &ld_return)); |
| 754 |
| 755 // Wait for the login DB methods to execute on the DB thread. |
| 756 ChromeThread::PostTask(ChromeThread::DB, FROM_HERE, new SignalingTask(&done)); |
| 757 done.Wait(); |
| 758 |
| 759 STLDeleteElements(&expected_autofillable); |
| 760 STLDeleteElements(&expected_blacklisted); |
| 761 } |
| 762 |
| 763 INSTANTIATE_TEST_CASE_P(NoBackend, |
| 764 PasswordStoreXTest, |
| 765 testing::Values(NO_BACKEND)); |
| 766 INSTANTIATE_TEST_CASE_P(FailingBackend, |
| 767 PasswordStoreXTest, |
| 768 testing::Values(FAILING_BACKEND)); |
| 769 INSTANTIATE_TEST_CASE_P(WorkingBackend, |
| 770 PasswordStoreXTest, |
| 771 testing::Values(WORKING_BACKEND)); |
OLD | NEW |