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