| 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 "base/basictypes.h" | 5 #include "base/basictypes.h" |
| 6 #include "base/bind.h" | 6 #include "base/bind.h" |
| 7 #include "base/bind_helpers.h" | 7 #include "base/bind_helpers.h" |
| 8 #include "base/file_util.h" | 8 #include "base/file_util.h" |
| 9 #include "base/files/scoped_temp_dir.h" | 9 #include "base/files/scoped_temp_dir.h" |
| 10 #include "base/platform_file.h" | 10 #include "base/platform_file.h" |
| 11 #include "base/prefs/pref_service.h" | 11 #include "base/prefs/pref_service.h" |
| 12 #include "base/run_loop.h" |
| 12 #include "base/stl_util.h" | 13 #include "base/stl_util.h" |
| 13 #include "base/strings/string_util.h" | 14 #include "base/strings/string_util.h" |
| 14 #include "base/strings/stringprintf.h" | 15 #include "base/strings/stringprintf.h" |
| 15 #include "base/strings/utf_string_conversions.h" | 16 #include "base/strings/utf_string_conversions.h" |
| 16 #include "base/synchronization/waitable_event.h" | |
| 17 #include "base/time/time.h" | 17 #include "base/time/time.h" |
| 18 #include "chrome/browser/chrome_notification_types.h" | 18 #include "chrome/browser/chrome_notification_types.h" |
| 19 #include "chrome/browser/password_manager/password_form_data.h" | 19 #include "chrome/browser/password_manager/password_form_data.h" |
| 20 #include "chrome/browser/password_manager/password_store_change.h" | 20 #include "chrome/browser/password_manager/password_store_change.h" |
| 21 #include "chrome/browser/password_manager/password_store_consumer.h" | 21 #include "chrome/browser/password_manager/password_store_consumer.h" |
| 22 #include "chrome/browser/password_manager/password_store_x.h" | 22 #include "chrome/browser/password_manager/password_store_x.h" |
| 23 #include "chrome/common/pref_names.h" | 23 #include "chrome/common/pref_names.h" |
| 24 #include "chrome/test/base/testing_browser_process.h" | 24 #include "chrome/test/base/testing_browser_process.h" |
| 25 #include "chrome/test/base/testing_profile.h" | 25 #include "chrome/test/base/testing_profile.h" |
| 26 #include "content/public/browser/browser_thread.h" |
| 26 #include "content/public/browser/notification_details.h" | 27 #include "content/public/browser/notification_details.h" |
| 27 #include "content/public/browser/notification_registrar.h" | 28 #include "content/public/browser/notification_registrar.h" |
| 28 #include "content/public/browser/notification_source.h" | 29 #include "content/public/browser/notification_source.h" |
| 29 #include "content/public/test/mock_notification_observer.h" | 30 #include "content/public/test/mock_notification_observer.h" |
| 30 #include "content/public/test/test_browser_thread.h" | 31 #include "content/public/test/test_browser_thread_bundle.h" |
| 31 #include "testing/gmock/include/gmock/gmock.h" | 32 #include "testing/gmock/include/gmock/gmock.h" |
| 32 #include "testing/gtest/include/gtest/gtest.h" | 33 #include "testing/gtest/include/gtest/gtest.h" |
| 33 | 34 |
| 34 using base::WaitableEvent; | |
| 35 using content::BrowserThread; | 35 using content::BrowserThread; |
| 36 using testing::_; | 36 using testing::_; |
| 37 using testing::DoAll; | 37 using testing::DoAll; |
| 38 using testing::ElementsAreArray; | 38 using testing::ElementsAreArray; |
| 39 using testing::Pointee; | 39 using testing::Pointee; |
| 40 using testing::Property; | 40 using testing::Property; |
| 41 using testing::WithArg; | 41 using testing::WithArg; |
| 42 using content::PasswordForm; | 42 using content::PasswordForm; |
| 43 | 43 |
| 44 typedef std::vector<PasswordForm*> VectorOfForms; | 44 typedef std::vector<PasswordForm*> VectorOfForms; |
| 45 | 45 |
| 46 namespace { | 46 namespace { |
| 47 | 47 |
| 48 class MockPasswordStoreConsumer : public PasswordStoreConsumer { | 48 class MockPasswordStoreConsumer : public PasswordStoreConsumer { |
| 49 public: | 49 public: |
| 50 MOCK_METHOD2(OnPasswordStoreRequestDone, | 50 MOCK_METHOD2(OnPasswordStoreRequestDone, |
| 51 void(CancelableRequestProvider::Handle, | 51 void(CancelableRequestProvider::Handle, |
| 52 const std::vector<PasswordForm*>&)); | 52 const std::vector<PasswordForm*>&)); |
| 53 MOCK_METHOD1(OnGetPasswordStoreResults, | 53 MOCK_METHOD1(OnGetPasswordStoreResults, |
| 54 void(const std::vector<PasswordForm*>&)); | 54 void(const std::vector<PasswordForm*>&)); |
| 55 }; | 55 }; |
| 56 | 56 |
| 57 // This class will add and remove a mock notification observer from | 57 // This class will add and remove a mock notification observer from |
| 58 // the DB thread. | 58 // the DB thread. |
| 59 class DBThreadObserverHelper | 59 class DBThreadObserverHelper { |
| 60 : public base::RefCountedThreadSafe<DBThreadObserverHelper, | |
| 61 BrowserThread::DeleteOnDBThread> { | |
| 62 public: | 60 public: |
| 63 DBThreadObserverHelper() : done_event_(true, false) {} | 61 DBThreadObserverHelper() {} |
| 62 |
| 63 ~DBThreadObserverHelper() { |
| 64 registrar_.RemoveAll(); |
| 65 } |
| 64 | 66 |
| 65 void Init(PasswordStore* password_store) { | 67 void Init(PasswordStore* password_store) { |
| 66 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 68 registrar_.Add(&observer_, |
| 67 BrowserThread::PostTask( | 69 chrome::NOTIFICATION_LOGINS_CHANGED, |
| 68 BrowserThread::DB, | 70 content::Source<PasswordStore>(password_store)); |
| 69 FROM_HERE, | |
| 70 base::Bind(&DBThreadObserverHelper::AddObserverTask, | |
| 71 this, make_scoped_refptr(password_store))); | |
| 72 done_event_.Wait(); | |
| 73 } | 71 } |
| 74 | 72 |
| 75 content::MockNotificationObserver& observer() { | 73 content::MockNotificationObserver& observer() { |
| 76 return observer_; | 74 return observer_; |
| 77 } | 75 } |
| 78 | 76 |
| 79 protected: | 77 private: |
| 80 friend struct BrowserThread::DeleteOnThread<BrowserThread::DB>; | |
| 81 friend class base::DeleteHelper<DBThreadObserverHelper>; | |
| 82 | |
| 83 virtual ~DBThreadObserverHelper() { | |
| 84 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); | |
| 85 registrar_.RemoveAll(); | |
| 86 } | |
| 87 | |
| 88 void AddObserverTask(PasswordStore* password_store) { | |
| 89 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); | |
| 90 registrar_.Add(&observer_, | |
| 91 chrome::NOTIFICATION_LOGINS_CHANGED, | |
| 92 content::Source<PasswordStore>(password_store)); | |
| 93 done_event_.Signal(); | |
| 94 } | |
| 95 | |
| 96 WaitableEvent done_event_; | |
| 97 content::NotificationRegistrar registrar_; | 78 content::NotificationRegistrar registrar_; |
| 98 content::MockNotificationObserver observer_; | 79 content::MockNotificationObserver observer_; |
| 99 }; | 80 }; |
| 100 | 81 |
| 101 class FailingBackend : public PasswordStoreX::NativeBackend { | 82 class FailingBackend : public PasswordStoreX::NativeBackend { |
| 102 public: | 83 public: |
| 103 virtual bool Init() OVERRIDE { return true; } | 84 virtual bool Init() OVERRIDE { return true; } |
| 104 | 85 |
| 105 virtual bool AddLogin(const PasswordForm& form) OVERRIDE { return false; } | 86 virtual bool AddLogin(const PasswordForm& form) OVERRIDE { return false; } |
| 106 virtual bool UpdateLogin(const PasswordForm& form) OVERRIDE { return false; } | 87 virtual bool UpdateLogin(const PasswordForm& form) OVERRIDE { return false; } |
| (...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 262 } // anonymous namespace | 243 } // anonymous namespace |
| 263 | 244 |
| 264 enum BackendType { | 245 enum BackendType { |
| 265 NO_BACKEND, | 246 NO_BACKEND, |
| 266 FAILING_BACKEND, | 247 FAILING_BACKEND, |
| 267 WORKING_BACKEND | 248 WORKING_BACKEND |
| 268 }; | 249 }; |
| 269 | 250 |
| 270 class PasswordStoreXTest : public testing::TestWithParam<BackendType> { | 251 class PasswordStoreXTest : public testing::TestWithParam<BackendType> { |
| 271 protected: | 252 protected: |
| 272 PasswordStoreXTest() | |
| 273 : ui_thread_(BrowserThread::UI, &message_loop_), | |
| 274 db_thread_(BrowserThread::DB) { | |
| 275 } | |
| 276 | |
| 277 virtual void SetUp() { | 253 virtual void SetUp() { |
| 278 ASSERT_TRUE(db_thread_.Start()); | |
| 279 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); | 254 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); |
| 280 | 255 |
| 281 profile_.reset(new TestingProfile()); | 256 profile_.reset(new TestingProfile()); |
| 282 | 257 |
| 283 login_db_.reset(new LoginDatabase()); | 258 login_db_.reset(new LoginDatabase()); |
| 284 ASSERT_TRUE(login_db_->Init(temp_dir_.path().Append("login_test"))); | 259 ASSERT_TRUE(login_db_->Init(temp_dir_.path().Append("login_test"))); |
| 285 } | 260 } |
| 286 | 261 |
| 287 virtual void TearDown() { | 262 virtual void TearDown() { |
| 288 base::MessageLoop::current()->PostTask(FROM_HERE, | 263 base::RunLoop().RunUntilIdle(); |
| 289 base::MessageLoop::QuitClosure()); | |
| 290 base::MessageLoop::current()->Run(); | |
| 291 db_thread_.Stop(); | |
| 292 } | 264 } |
| 293 | 265 |
| 294 PasswordStoreX::NativeBackend* GetBackend() { | 266 PasswordStoreX::NativeBackend* GetBackend() { |
| 295 switch (GetParam()) { | 267 switch (GetParam()) { |
| 296 case FAILING_BACKEND: | 268 case FAILING_BACKEND: |
| 297 return new FailingBackend(); | 269 return new FailingBackend(); |
| 298 case WORKING_BACKEND: | 270 case WORKING_BACKEND: |
| 299 return new MockBackend(); | 271 return new MockBackend(); |
| 300 default: | 272 default: |
| 301 return NULL; | 273 return NULL; |
| 302 } | 274 } |
| 303 } | 275 } |
| 304 | 276 |
| 305 base::MessageLoopForUI message_loop_; | 277 content::TestBrowserThreadBundle thread_bundle_; |
| 306 content::TestBrowserThread ui_thread_; | |
| 307 // PasswordStore, WDS schedule work on this thread. | |
| 308 content::TestBrowserThread db_thread_; | |
| 309 | 278 |
| 310 scoped_ptr<LoginDatabase> login_db_; | 279 scoped_ptr<LoginDatabase> login_db_; |
| 311 scoped_ptr<TestingProfile> profile_; | 280 scoped_ptr<TestingProfile> profile_; |
| 312 base::ScopedTempDir temp_dir_; | 281 base::ScopedTempDir temp_dir_; |
| 313 }; | 282 }; |
| 314 | 283 |
| 315 ACTION(STLDeleteElements0) { | 284 ACTION(STLDeleteElements0) { |
| 316 STLDeleteContainerPointers(arg0.begin(), arg0.end()); | 285 STLDeleteContainerPointers(arg0.begin(), arg0.end()); |
| 317 } | 286 } |
| 318 | 287 |
| 319 ACTION(QuitUIMessageLoop) { | |
| 320 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
| 321 base::MessageLoop::current()->Quit(); | |
| 322 } | |
| 323 | |
| 324 TEST_P(PasswordStoreXTest, Notifications) { | 288 TEST_P(PasswordStoreXTest, Notifications) { |
| 325 scoped_refptr<PasswordStoreX> store( | 289 scoped_refptr<PasswordStoreX> store( |
| 326 new PasswordStoreX(login_db_.release(), | 290 new PasswordStoreX(login_db_.release(), |
| 327 profile_.get(), | 291 profile_.get(), |
| 328 GetBackend())); | 292 GetBackend())); |
| 329 store->Init(); | 293 store->Init(); |
| 330 | 294 |
| 331 PasswordFormData form_data = | 295 PasswordFormData form_data = |
| 332 { PasswordForm::SCHEME_HTML, | 296 { PasswordForm::SCHEME_HTML, |
| 333 "http://bar.example.com", | 297 "http://bar.example.com", |
| 334 "http://bar.example.com/origin", | 298 "http://bar.example.com/origin", |
| 335 "http://bar.example.com/action", | 299 "http://bar.example.com/action", |
| 336 L"submit_element", | 300 L"submit_element", |
| 337 L"username_element", | 301 L"username_element", |
| 338 L"password_element", | 302 L"password_element", |
| 339 L"username_value", | 303 L"username_value", |
| 340 L"password_value", | 304 L"password_value", |
| 341 true, false, 1 }; | 305 true, false, 1 }; |
| 342 scoped_ptr<PasswordForm> form(CreatePasswordFormFromData(form_data)); | 306 scoped_ptr<PasswordForm> form(CreatePasswordFormFromData(form_data)); |
| 343 | 307 |
| 344 scoped_refptr<DBThreadObserverHelper> helper = new DBThreadObserverHelper; | 308 DBThreadObserverHelper helper; |
| 345 helper->Init(store.get()); | 309 helper.Init(store.get()); |
| 346 | 310 |
| 347 const PasswordStoreChange expected_add_changes[] = { | 311 const PasswordStoreChange expected_add_changes[] = { |
| 348 PasswordStoreChange(PasswordStoreChange::ADD, *form), | 312 PasswordStoreChange(PasswordStoreChange::ADD, *form), |
| 349 }; | 313 }; |
| 350 | 314 |
| 351 EXPECT_CALL( | 315 EXPECT_CALL( |
| 352 helper->observer(), | 316 helper.observer(), |
| 353 Observe(int(chrome::NOTIFICATION_LOGINS_CHANGED), | 317 Observe(int(chrome::NOTIFICATION_LOGINS_CHANGED), |
| 354 content::Source<PasswordStore>(store.get()), | 318 content::Source<PasswordStore>(store.get()), |
| 355 Property(&content::Details<const PasswordStoreChangeList>::ptr, | 319 Property(&content::Details<const PasswordStoreChangeList>::ptr, |
| 356 Pointee(ElementsAreArray(expected_add_changes))))); | 320 Pointee(ElementsAreArray(expected_add_changes))))); |
| 357 | 321 |
| 358 // Adding a login should trigger a notification. | 322 // Adding a login should trigger a notification. |
| 359 store->AddLogin(*form); | 323 store->AddLogin(*form); |
| 360 | 324 |
| 361 // The PasswordStore schedules tasks to run on the DB thread so we schedule | 325 // The PasswordStore schedules tasks to run on the DB thread. Wait for them |
| 362 // yet another task to notify us that it's safe to carry on with the test. | 326 // to complete. |
| 363 WaitableEvent done(false, false); | 327 base::RunLoop().RunUntilIdle(); |
| 364 BrowserThread::PostTask(BrowserThread::DB, FROM_HERE, | |
| 365 base::Bind(&WaitableEvent::Signal, base::Unretained(&done))); | |
| 366 done.Wait(); | |
| 367 | 328 |
| 368 // Change the password. | 329 // Change the password. |
| 369 form->password_value = WideToUTF16(L"a different password"); | 330 form->password_value = WideToUTF16(L"a different password"); |
| 370 | 331 |
| 371 const PasswordStoreChange expected_update_changes[] = { | 332 const PasswordStoreChange expected_update_changes[] = { |
| 372 PasswordStoreChange(PasswordStoreChange::UPDATE, *form), | 333 PasswordStoreChange(PasswordStoreChange::UPDATE, *form), |
| 373 }; | 334 }; |
| 374 | 335 |
| 375 EXPECT_CALL( | 336 EXPECT_CALL( |
| 376 helper->observer(), | 337 helper.observer(), |
| 377 Observe(int(chrome::NOTIFICATION_LOGINS_CHANGED), | 338 Observe(int(chrome::NOTIFICATION_LOGINS_CHANGED), |
| 378 content::Source<PasswordStore>(store.get()), | 339 content::Source<PasswordStore>(store.get()), |
| 379 Property(&content::Details<const PasswordStoreChangeList>::ptr, | 340 Property(&content::Details<const PasswordStoreChangeList>::ptr, |
| 380 Pointee(ElementsAreArray(expected_update_changes))))); | 341 Pointee(ElementsAreArray(expected_update_changes))))); |
| 381 | 342 |
| 382 // Updating the login with the new password should trigger a notification. | 343 // Updating the login with the new password should trigger a notification. |
| 383 store->UpdateLogin(*form); | 344 store->UpdateLogin(*form); |
| 384 | 345 |
| 385 // Wait for PasswordStore to send the notification. | 346 // Wait for PasswordStore to send execute. |
| 386 BrowserThread::PostTask(BrowserThread::DB, FROM_HERE, | 347 base::RunLoop().RunUntilIdle(); |
| 387 base::Bind(&WaitableEvent::Signal, base::Unretained(&done))); | |
| 388 done.Wait(); | |
| 389 | 348 |
| 390 const PasswordStoreChange expected_delete_changes[] = { | 349 const PasswordStoreChange expected_delete_changes[] = { |
| 391 PasswordStoreChange(PasswordStoreChange::REMOVE, *form), | 350 PasswordStoreChange(PasswordStoreChange::REMOVE, *form), |
| 392 }; | 351 }; |
| 393 | 352 |
| 394 EXPECT_CALL( | 353 EXPECT_CALL( |
| 395 helper->observer(), | 354 helper.observer(), |
| 396 Observe(int(chrome::NOTIFICATION_LOGINS_CHANGED), | 355 Observe(int(chrome::NOTIFICATION_LOGINS_CHANGED), |
| 397 content::Source<PasswordStore>(store.get()), | 356 content::Source<PasswordStore>(store.get()), |
| 398 Property(&content::Details<const PasswordStoreChangeList>::ptr, | 357 Property(&content::Details<const PasswordStoreChangeList>::ptr, |
| 399 Pointee(ElementsAreArray(expected_delete_changes))))); | 358 Pointee(ElementsAreArray(expected_delete_changes))))); |
| 400 | 359 |
| 401 // Deleting the login should trigger a notification. | 360 // Deleting the login should trigger a notification. |
| 402 store->RemoveLogin(*form); | 361 store->RemoveLogin(*form); |
| 403 | 362 |
| 404 // Wait for PasswordStore to send the notification. | 363 // Wait for PasswordStore to execute. |
| 405 BrowserThread::PostTask(BrowserThread::DB, FROM_HERE, | 364 base::RunLoop().RunUntilIdle(); |
| 406 base::Bind(&WaitableEvent::Signal, base::Unretained(&done))); | |
| 407 done.Wait(); | |
| 408 | 365 |
| 409 // Public in PasswordStore, protected in PasswordStoreX. | 366 // Public in PasswordStore, protected in PasswordStoreX. |
| 410 static_cast<PasswordStore*>(store.get())->ShutdownOnUIThread(); | 367 static_cast<PasswordStore*>(store.get())->ShutdownOnUIThread(); |
| 411 } | 368 } |
| 412 | 369 |
| 413 TEST_P(PasswordStoreXTest, NativeMigration) { | 370 TEST_P(PasswordStoreXTest, NativeMigration) { |
| 414 VectorOfForms expected_autofillable; | 371 VectorOfForms expected_autofillable; |
| 415 InitExpectedForms(true, 50, &expected_autofillable); | 372 InitExpectedForms(true, 50, &expected_autofillable); |
| 416 | 373 |
| 417 VectorOfForms expected_blacklisted; | 374 VectorOfForms expected_blacklisted; |
| 418 InitExpectedForms(false, 50, &expected_blacklisted); | 375 InitExpectedForms(false, 50, &expected_blacklisted); |
| 419 | 376 |
| 420 // Get the initial size of the login DB file, before we populate it. | 377 // Get the initial size of the login DB file, before we populate it. |
| 421 // This will be used later to make sure it gets back to this size. | 378 // This will be used later to make sure it gets back to this size. |
| 422 const base::FilePath login_db_file = temp_dir_.path().Append("login_test"); | 379 const base::FilePath login_db_file = temp_dir_.path().Append("login_test"); |
| 423 base::PlatformFileInfo db_file_start_info; | 380 base::PlatformFileInfo db_file_start_info; |
| 424 ASSERT_TRUE(file_util::GetFileInfo(login_db_file, &db_file_start_info)); | 381 ASSERT_TRUE(file_util::GetFileInfo(login_db_file, &db_file_start_info)); |
| 425 | 382 |
| 426 LoginDatabase* login_db = login_db_.get(); | 383 LoginDatabase* login_db = login_db_.get(); |
| 427 | 384 |
| 428 // Populate the login DB with logins that should be migrated. | 385 // Populate the login DB with logins that should be migrated. |
| 429 for (VectorOfForms::iterator it = expected_autofillable.begin(); | 386 for (VectorOfForms::iterator it = expected_autofillable.begin(); |
| 430 it != expected_autofillable.end(); ++it) { | 387 it != expected_autofillable.end(); ++it) { |
| 431 BrowserThread::PostTask(BrowserThread::DB, FROM_HERE, | 388 login_db->AddLogin(**it); |
| 432 base::Bind( | |
| 433 base::IgnoreResult(&LoginDatabase::AddLogin), | |
| 434 base::Unretained(login_db), **it)); | |
| 435 } | 389 } |
| 436 for (VectorOfForms::iterator it = expected_blacklisted.begin(); | 390 for (VectorOfForms::iterator it = expected_blacklisted.begin(); |
| 437 it != expected_blacklisted.end(); ++it) { | 391 it != expected_blacklisted.end(); ++it) { |
| 438 BrowserThread::PostTask(BrowserThread::DB, FROM_HERE, | 392 login_db->AddLogin(**it); |
| 439 base::Bind( | |
| 440 base::IgnoreResult(&LoginDatabase::AddLogin), | |
| 441 base::Unretained(login_db), **it)); | |
| 442 } | 393 } |
| 443 | 394 |
| 444 // Schedule another task on the DB thread to notify us that it's safe to | |
| 445 // carry on with the test. | |
| 446 WaitableEvent done(false, false); | |
| 447 BrowserThread::PostTask(BrowserThread::DB, FROM_HERE, | |
| 448 base::Bind(&WaitableEvent::Signal, base::Unretained(&done))); | |
| 449 done.Wait(); | |
| 450 | |
| 451 // Get the new size of the login DB file. We expect it to be larger. | 395 // Get the new size of the login DB file. We expect it to be larger. |
| 452 base::PlatformFileInfo db_file_full_info; | 396 base::PlatformFileInfo db_file_full_info; |
| 453 ASSERT_TRUE(file_util::GetFileInfo(login_db_file, &db_file_full_info)); | 397 ASSERT_TRUE(file_util::GetFileInfo(login_db_file, &db_file_full_info)); |
| 454 EXPECT_GT(db_file_full_info.size, db_file_start_info.size); | 398 EXPECT_GT(db_file_full_info.size, db_file_start_info.size); |
| 455 | 399 |
| 456 // Initializing the PasswordStore shouldn't trigger a native migration (yet). | 400 // Initializing the PasswordStore shouldn't trigger a native migration (yet). |
| 457 scoped_refptr<PasswordStoreX> store( | 401 scoped_refptr<PasswordStoreX> store( |
| 458 new PasswordStoreX(login_db_.release(), | 402 new PasswordStoreX(login_db_.release(), |
| 459 profile_.get(), | 403 profile_.get(), |
| 460 GetBackend())); | 404 GetBackend())); |
| 461 store->Init(); | 405 store->Init(); |
| 462 | 406 |
| 463 MockPasswordStoreConsumer consumer; | 407 MockPasswordStoreConsumer consumer; |
| 464 | 408 |
| 465 // Make sure we quit the MessageLoop even if the test fails. | |
| 466 ON_CALL(consumer, OnPasswordStoreRequestDone(_, _)) | |
| 467 .WillByDefault(QuitUIMessageLoop()); | |
| 468 | |
| 469 // The autofillable forms should have been migrated to the native backend. | 409 // The autofillable forms should have been migrated to the native backend. |
| 470 EXPECT_CALL(consumer, | 410 EXPECT_CALL(consumer, |
| 471 OnPasswordStoreRequestDone(_, | 411 OnPasswordStoreRequestDone(_, |
| 472 ContainsAllPasswordForms(expected_autofillable))) | 412 ContainsAllPasswordForms(expected_autofillable))) |
| 473 .WillOnce(DoAll(WithArg<1>(STLDeleteElements0()), QuitUIMessageLoop())); | 413 .WillOnce(WithArg<1>(STLDeleteElements0())); |
| 474 | 414 |
| 475 store->GetAutofillableLogins(&consumer); | 415 store->GetAutofillableLogins(&consumer); |
| 476 base::MessageLoop::current()->Run(); | 416 base::RunLoop().RunUntilIdle(); |
| 477 | 417 |
| 478 // The blacklisted forms should have been migrated to the native backend. | 418 // The blacklisted forms should have been migrated to the native backend. |
| 479 EXPECT_CALL(consumer, | 419 EXPECT_CALL(consumer, |
| 480 OnPasswordStoreRequestDone(_, | 420 OnPasswordStoreRequestDone(_, |
| 481 ContainsAllPasswordForms(expected_blacklisted))) | 421 ContainsAllPasswordForms(expected_blacklisted))) |
| 482 .WillOnce(DoAll(WithArg<1>(STLDeleteElements0()), QuitUIMessageLoop())); | 422 .WillOnce(WithArg<1>(STLDeleteElements0())); |
| 483 | 423 |
| 484 store->GetBlacklistLogins(&consumer); | 424 store->GetBlacklistLogins(&consumer); |
| 485 base::MessageLoop::current()->Run(); | 425 base::RunLoop().RunUntilIdle(); |
| 486 | 426 |
| 487 VectorOfForms empty; | 427 VectorOfForms empty; |
| 488 MockLoginDatabaseReturn ld_return; | 428 MockLoginDatabaseReturn ld_return; |
| 489 | 429 |
| 490 if (GetParam() == WORKING_BACKEND) { | 430 if (GetParam() == WORKING_BACKEND) { |
| 491 // No autofillable logins should be left in the login DB. | 431 // No autofillable logins should be left in the login DB. |
| 492 EXPECT_CALL(ld_return, | 432 EXPECT_CALL(ld_return, |
| 493 OnLoginDatabaseQueryDone(ContainsAllPasswordForms(empty))); | 433 OnLoginDatabaseQueryDone(ContainsAllPasswordForms(empty))); |
| 494 } else { | 434 } else { |
| 495 // The autofillable logins should still be in the login DB. | 435 // The autofillable logins should still be in the login DB. |
| 496 EXPECT_CALL(ld_return, | 436 EXPECT_CALL(ld_return, |
| 497 OnLoginDatabaseQueryDone( | 437 OnLoginDatabaseQueryDone( |
| 498 ContainsAllPasswordForms(expected_autofillable))) | 438 ContainsAllPasswordForms(expected_autofillable))) |
| 499 .WillOnce(WithArg<0>(STLDeleteElements0())); | 439 .WillOnce(WithArg<0>(STLDeleteElements0())); |
| 500 } | 440 } |
| 501 | 441 |
| 502 BrowserThread::PostTask( | 442 LoginDatabaseQueryCallback(login_db, true, &ld_return); |
| 503 BrowserThread::DB, FROM_HERE, | |
| 504 base::Bind(&LoginDatabaseQueryCallback, login_db, true, &ld_return)); | |
| 505 | 443 |
| 506 // Wait for the login DB methods to execute on the DB thread. | 444 // Wait for the login DB methods to execute. |
| 507 BrowserThread::PostTask(BrowserThread::DB, FROM_HERE, | 445 base::RunLoop().RunUntilIdle(); |
| 508 base::Bind(&WaitableEvent::Signal, base::Unretained(&done))); | |
| 509 done.Wait(); | |
| 510 | 446 |
| 511 if (GetParam() == WORKING_BACKEND) { | 447 if (GetParam() == WORKING_BACKEND) { |
| 512 // Likewise, no blacklisted logins should be left in the login DB. | 448 // Likewise, no blacklisted logins should be left in the login DB. |
| 513 EXPECT_CALL(ld_return, | 449 EXPECT_CALL(ld_return, |
| 514 OnLoginDatabaseQueryDone(ContainsAllPasswordForms(empty))); | 450 OnLoginDatabaseQueryDone(ContainsAllPasswordForms(empty))); |
| 515 } else { | 451 } else { |
| 516 // The blacklisted logins should still be in the login DB. | 452 // The blacklisted logins should still be in the login DB. |
| 517 EXPECT_CALL(ld_return, | 453 EXPECT_CALL(ld_return, |
| 518 OnLoginDatabaseQueryDone( | 454 OnLoginDatabaseQueryDone( |
| 519 ContainsAllPasswordForms(expected_blacklisted))) | 455 ContainsAllPasswordForms(expected_blacklisted))) |
| 520 .WillOnce(WithArg<0>(STLDeleteElements0())); | 456 .WillOnce(WithArg<0>(STLDeleteElements0())); |
| 521 } | 457 } |
| 522 | 458 |
| 523 BrowserThread::PostTask( | 459 LoginDatabaseQueryCallback(login_db, false, &ld_return); |
| 524 BrowserThread::DB, FROM_HERE, | |
| 525 base::Bind(&LoginDatabaseQueryCallback, login_db, false, &ld_return)); | |
| 526 | 460 |
| 527 // Wait for the login DB methods to execute on the DB thread. | 461 // Wait for the login DB methods to execute. |
| 528 BrowserThread::PostTask(BrowserThread::DB, FROM_HERE, | 462 base::RunLoop().RunUntilIdle(); |
| 529 base::Bind(&WaitableEvent::Signal, base::Unretained(&done))); | |
| 530 done.Wait(); | |
| 531 | 463 |
| 532 if (GetParam() == WORKING_BACKEND) { | 464 if (GetParam() == WORKING_BACKEND) { |
| 533 // If the migration succeeded, then not only should there be no logins left | 465 // If the migration succeeded, then not only should there be no logins left |
| 534 // in the login DB, but also the file should have been deleted and then | 466 // in the login DB, but also the file should have been deleted and then |
| 535 // recreated. We approximate checking for this by checking that the file | 467 // recreated. We approximate checking for this by checking that the file |
| 536 // size is equal to the size before we populated it, even though it was | 468 // size is equal to the size before we populated it, even though it was |
| 537 // larger after populating it. | 469 // larger after populating it. |
| 538 base::PlatformFileInfo db_file_end_info; | 470 base::PlatformFileInfo db_file_end_info; |
| 539 ASSERT_TRUE(file_util::GetFileInfo(login_db_file, &db_file_end_info)); | 471 ASSERT_TRUE(file_util::GetFileInfo(login_db_file, &db_file_end_info)); |
| 540 EXPECT_EQ(db_file_start_info.size, db_file_end_info.size); | 472 EXPECT_EQ(db_file_start_info.size, db_file_end_info.size); |
| 541 } | 473 } |
| 542 | 474 |
| 543 STLDeleteElements(&expected_autofillable); | 475 STLDeleteElements(&expected_autofillable); |
| 544 STLDeleteElements(&expected_blacklisted); | 476 STLDeleteElements(&expected_blacklisted); |
| 545 | 477 |
| 546 // Public in PasswordStore, protected in PasswordStoreX. | 478 // Public in PasswordStore, protected in PasswordStoreX. |
| 547 static_cast<PasswordStore*>(store.get())->ShutdownOnUIThread(); | 479 static_cast<PasswordStore*>(store.get())->ShutdownOnUIThread(); |
| 548 } | 480 } |
| 549 | 481 |
| 550 INSTANTIATE_TEST_CASE_P(NoBackend, | 482 INSTANTIATE_TEST_CASE_P(NoBackend, |
| 551 PasswordStoreXTest, | 483 PasswordStoreXTest, |
| 552 testing::Values(NO_BACKEND)); | 484 testing::Values(NO_BACKEND)); |
| 553 INSTANTIATE_TEST_CASE_P(FailingBackend, | 485 INSTANTIATE_TEST_CASE_P(FailingBackend, |
| 554 PasswordStoreXTest, | 486 PasswordStoreXTest, |
| 555 testing::Values(FAILING_BACKEND)); | 487 testing::Values(FAILING_BACKEND)); |
| 556 INSTANTIATE_TEST_CASE_P(WorkingBackend, | 488 INSTANTIATE_TEST_CASE_P(WorkingBackend, |
| 557 PasswordStoreXTest, | 489 PasswordStoreXTest, |
| 558 testing::Values(WORKING_BACKEND)); | 490 testing::Values(WORKING_BACKEND)); |
| OLD | NEW |