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 3 // found in the LICENSE file. 4 5 #include "base/memory/scoped_ptr.h" 6 #include "base/message_loop/message_loop.h" 7 #include "base/prefs/pref_registry_simple.h" 8 #include "base/prefs/pref_service.h" 9 #include "base/prefs/testing_pref_service.h" 10 #include "base/run_loop.h" 11 #include "base/strings/string_util.h" 12 #include "base/strings/utf_string_conversions.h" 13 #include "components/autofill/core/common/password_form.h" 14 #include "components/password_manager/core/browser/mock_password_store.h" 15 #include "components/password_manager/core/browser/password_form_manager.h" 16 #include "components/password_manager/core/browser/password_manager.h" 17 #include "components/password_manager/core/browser/password_manager_driver.h" 18 #include "components/password_manager/core/browser/password_store.h" 19 #include "components/password_manager/core/browser/stub_password_manager_client.h" 20 #include "components/password_manager/core/browser/stub_password_manager_driver.h" 21 #include "components/password_manager/core/browser/test_password_store.h" 22 #include "components/password_manager/core/common/password_manager_pref_names.h" 23 #include "testing/gmock/include/gmock/gmock.h" 24 #include "testing/gtest/include/gtest/gtest.h" 25 26 using autofill::PasswordForm; 27 using base::ASCIIToUTF16; 28 using ::testing::_; 29 using ::testing::Eq; 30 using ::testing::Mock; 31 using ::testing::Return; 32 33 namespace autofill { 34 class AutofillManager; 35 } 36 37 namespace password_manager { 38 39 namespace { 40 41 void RunAllPendingTasks() { 42 base::RunLoop run_loop; 43 base::MessageLoop::current()->PostTask( 44 FROM_HERE, base::MessageLoop::QuitWhenIdleClosure()); 45 run_loop.Run(); 46 } 47 48 class MockPasswordManagerDriver : public StubPasswordManagerDriver { 49 public: 50 MOCK_METHOD0(IsOffTheRecord, bool()); 51 MOCK_METHOD1(AllowPasswordGenerationForForm, void(autofill::PasswordForm*)); 52 }; 53 54 class TestPasswordManagerClient : public StubPasswordManagerClient { 55 public: 56 explicit TestPasswordManagerClient(PasswordStore* password_store) 57 : password_store_(password_store) { 58 prefs_.registry()->RegisterBooleanPref(prefs::kPasswordManagerEnabled, 59 true); 60 } 61 62 virtual void PromptUserToSavePassword(PasswordFormManager* form_to_save) 63 OVERRIDE {} 64 virtual PrefService* GetPrefs() OVERRIDE { return &prefs_; } 65 virtual PasswordStore* GetPasswordStore() OVERRIDE { return password_store_; } 66 virtual PasswordManagerDriver* GetDriver() OVERRIDE { return &driver_; } 67 virtual void AuthenticateAutofillAndFillForm( 68 scoped_ptr<autofill::PasswordFormFillData> fill_data) OVERRIDE { 69 driver_.FillPasswordForm(*fill_data.get()); 70 } 71 72 MockPasswordManagerDriver* GetMockDriver() { return &driver_; } 73 74 private: 75 TestingPrefServiceSimple prefs_; 76 PasswordStore* password_store_; 77 MockPasswordManagerDriver driver_; 78 }; 79 80 class TestPasswordManager : public PasswordManager { 81 public: 82 explicit TestPasswordManager(PasswordManagerClient* client) 83 : PasswordManager(client) {} 84 85 virtual void Autofill(const autofill::PasswordForm& form_for_autofill, 86 const autofill::PasswordFormMap& best_matches, 87 const autofill::PasswordForm& preferred_match, 88 bool wait_for_username) const OVERRIDE { 89 best_matches_ = best_matches; 90 } 91 92 const autofill::PasswordFormMap& GetLatestBestMatches() { 93 return best_matches_; 94 } 95 96 private: 97 // Marked mutable to get around constness of Autofill(). 98 mutable autofill::PasswordFormMap best_matches_; 99 }; 100 101 } // namespace 102 103 class PasswordFormManagerTest : public testing::Test { 104 public: 105 PasswordFormManagerTest() {} 106 107 virtual void SetUp() { 108 observed_form_.origin = GURL("http://accounts.google.com/a/LoginAuth"); 109 observed_form_.action = GURL("http://accounts.google.com/a/Login"); 110 observed_form_.username_element = ASCIIToUTF16("Email"); 111 observed_form_.password_element = ASCIIToUTF16("Passwd"); 112 observed_form_.submit_element = ASCIIToUTF16("signIn"); 113 observed_form_.signon_realm = "http://accounts.google.com"; 114 115 saved_match_ = observed_form_; 116 saved_match_.origin = GURL("http://accounts.google.com/a/ServiceLoginAuth"); 117 saved_match_.action = GURL("http://accounts.google.com/a/ServiceLogin"); 118 saved_match_.preferred = true; 119 saved_match_.username_value = ASCIIToUTF16("test (at) gmail.com"); 120 saved_match_.password_value = ASCIIToUTF16("test1"); 121 saved_match_.other_possible_usernames.push_back( 122 ASCIIToUTF16("test2 (at) gmail.com")); 123 } 124 125 virtual void TearDown() { 126 if (mock_store_) 127 mock_store_->Shutdown(); 128 } 129 130 void InitializeMockStore() { 131 if (!mock_store_) { 132 mock_store_ = new MockPasswordStore(); 133 ASSERT_TRUE(mock_store_); 134 } 135 } 136 137 MockPasswordStore* mock_store() const { return mock_store_.get(); } 138 139 PasswordForm* GetPendingCredentials(PasswordFormManager* p) { 140 return &p->pending_credentials_; 141 } 142 143 void SimulateMatchingPhase(PasswordFormManager* p, bool find_match) { 144 // Roll up the state to mock out the matching phase. 145 p->state_ = PasswordFormManager::POST_MATCHING_PHASE; 146 if (!find_match) 147 return; 148 149 PasswordForm* match = new PasswordForm(saved_match_); 150 // Heap-allocated form is owned by p. 151 p->best_matches_[match->username_value] = match; 152 p->preferred_match_ = match; 153 } 154 155 void SimulateFetchMatchingLoginsFromPasswordStore( 156 PasswordFormManager* manager) { 157 // Just need to update the internal states. 158 manager->state_ = PasswordFormManager::MATCHING_PHASE; 159 } 160 161 void SimulateResponseFromPasswordStore( 162 PasswordFormManager* manager, 163 const std::vector<PasswordForm*>& result) { 164 // Simply call the callback method when request done. This will transfer 165 // the ownership of the objects in |result| to the |manager|. 166 manager->OnGetPasswordStoreResults(result); 167 } 168 169 void SanitizePossibleUsernames(PasswordFormManager* p, PasswordForm* form) { 170 p->SanitizePossibleUsernames(form); 171 } 172 173 bool IgnoredResult(PasswordFormManager* p, PasswordForm* form) { 174 return p->IgnoreResult(*form); 175 } 176 177 PasswordForm* observed_form() { return &observed_form_; } 178 PasswordForm* saved_match() { return &saved_match_; } 179 PasswordForm* CreateSavedMatch(bool blacklisted) { 180 // Owned by the caller of this method. 181 PasswordForm* match = new PasswordForm(saved_match_); 182 match->blacklisted_by_user = blacklisted; 183 return match; 184 } 185 186 private: 187 PasswordForm observed_form_; 188 PasswordForm saved_match_; 189 scoped_refptr<MockPasswordStore> mock_store_; 190 }; 191 192 TEST_F(PasswordFormManagerTest, TestNewLogin) { 193 scoped_ptr<TestPasswordManagerClient> client( 194 new TestPasswordManagerClient(NULL)); 195 scoped_ptr<StubPasswordManagerDriver> driver; 196 PasswordFormManager* manager = new PasswordFormManager( 197 NULL, client.get(), driver.get(), *observed_form(), false); 198 199 SimulateMatchingPhase(manager, false); 200 // User submits credentials for the observed form. 201 PasswordForm credentials = *observed_form(); 202 credentials.username_value = saved_match()->username_value; 203 credentials.password_value = saved_match()->password_value; 204 credentials.preferred = true; 205 manager->ProvisionallySave( 206 credentials, PasswordFormManager::IGNORE_OTHER_POSSIBLE_USERNAMES); 207 208 // Successful login. The PasswordManager would instruct PasswordFormManager 209 // to save, which should know this is a new login. 210 EXPECT_TRUE(manager->IsNewLogin()); 211 // Make sure the credentials that would be submitted on successful login 212 // are going to match the stored entry in the db. 213 EXPECT_EQ(observed_form()->origin.spec(), 214 GetPendingCredentials(manager)->origin.spec()); 215 EXPECT_EQ(observed_form()->signon_realm, 216 GetPendingCredentials(manager)->signon_realm); 217 EXPECT_EQ(observed_form()->action, GetPendingCredentials(manager)->action); 218 EXPECT_TRUE(GetPendingCredentials(manager)->preferred); 219 EXPECT_EQ(saved_match()->password_value, 220 GetPendingCredentials(manager)->password_value); 221 EXPECT_EQ(saved_match()->username_value, 222 GetPendingCredentials(manager)->username_value); 223 224 // Now, suppose the user re-visits the site and wants to save an additional 225 // login for the site with a new username. In this case, the matching phase 226 // will yield the previously saved login. 227 SimulateMatchingPhase(manager, true); 228 // Set up the new login. 229 base::string16 new_user = ASCIIToUTF16("newuser"); 230 base::string16 new_pass = ASCIIToUTF16("newpass"); 231 credentials.username_value = new_user; 232 credentials.password_value = new_pass; 233 manager->ProvisionallySave( 234 credentials, PasswordFormManager::IGNORE_OTHER_POSSIBLE_USERNAMES); 235 236 // Again, the PasswordFormManager should know this is still a new login. 237 EXPECT_TRUE(manager->IsNewLogin()); 238 // And make sure everything squares up again. 239 EXPECT_EQ(observed_form()->origin.spec(), 240 GetPendingCredentials(manager)->origin.spec()); 241 EXPECT_EQ(observed_form()->signon_realm, 242 GetPendingCredentials(manager)->signon_realm); 243 EXPECT_TRUE(GetPendingCredentials(manager)->preferred); 244 EXPECT_EQ(new_pass, GetPendingCredentials(manager)->password_value); 245 EXPECT_EQ(new_user, GetPendingCredentials(manager)->username_value); 246 delete manager; 247 } 248 249 TEST_F(PasswordFormManagerTest, TestUpdatePassword) { 250 // Create a PasswordFormManager with observed_form, as if we just 251 // saw this form and need to find matching logins. 252 scoped_ptr<TestPasswordManagerClient> client( 253 new TestPasswordManagerClient(NULL)); 254 scoped_ptr<StubPasswordManagerDriver> driver; 255 PasswordFormManager* manager = new PasswordFormManager( 256 NULL, client.get(), driver.get(), *observed_form(), false); 257 258 SimulateMatchingPhase(manager, true); 259 260 // User submits credentials for the observed form using a username previously 261 // stored, but a new password. Note that the observed form may have different 262 // origin URL (as it does in this case) than the saved_match, but we want to 263 // make sure the updated password is reflected in saved_match, because that is 264 // what we autofilled. 265 base::string16 new_pass = ASCIIToUTF16("newpassword"); 266 PasswordForm credentials = *observed_form(); 267 credentials.username_value = saved_match()->username_value; 268 credentials.password_value = new_pass; 269 credentials.preferred = true; 270 manager->ProvisionallySave( 271 credentials, PasswordFormManager::IGNORE_OTHER_POSSIBLE_USERNAMES); 272 273 // Successful login. The PasswordManager would instruct PasswordFormManager 274 // to save, and since this is an update, it should know not to save as a new 275 // login. 276 EXPECT_FALSE(manager->IsNewLogin()); 277 278 // Make sure the credentials that would be submitted on successful login 279 // are going to match the stored entry in the db. (This verifies correct 280 // behaviour for bug 1074420). 281 EXPECT_EQ(GetPendingCredentials(manager)->origin.spec(), 282 saved_match()->origin.spec()); 283 EXPECT_EQ(GetPendingCredentials(manager)->signon_realm, 284 saved_match()->signon_realm); 285 EXPECT_TRUE(GetPendingCredentials(manager)->preferred); 286 EXPECT_EQ(new_pass, GetPendingCredentials(manager)->password_value); 287 // Done. 288 delete manager; 289 } 290 291 TEST_F(PasswordFormManagerTest, TestIgnoreResult) { 292 scoped_ptr<TestPasswordManagerClient> client( 293 new TestPasswordManagerClient(NULL)); 294 scoped_ptr<StubPasswordManagerDriver> driver; 295 PasswordFormManager* manager = new PasswordFormManager( 296 NULL, client.get(), driver.get(), *observed_form(), false); 297 298 // Make sure we don't match a PasswordForm if it was originally saved on 299 // an SSL-valid page and we are now on a page with invalid certificate. 300 saved_match()->ssl_valid = true; 301 EXPECT_TRUE(IgnoredResult(manager, saved_match())); 302 303 saved_match()->ssl_valid = false; 304 // Different paths for action / origin are okay. 305 saved_match()->action = GURL("http://www.google.com/b/Login"); 306 saved_match()->origin = GURL("http://www.google.com/foo"); 307 EXPECT_FALSE(IgnoredResult(manager, saved_match())); 308 309 // Done. 310 delete manager; 311 } 312 313 TEST_F(PasswordFormManagerTest, TestEmptyAction) { 314 scoped_ptr<TestPasswordManagerClient> client( 315 new TestPasswordManagerClient(NULL)); 316 scoped_ptr<StubPasswordManagerDriver> driver; 317 scoped_ptr<PasswordFormManager> manager(new PasswordFormManager( 318 NULL, client.get(), driver.get(), *observed_form(), false)); 319 320 saved_match()->action = GURL(); 321 SimulateMatchingPhase(manager.get(), true); 322 // User logs in with the autofilled username / password from saved_match. 323 PasswordForm login = *observed_form(); 324 login.username_value = saved_match()->username_value; 325 login.password_value = saved_match()->password_value; 326 manager->ProvisionallySave( 327 login, PasswordFormManager::IGNORE_OTHER_POSSIBLE_USERNAMES); 328 EXPECT_FALSE(manager->IsNewLogin()); 329 // We bless our saved PasswordForm entry with the action URL of the 330 // observed form. 331 EXPECT_EQ(observed_form()->action, 332 GetPendingCredentials(manager.get())->action); 333 } 334 335 TEST_F(PasswordFormManagerTest, TestUpdateAction) { 336 scoped_ptr<TestPasswordManagerClient> client( 337 new TestPasswordManagerClient(NULL)); 338 scoped_ptr<StubPasswordManagerDriver> driver; 339 scoped_ptr<PasswordFormManager> manager(new PasswordFormManager( 340 NULL, client.get(), driver.get(), *observed_form(), false)); 341 342 SimulateMatchingPhase(manager.get(), true); 343 // User logs in with the autofilled username / password from saved_match. 344 PasswordForm login = *observed_form(); 345 login.username_value = saved_match()->username_value; 346 login.password_value = saved_match()->password_value; 347 348 manager->ProvisionallySave( 349 login, PasswordFormManager::IGNORE_OTHER_POSSIBLE_USERNAMES); 350 EXPECT_FALSE(manager->IsNewLogin()); 351 // The observed action URL is different from the previously saved one, and 352 // is the same as the one that would be submitted on successful login. 353 EXPECT_NE(observed_form()->action, saved_match()->action); 354 EXPECT_EQ(observed_form()->action, 355 GetPendingCredentials(manager.get())->action); 356 } 357 358 TEST_F(PasswordFormManagerTest, TestDynamicAction) { 359 scoped_ptr<TestPasswordManagerClient> client( 360 new TestPasswordManagerClient(NULL)); 361 scoped_ptr<StubPasswordManagerDriver> driver; 362 scoped_ptr<PasswordFormManager> manager(new PasswordFormManager( 363 NULL, client.get(), driver.get(), *observed_form(), false)); 364 365 SimulateMatchingPhase(manager.get(), false); 366 PasswordForm login(*observed_form()); 367 // The submitted action URL is different from the one observed on page load. 368 GURL new_action = GURL("http://www.google.com/new_action"); 369 login.action = new_action; 370 371 manager->ProvisionallySave( 372 login, PasswordFormManager::IGNORE_OTHER_POSSIBLE_USERNAMES); 373 EXPECT_TRUE(manager->IsNewLogin()); 374 // Check that the provisionally saved action URL is the same as the submitted 375 // action URL, not the one observed on page load. 376 EXPECT_EQ(new_action, GetPendingCredentials(manager.get())->action); 377 } 378 379 TEST_F(PasswordFormManagerTest, TestAlternateUsername) { 380 // Need a MessageLoop for callbacks. 381 base::MessageLoop message_loop; 382 scoped_refptr<TestPasswordStore> password_store = new TestPasswordStore; 383 CHECK(password_store->Init(syncer::SyncableService::StartSyncFlare())); 384 385 TestPasswordManagerClient client(password_store.get()); 386 TestPasswordManager password_manager(&client); 387 scoped_ptr<PasswordFormManager> manager(new PasswordFormManager( 388 &password_manager, &client, client.GetDriver(), *observed_form(), false)); 389 EXPECT_CALL(*client.GetMockDriver(), AllowPasswordGenerationForForm(_)) 390 .Times(1); 391 EXPECT_CALL(*client.GetMockDriver(), IsOffTheRecord()) 392 .WillRepeatedly(Return(false)); 393 394 password_store->AddLogin(*saved_match()); 395 manager->FetchMatchingLoginsFromPasswordStore(PasswordStore::ALLOW_PROMPT); 396 RunAllPendingTasks(); 397 398 // The saved match has the right username already. 399 PasswordForm login(*observed_form()); 400 login.username_value = saved_match()->username_value; 401 login.password_value = saved_match()->password_value; 402 login.preferred = true; 403 manager->ProvisionallySave( 404 login, PasswordFormManager::ALLOW_OTHER_POSSIBLE_USERNAMES); 405 406 EXPECT_FALSE(manager->IsNewLogin()); 407 manager->Save(); 408 RunAllPendingTasks(); 409 410 // Should be only one password stored, and should not have 411 // |other_possible_usernames| set anymore. 412 TestPasswordStore::PasswordMap passwords = password_store->stored_passwords(); 413 EXPECT_EQ(1U, passwords.size()); 414 ASSERT_EQ(1U, passwords[saved_match()->signon_realm].size()); 415 EXPECT_EQ(saved_match()->username_value, 416 passwords[saved_match()->signon_realm][0].username_value); 417 EXPECT_EQ(0U, 418 passwords[saved_match()->signon_realm][0] 419 .other_possible_usernames.size()); 420 421 // This time use an alternate username 422 manager.reset(new PasswordFormManager( 423 &password_manager, &client, client.GetDriver(), *observed_form(), false)); 424 EXPECT_CALL(*client.GetMockDriver(), AllowPasswordGenerationForForm(_)) 425 .Times(1); 426 password_store->Clear(); 427 password_store->AddLogin(*saved_match()); 428 manager->FetchMatchingLoginsFromPasswordStore(PasswordStore::ALLOW_PROMPT); 429 RunAllPendingTasks(); 430 431 base::string16 new_username = saved_match()->other_possible_usernames[0]; 432 login.username_value = new_username; 433 manager->ProvisionallySave( 434 login, PasswordFormManager::ALLOW_OTHER_POSSIBLE_USERNAMES); 435 436 EXPECT_FALSE(manager->IsNewLogin()); 437 manager->Save(); 438 RunAllPendingTasks(); 439 440 // |other_possible_usernames| should also be empty, but username_value should 441 // be changed to match |new_username| 442 passwords = password_store->stored_passwords(); 443 EXPECT_EQ(1U, passwords.size()); 444 ASSERT_EQ(1U, passwords[saved_match()->signon_realm].size()); 445 EXPECT_EQ(new_username, 446 passwords[saved_match()->signon_realm][0].username_value); 447 EXPECT_EQ(0U, 448 passwords[saved_match()->signon_realm][0] 449 .other_possible_usernames.size()); 450 password_store->Shutdown(); 451 } 452 453 TEST_F(PasswordFormManagerTest, TestValidForms) { 454 // User submits credentials for the observed form. 455 PasswordForm credentials = *observed_form(); 456 credentials.scheme = PasswordForm::SCHEME_HTML; 457 credentials.username_value = saved_match()->username_value; 458 credentials.password_value = saved_match()->password_value; 459 460 // Form with both username_element and password_element. 461 PasswordFormManager manager1(NULL, NULL, NULL, credentials, false); 462 SimulateMatchingPhase(&manager1, false); 463 EXPECT_TRUE(manager1.HasValidPasswordForm()); 464 465 // Form without a username_element but with a password_element. 466 credentials.username_element.clear(); 467 PasswordFormManager manager2(NULL, NULL, NULL, credentials, false); 468 SimulateMatchingPhase(&manager2, false); 469 EXPECT_FALSE(manager2.HasValidPasswordForm()); 470 471 // Form without a password_element but with a username_element. 472 credentials.username_element = saved_match()->username_element; 473 credentials.password_element.clear(); 474 PasswordFormManager manager3(NULL, NULL, NULL, credentials, false); 475 SimulateMatchingPhase(&manager3, false); 476 EXPECT_FALSE(manager3.HasValidPasswordForm()); 477 478 // Form with neither a password_element nor a username_element. 479 credentials.username_element.clear(); 480 credentials.password_element.clear(); 481 PasswordFormManager manager4(NULL, NULL, NULL, credentials, false); 482 SimulateMatchingPhase(&manager4, false); 483 EXPECT_FALSE(manager4.HasValidPasswordForm()); 484 } 485 486 TEST_F(PasswordFormManagerTest, TestValidFormsBasic) { 487 // User submits credentials for the observed form. 488 PasswordForm credentials = *observed_form(); 489 credentials.scheme = PasswordForm::SCHEME_BASIC; 490 credentials.username_value = saved_match()->username_value; 491 credentials.password_value = saved_match()->password_value; 492 493 // Form with both username_element and password_element. 494 PasswordFormManager manager1(NULL, NULL, NULL, credentials, false); 495 SimulateMatchingPhase(&manager1, false); 496 EXPECT_TRUE(manager1.HasValidPasswordForm()); 497 498 // Form without a username_element but with a password_element. 499 credentials.username_element.clear(); 500 PasswordFormManager manager2(NULL, NULL, NULL, credentials, false); 501 SimulateMatchingPhase(&manager2, false); 502 EXPECT_TRUE(manager2.HasValidPasswordForm()); 503 504 // Form without a password_element but with a username_element. 505 credentials.username_element = saved_match()->username_element; 506 credentials.password_element.clear(); 507 PasswordFormManager manager3(NULL, NULL, NULL, credentials, false); 508 SimulateMatchingPhase(&manager3, false); 509 EXPECT_TRUE(manager3.HasValidPasswordForm()); 510 511 // Form with neither a password_element nor a username_element. 512 credentials.username_element.clear(); 513 credentials.password_element.clear(); 514 PasswordFormManager manager4(NULL, NULL, NULL, credentials, false); 515 SimulateMatchingPhase(&manager4, false); 516 EXPECT_TRUE(manager4.HasValidPasswordForm()); 517 } 518 519 TEST_F(PasswordFormManagerTest, TestSendNotBlacklistedMessage) { 520 base::MessageLoop message_loop; 521 522 // A dumb password manager. 523 TestPasswordManagerClient client(NULL); 524 TestPasswordManager password_manager(&client); 525 scoped_ptr<PasswordFormManager> manager(new PasswordFormManager( 526 &password_manager, &client, client.GetDriver(), *observed_form(), false)); 527 528 // First time sign up attempt; No login result is found from password store; 529 // We should send the not blacklisted message. 530 EXPECT_CALL(*client.GetMockDriver(), AllowPasswordGenerationForForm(_)) 531 .Times(1); 532 SimulateFetchMatchingLoginsFromPasswordStore(manager.get()); 533 std::vector<PasswordForm*> result; 534 SimulateResponseFromPasswordStore(manager.get(), result); 535 Mock::VerifyAndClearExpectations(client.GetMockDriver()); 536 537 // Sign up attempt to previously visited sites; Login result is found from 538 // password store, and is not blacklisted; We should send the not blacklisted 539 // message. 540 manager.reset(new PasswordFormManager( 541 &password_manager, &client, client.GetDriver(), *observed_form(), false)); 542 EXPECT_CALL(*client.GetMockDriver(), AllowPasswordGenerationForForm(_)) 543 .Times(1); 544 EXPECT_CALL(*client.GetMockDriver(), IsOffTheRecord()) 545 .WillRepeatedly(Return(false)); 546 SimulateFetchMatchingLoginsFromPasswordStore(manager.get()); 547 // We need add heap allocated objects to result. 548 result.push_back(CreateSavedMatch(false)); 549 SimulateResponseFromPasswordStore(manager.get(), result); 550 Mock::VerifyAndClearExpectations(client.GetMockDriver()); 551 552 // Sign up attempt to previously visited sites; Login result is found from 553 // password store, but is blacklisted; We should not send the not blacklisted 554 // message. 555 manager.reset(new PasswordFormManager( 556 &password_manager, &client, client.GetDriver(), *observed_form(), false)); 557 EXPECT_CALL(*client.GetMockDriver(), AllowPasswordGenerationForForm(_)) 558 .Times(0); 559 SimulateFetchMatchingLoginsFromPasswordStore(manager.get()); 560 result.clear(); 561 result.push_back(CreateSavedMatch(true)); 562 SimulateResponseFromPasswordStore(manager.get(), result); 563 Mock::VerifyAndClearExpectations(client.GetMockDriver()); 564 } 565 566 TEST_F(PasswordFormManagerTest, TestForceInclusionOfGeneratedPasswords) { 567 base::MessageLoop message_loop; 568 569 TestPasswordManagerClient client(NULL); 570 TestPasswordManager password_manager(&client); 571 scoped_ptr<PasswordFormManager> manager(new PasswordFormManager( 572 &password_manager, &client, client.GetDriver(), *observed_form(), false)); 573 EXPECT_CALL(*client.GetMockDriver(), AllowPasswordGenerationForForm(_)) 574 .Times(1); 575 EXPECT_CALL(*client.GetMockDriver(), IsOffTheRecord()) 576 .WillRepeatedly(Return(false)); 577 578 // Simulate having two matches for this origin, one of which was from a form 579 // with different HTML tags for elements. Because of scoring differences, 580 // only the first form will be sent to Autofill(). 581 std::vector<PasswordForm*> results; 582 results.push_back(CreateSavedMatch(false)); 583 results.push_back(CreateSavedMatch(false)); 584 results[1]->username_value = ASCIIToUTF16("other (at) gmail.com"); 585 results[1]->password_element = ASCIIToUTF16("signup_password"); 586 results[1]->username_element = ASCIIToUTF16("signup_username"); 587 SimulateFetchMatchingLoginsFromPasswordStore(manager.get()); 588 SimulateResponseFromPasswordStore(manager.get(), results); 589 EXPECT_EQ(1u, password_manager.GetLatestBestMatches().size()); 590 results.clear(); 591 592 // Same thing, except this time the credentials that don't match quite as 593 // well are generated. They should now be sent to Autofill(). 594 manager.reset(new PasswordFormManager( 595 &password_manager, &client, client.GetDriver(), *observed_form(), false)); 596 EXPECT_CALL(*client.GetMockDriver(), AllowPasswordGenerationForForm(_)) 597 .Times(1); 598 599 results.push_back(CreateSavedMatch(false)); 600 results.push_back(CreateSavedMatch(false)); 601 results[1]->username_value = ASCIIToUTF16("other (at) gmail.com"); 602 results[1]->password_element = ASCIIToUTF16("signup_password"); 603 results[1]->username_element = ASCIIToUTF16("signup_username"); 604 results[1]->type = PasswordForm::TYPE_GENERATED; 605 SimulateFetchMatchingLoginsFromPasswordStore(manager.get()); 606 SimulateResponseFromPasswordStore(manager.get(), results); 607 EXPECT_EQ(2u, password_manager.GetLatestBestMatches().size()); 608 } 609 610 TEST_F(PasswordFormManagerTest, TestSanitizePossibleUsernames) { 611 scoped_ptr<TestPasswordManagerClient> client( 612 new TestPasswordManagerClient(NULL)); 613 scoped_ptr<StubPasswordManagerDriver> driver; 614 scoped_ptr<PasswordFormManager> manager(new PasswordFormManager( 615 NULL, client.get(), driver.get(), *observed_form(), false)); 616 PasswordForm credentials(*observed_form()); 617 credentials.other_possible_usernames.push_back(ASCIIToUTF16("543-43-1234")); 618 credentials.other_possible_usernames.push_back( 619 ASCIIToUTF16("378282246310005")); 620 credentials.other_possible_usernames.push_back( 621 ASCIIToUTF16("other username")); 622 credentials.username_value = ASCIIToUTF16("test (at) gmail.com"); 623 624 SanitizePossibleUsernames(manager.get(), &credentials); 625 626 // Possible credit card number and SSN are stripped. 627 std::vector<base::string16> expected; 628 expected.push_back(ASCIIToUTF16("other username")); 629 EXPECT_THAT(credentials.other_possible_usernames, Eq(expected)); 630 631 credentials.other_possible_usernames.clear(); 632 credentials.other_possible_usernames.push_back(ASCIIToUTF16("511-32-9830")); 633 credentials.other_possible_usernames.push_back(ASCIIToUTF16("duplicate")); 634 credentials.other_possible_usernames.push_back(ASCIIToUTF16("duplicate")); 635 credentials.other_possible_usernames.push_back(ASCIIToUTF16("random")); 636 credentials.other_possible_usernames.push_back( 637 ASCIIToUTF16("test (at) gmail.com")); 638 639 SanitizePossibleUsernames(manager.get(), &credentials); 640 641 // SSN, duplicate in |other_possible_usernames| and duplicate of 642 // |username_value| all removed. 643 expected.clear(); 644 expected.push_back(ASCIIToUTF16("duplicate")); 645 expected.push_back(ASCIIToUTF16("random")); 646 EXPECT_THAT(credentials.other_possible_usernames, Eq(expected)); 647 } 648 649 TEST_F(PasswordFormManagerTest, TestUpdateIncompleteCredentials) { 650 InitializeMockStore(); 651 652 // We've found this form on a website: 653 PasswordForm encountered_form; 654 encountered_form.origin = GURL("http://accounts.google.com/LoginAuth"); 655 encountered_form.signon_realm = "http://accounts.google.com/"; 656 encountered_form.action = GURL("http://accounts.google.com/Login"); 657 encountered_form.username_element = ASCIIToUTF16("Email"); 658 encountered_form.password_element = ASCIIToUTF16("Passwd"); 659 encountered_form.submit_element = ASCIIToUTF16("signIn"); 660 661 TestPasswordManagerClient client(mock_store()); 662 MockPasswordManagerDriver driver; 663 EXPECT_CALL(driver, IsOffTheRecord()).WillRepeatedly(Return(false)); 664 EXPECT_CALL(driver, AllowPasswordGenerationForForm(_)); 665 666 TestPasswordManager manager(&client); 667 PasswordFormManager form_manager( 668 &manager, &client, &driver, encountered_form, false); 669 670 const PasswordStore::AuthorizationPromptPolicy auth_policy = 671 PasswordStore::DISALLOW_PROMPT; 672 EXPECT_CALL(*mock_store(), 673 GetLogins(encountered_form, auth_policy, &form_manager)); 674 form_manager.FetchMatchingLoginsFromPasswordStore(auth_policy); 675 676 // Password store only has these incomplete credentials. 677 PasswordForm* incomplete_form = new PasswordForm(); 678 incomplete_form->origin = GURL("http://accounts.google.com/LoginAuth"); 679 incomplete_form->signon_realm = "http://accounts.google.com/"; 680 incomplete_form->password_value = ASCIIToUTF16("my_password"); 681 incomplete_form->username_value = ASCIIToUTF16("my_username"); 682 incomplete_form->preferred = true; 683 incomplete_form->ssl_valid = false; 684 incomplete_form->scheme = PasswordForm::SCHEME_HTML; 685 686 // We expect to see this form eventually sent to the Password store. It 687 // has password/username values from the store and 'username_element', 688 // 'password_element', 'submit_element' and 'action' fields copied from 689 // the encountered form. 690 PasswordForm complete_form(*incomplete_form); 691 complete_form.action = encountered_form.action; 692 complete_form.password_element = encountered_form.password_element; 693 complete_form.username_element = encountered_form.username_element; 694 complete_form.submit_element = encountered_form.submit_element; 695 696 PasswordForm obsolete_form(*incomplete_form); 697 obsolete_form.action = encountered_form.action; 698 699 // Feed the incomplete credentials to the manager. 700 std::vector<PasswordForm*> results; 701 results.push_back(incomplete_form); // Takes ownership. 702 form_manager.OnRequestDone(results); 703 704 form_manager.ProvisionallySave( 705 complete_form, PasswordFormManager::IGNORE_OTHER_POSSIBLE_USERNAMES); 706 // By now that form has been used once. 707 complete_form.times_used = 1; 708 obsolete_form.times_used = 1; 709 710 // Check that PasswordStore receives an update request with the complete form. 711 EXPECT_CALL(*mock_store(), RemoveLogin(obsolete_form)); 712 EXPECT_CALL(*mock_store(), AddLogin(complete_form)); 713 form_manager.Save(); 714 } 715 716 TEST_F(PasswordFormManagerTest, TestScoringPublicSuffixMatch) { 717 base::MessageLoop message_loop; 718 719 TestPasswordManagerClient client(NULL); 720 MockPasswordManagerDriver driver; 721 EXPECT_CALL(driver, IsOffTheRecord()).WillRepeatedly(Return(false)); 722 EXPECT_CALL(driver, AllowPasswordGenerationForForm(_)); 723 724 TestPasswordManager password_manager(&client); 725 scoped_ptr<PasswordFormManager> manager(new PasswordFormManager( 726 &password_manager, &client, &driver, *observed_form(), false)); 727 728 // Simulate having two matches for this form, first comes from different 729 // signon realm, but reports the same origin and action as matched form. 730 // Second candidate has the same signon realm as the form, but has a different 731 // origin and action. Public suffix match is the most important criterion so 732 // the second candidate should be selected. 733 std::vector<PasswordForm*> results; 734 results.push_back(CreateSavedMatch(false)); 735 results.push_back(CreateSavedMatch(false)); 736 results[0]->original_signon_realm = "http://accounts2.google.com"; 737 results[1]->origin = GURL("http://accounts.google.com/a/ServiceLoginAuth2"); 738 results[1]->action = GURL("http://accounts.google.com/a/ServiceLogin2"); 739 SimulateFetchMatchingLoginsFromPasswordStore(manager.get()); 740 SimulateResponseFromPasswordStore(manager.get(), results); 741 EXPECT_EQ(1u, password_manager.GetLatestBestMatches().size()); 742 EXPECT_EQ("", password_manager.GetLatestBestMatches().begin() 743 ->second->original_signon_realm); 744 } 745 746 } // namespace password_manager 747