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