password_manager_unittest.cc revision 5c02ac1a9c1b504631c0a3d2b6e737b5d738bae1
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 <vector> 6 7#include "base/message_loop/message_loop.h" 8#include "base/prefs/pref_registry_simple.h" 9#include "base/prefs/pref_service.h" 10#include "base/prefs/testing_pref_service.h" 11#include "base/strings/string_util.h" 12#include "base/strings/utf_string_conversions.h" 13#include "components/password_manager/core/browser/mock_password_manager_driver.h" 14#include "components/password_manager/core/browser/mock_password_store.h" 15#include "components/password_manager/core/browser/password_autofill_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/common/password_manager_pref_names.h" 21#include "testing/gmock/include/gmock/gmock.h" 22#include "testing/gtest/include/gtest/gtest.h" 23 24class PasswordGenerationManager; 25 26using autofill::PasswordForm; 27using base::ASCIIToUTF16; 28using testing::_; 29using testing::AnyNumber; 30using testing::DoAll; 31using testing::Exactly; 32using testing::Return; 33using testing::WithArg; 34 35namespace autofill { 36class AutofillManager; 37} 38 39namespace password_manager { 40 41namespace { 42 43class MockPasswordManagerClient : public StubPasswordManagerClient { 44 public: 45 MOCK_METHOD1(PromptUserToSavePassword, void(PasswordFormManager*)); 46 MOCK_METHOD0(GetPasswordStore, PasswordStore*()); 47 MOCK_METHOD0(GetPrefs, PrefService*()); 48 MOCK_METHOD0(GetDriver, PasswordManagerDriver*()); 49}; 50 51ACTION_P(InvokeConsumer, forms) { arg0->OnGetPasswordStoreResults(forms); } 52 53ACTION_P(SaveToScopedPtr, scoped) { scoped->reset(arg0); } 54 55class TestPasswordManager : public PasswordManager { 56 public: 57 explicit TestPasswordManager(PasswordManagerClient* client) 58 : PasswordManager(client) {} 59 virtual ~TestPasswordManager() {} 60 61 private: 62 DISALLOW_COPY_AND_ASSIGN(TestPasswordManager); 63}; 64 65} // namespace 66 67class PasswordManagerTest : public testing::Test { 68 protected: 69 virtual void SetUp() { 70 prefs_.registry()->RegisterBooleanPref(prefs::kPasswordManagerEnabled, 71 true); 72 73 store_ = new MockPasswordStore; 74 CHECK(store_->Init(syncer::SyncableService::StartSyncFlare())); 75 76 EXPECT_CALL(client_, GetPasswordStore()).WillRepeatedly(Return(store_)); 77 EXPECT_CALL(client_, GetPrefs()).WillRepeatedly(Return(&prefs_)); 78 EXPECT_CALL(client_, GetDriver()).WillRepeatedly(Return(&driver_)); 79 80 manager_.reset(new TestPasswordManager(&client_)); 81 password_autofill_manager_.reset( 82 new PasswordAutofillManager(&client_, NULL)); 83 84 EXPECT_CALL(driver_, DidLastPageLoadEncounterSSLErrors()) 85 .WillRepeatedly(Return(false)); 86 EXPECT_CALL(driver_, IsOffTheRecord()).WillRepeatedly(Return(false)); 87 EXPECT_CALL(driver_, GetPasswordGenerationManager()) 88 .WillRepeatedly(Return(static_cast<PasswordGenerationManager*>(NULL))); 89 EXPECT_CALL(driver_, GetPasswordManager()) 90 .WillRepeatedly(Return(manager_.get())); 91 EXPECT_CALL(driver_, AllowPasswordGenerationForForm(_)).Times(AnyNumber()); 92 EXPECT_CALL(driver_, GetPasswordAutofillManager()) 93 .WillRepeatedly(Return(password_autofill_manager_.get())); 94 95 EXPECT_CALL(*store_, ReportMetricsImpl()).Times(AnyNumber()); 96 } 97 98 virtual void TearDown() { 99 store_->Shutdown(); 100 store_ = NULL; 101 } 102 103 PasswordForm MakeSimpleForm() { 104 PasswordForm form; 105 form.origin = GURL("http://www.google.com/a/LoginAuth"); 106 form.action = GURL("http://www.google.com/a/Login"); 107 form.username_element = ASCIIToUTF16("Email"); 108 form.password_element = ASCIIToUTF16("Passwd"); 109 form.username_value = ASCIIToUTF16("google"); 110 form.password_value = ASCIIToUTF16("password"); 111 // Default to true so we only need to add tests in autocomplete=off cases. 112 form.password_autocomplete_set = true; 113 form.submit_element = ASCIIToUTF16("signIn"); 114 form.signon_realm = "http://www.google.com"; 115 return form; 116 } 117 118 // Reproduction of the form present on twitter's login page. 119 PasswordForm MakeTwitterLoginForm() { 120 PasswordForm form; 121 form.origin = GURL("https://twitter.com/"); 122 form.action = GURL("https://twitter.com/sessions"); 123 form.username_element = ASCIIToUTF16("Email"); 124 form.password_element = ASCIIToUTF16("Passwd"); 125 form.username_value = ASCIIToUTF16("twitter"); 126 form.password_value = ASCIIToUTF16("password"); 127 form.password_autocomplete_set = true; 128 form.submit_element = ASCIIToUTF16("signIn"); 129 form.signon_realm = "https://twitter.com"; 130 return form; 131 } 132 133 // Reproduction of the form present on twitter's failed login page. 134 PasswordForm MakeTwitterFailedLoginForm() { 135 PasswordForm form; 136 form.origin = GURL("https://twitter.com/login/error?redirect_after_login"); 137 form.action = GURL("https://twitter.com/sessions"); 138 form.username_element = ASCIIToUTF16("EmailField"); 139 form.password_element = ASCIIToUTF16("PasswdField"); 140 form.username_value = ASCIIToUTF16("twitter"); 141 form.password_value = ASCIIToUTF16("password"); 142 form.password_autocomplete_set = true; 143 form.submit_element = ASCIIToUTF16("signIn"); 144 form.signon_realm = "https://twitter.com"; 145 return form; 146 } 147 148 bool FormsAreEqual(const autofill::PasswordForm& lhs, 149 const autofill::PasswordForm& rhs) { 150 if (lhs.origin != rhs.origin) 151 return false; 152 if (lhs.action != rhs.action) 153 return false; 154 if (lhs.username_element != rhs.username_element) 155 return false; 156 if (lhs.password_element != rhs.password_element) 157 return false; 158 if (lhs.username_value != rhs.username_value) 159 return false; 160 if (lhs.password_value != rhs.password_value) 161 return false; 162 if (lhs.password_autocomplete_set != rhs.password_autocomplete_set) 163 return false; 164 if (lhs.submit_element != rhs.submit_element) 165 return false; 166 if (lhs.signon_realm != rhs.signon_realm) 167 return false; 168 return true; 169 } 170 171 TestPasswordManager* manager() { return manager_.get(); } 172 173 void OnPasswordFormSubmitted(const autofill::PasswordForm& form) { 174 manager()->OnPasswordFormSubmitted(form); 175 } 176 177 PasswordManager::PasswordSubmittedCallback SubmissionCallback() { 178 return base::Bind(&PasswordManagerTest::FormSubmitted, 179 base::Unretained(this)); 180 } 181 182 void FormSubmitted(const autofill::PasswordForm& form) { 183 submitted_form_ = form; 184 } 185 186 TestingPrefServiceSimple prefs_; 187 scoped_refptr<MockPasswordStore> store_; 188 MockPasswordManagerClient client_; 189 MockPasswordManagerDriver driver_; 190 scoped_ptr<PasswordAutofillManager> password_autofill_manager_; 191 scoped_ptr<TestPasswordManager> manager_; 192 PasswordForm submitted_form_; 193}; 194 195MATCHER_P(FormMatches, form, "") { 196 return form.signon_realm == arg.signon_realm && form.origin == arg.origin && 197 form.action == arg.action && 198 form.username_element == arg.username_element && 199 form.password_element == arg.password_element && 200 form.password_autocomplete_set == arg.password_autocomplete_set && 201 form.submit_element == arg.submit_element; 202} 203 204TEST_F(PasswordManagerTest, FormSubmitEmptyStore) { 205 // Test that observing a newly submitted form shows the save password bar. 206 std::vector<PasswordForm*> result; // Empty password store. 207 EXPECT_CALL(driver_, FillPasswordForm(_)).Times(Exactly(0)); 208 EXPECT_CALL(*store_.get(), GetLogins(_, _, _)) 209 .WillOnce(DoAll(WithArg<2>(InvokeConsumer(result)), Return())); 210 std::vector<PasswordForm> observed; 211 PasswordForm form(MakeSimpleForm()); 212 observed.push_back(form); 213 manager()->OnPasswordFormsParsed(observed); // The initial load. 214 manager()->OnPasswordFormsRendered(observed); // The initial layout. 215 216 // And the form submit contract is to call ProvisionallySavePassword. 217 manager()->ProvisionallySavePassword(form); 218 219 scoped_ptr<PasswordFormManager> form_to_save; 220 EXPECT_CALL(client_, PromptUserToSavePassword(_)) 221 .WillOnce(WithArg<0>(SaveToScopedPtr(&form_to_save))); 222 223 // Now the password manager waits for the navigation to complete. 224 observed.clear(); 225 manager()->OnPasswordFormsParsed(observed); // The post-navigation load. 226 manager()->OnPasswordFormsRendered(observed); // The post-navigation layout. 227 228 ASSERT_TRUE(form_to_save.get()); 229 EXPECT_CALL(*store_.get(), AddLogin(FormMatches(form))); 230 231 // Simulate saving the form, as if the info bar was accepted. 232 form_to_save->Save(); 233} 234 235TEST_F(PasswordManagerTest, GeneratedPasswordFormSubmitEmptyStore) { 236 // This test is the same FormSubmitEmptyStore, except that it simulates the 237 // user generating the password through the browser. 238 std::vector<PasswordForm*> result; // Empty password store. 239 EXPECT_CALL(driver_, FillPasswordForm(_)).Times(Exactly(0)); 240 EXPECT_CALL(*store_.get(), GetLogins(_, _, _)) 241 .WillOnce(DoAll(WithArg<2>(InvokeConsumer(result)), Return())); 242 std::vector<PasswordForm> observed; 243 PasswordForm form(MakeSimpleForm()); 244 observed.push_back(form); 245 manager()->OnPasswordFormsParsed(observed); // The initial load. 246 manager()->OnPasswordFormsRendered(observed); // The initial layout. 247 248 // Simulate the user generating the password and submitting the form. 249 manager()->SetFormHasGeneratedPassword(form); 250 manager()->ProvisionallySavePassword(form); 251 252 // The user should not be presented with an infobar as they have already given 253 // consent by using the generated password. The form should be saved once 254 // navigation occurs. 255 EXPECT_CALL(client_, PromptUserToSavePassword(_)).Times(Exactly(0)); 256 EXPECT_CALL(*store_.get(), AddLogin(FormMatches(form))); 257 258 // Now the password manager waits for the navigation to complete. 259 observed.clear(); 260 manager()->OnPasswordFormsParsed(observed); // The post-navigation load. 261 manager()->OnPasswordFormsRendered(observed); // The post-navigation layout. 262} 263 264TEST_F(PasswordManagerTest, FormSubmitNoGoodMatch) { 265 // Same as above, except with an existing form for the same signon realm, 266 // but different origin. Detailed cases like this are covered by 267 // PasswordFormManagerTest. 268 std::vector<PasswordForm*> result; 269 PasswordForm* existing_different = new PasswordForm(MakeSimpleForm()); 270 existing_different->username_value = ASCIIToUTF16("google2"); 271 result.push_back(existing_different); 272 EXPECT_CALL(driver_, FillPasswordForm(_)); 273 EXPECT_CALL(*store_.get(), GetLogins(_, _, _)) 274 .WillOnce(DoAll(WithArg<2>(InvokeConsumer(result)), Return())); 275 276 std::vector<PasswordForm> observed; 277 PasswordForm form(MakeSimpleForm()); 278 observed.push_back(form); 279 manager()->OnPasswordFormsParsed(observed); // The initial load. 280 manager()->OnPasswordFormsRendered(observed); // The initial layout. 281 manager()->ProvisionallySavePassword(form); 282 283 // We still expect an add, since we didn't have a good match. 284 scoped_ptr<PasswordFormManager> form_to_save; 285 EXPECT_CALL(client_, PromptUserToSavePassword(_)) 286 .WillOnce(WithArg<0>(SaveToScopedPtr(&form_to_save))); 287 288 // Now the password manager waits for the navigation to complete. 289 observed.clear(); 290 manager()->OnPasswordFormsParsed(observed); // The post-navigation load. 291 manager()->OnPasswordFormsRendered(observed); // The post-navigation layout. 292 293 ASSERT_TRUE(form_to_save.get()); 294 EXPECT_CALL(*store_.get(), AddLogin(FormMatches(form))); 295 296 // Simulate saving the form. 297 form_to_save->Save(); 298} 299 300TEST_F(PasswordManagerTest, FormSeenThenLeftPage) { 301 std::vector<PasswordForm*> result; // Empty password store. 302 EXPECT_CALL(driver_, FillPasswordForm(_)).Times(Exactly(0)); 303 EXPECT_CALL(*store_.get(), GetLogins(_, _, _)) 304 .WillOnce(DoAll(WithArg<2>(InvokeConsumer(result)), Return())); 305 std::vector<PasswordForm> observed; 306 PasswordForm form(MakeSimpleForm()); 307 observed.push_back(form); 308 manager()->OnPasswordFormsParsed(observed); // The initial load. 309 manager()->OnPasswordFormsRendered(observed); // The initial layout. 310 311 // No message from the renderer that a password was submitted. No 312 // expected calls. 313 EXPECT_CALL(client_, PromptUserToSavePassword(_)).Times(0); 314 observed.clear(); 315 manager()->OnPasswordFormsParsed(observed); // The post-navigation load. 316 manager()->OnPasswordFormsRendered(observed); // The post-navigation layout. 317} 318 319TEST_F(PasswordManagerTest, FormSubmitAfterNavigateInPage) { 320 // Test that navigating in the page does not prevent us from showing the save 321 // password infobar. 322 std::vector<PasswordForm*> result; // Empty password store. 323 EXPECT_CALL(driver_, FillPasswordForm(_)).Times(Exactly(0)); 324 EXPECT_CALL(*store_.get(), GetLogins(_, _, _)) 325 .WillOnce(DoAll(WithArg<2>(InvokeConsumer(result)), Return())); 326 std::vector<PasswordForm> observed; 327 PasswordForm form(MakeSimpleForm()); 328 observed.push_back(form); 329 manager()->OnPasswordFormsParsed(observed); // The initial load. 330 manager()->OnPasswordFormsRendered(observed); // The initial layout. 331 332 // Simulate navigating in the page. 333 manager()->DidNavigateMainFrame(true); 334 335 // Simulate submitting the password. 336 OnPasswordFormSubmitted(form); 337 338 // Now the password manager waits for the navigation to complete. 339 scoped_ptr<PasswordFormManager> form_to_save; 340 EXPECT_CALL(client_, PromptUserToSavePassword(_)) 341 .WillOnce(WithArg<0>(SaveToScopedPtr(&form_to_save))); 342 343 observed.clear(); 344 manager()->OnPasswordFormsParsed(observed); // The post-navigation load. 345 manager()->OnPasswordFormsRendered(observed); // The post-navigation layout. 346 347 ASSERT_FALSE(NULL == form_to_save.get()); 348 EXPECT_CALL(*store_.get(), AddLogin(FormMatches(form))); 349 350 // Simulate saving the form, as if the info bar was accepted. 351 form_to_save->Save(); 352} 353 354// This test verifies a fix for http://crbug.com/236673 355TEST_F(PasswordManagerTest, FormSubmitWithFormOnPreviousPage) { 356 std::vector<PasswordForm*> result; // Empty password store. 357 EXPECT_CALL(driver_, FillPasswordForm(_)).Times(Exactly(0)); 358 EXPECT_CALL(*store_.get(), GetLogins(_, _, _)) 359 .WillRepeatedly(DoAll(WithArg<2>(InvokeConsumer(result)), Return())); 360 PasswordForm first_form(MakeSimpleForm()); 361 first_form.origin = GURL("http://www.nytimes.com/"); 362 first_form.action = GURL("https://myaccount.nytimes.com/auth/login"); 363 first_form.signon_realm = "http://www.nytimes.com/"; 364 PasswordForm second_form(MakeSimpleForm()); 365 second_form.origin = GURL("https://myaccount.nytimes.com/auth/login"); 366 second_form.action = GURL("https://myaccount.nytimes.com/auth/login"); 367 second_form.signon_realm = "https://myaccount.nytimes.com/"; 368 369 // Pretend that the form is hidden on the first page. 370 std::vector<PasswordForm> observed; 371 observed.push_back(first_form); 372 manager()->OnPasswordFormsParsed(observed); 373 observed.clear(); 374 manager()->OnPasswordFormsRendered(observed); 375 376 // Now navigate to a second page. 377 manager()->DidNavigateMainFrame(false); 378 379 // This page contains a form with the same markup, but on a different 380 // URL. 381 observed.push_back(second_form); 382 manager()->OnPasswordFormsParsed(observed); 383 manager()->OnPasswordFormsRendered(observed); 384 385 // Now submit this form 386 OnPasswordFormSubmitted(second_form); 387 388 // Navigation after form submit. 389 scoped_ptr<PasswordFormManager> form_to_save; 390 EXPECT_CALL(client_, PromptUserToSavePassword(_)) 391 .WillOnce(WithArg<0>(SaveToScopedPtr(&form_to_save))); 392 observed.clear(); 393 manager()->OnPasswordFormsParsed(observed); 394 manager()->OnPasswordFormsRendered(observed); 395 396 // Make sure that the saved form matches the second form, not the first. 397 ASSERT_TRUE(form_to_save.get()); 398 EXPECT_CALL(*store_.get(), AddLogin(FormMatches(second_form))); 399 400 // Simulate saving the form, as if the info bar was accepted. 401 form_to_save->Save(); 402} 403 404TEST_F(PasswordManagerTest, FormSubmitFailedLogin) { 405 std::vector<PasswordForm*> result; // Empty password store. 406 EXPECT_CALL(driver_, FillPasswordForm(_)).Times(Exactly(0)); 407 EXPECT_CALL(*store_.get(), GetLogins(_, _, _)) 408 .WillRepeatedly(DoAll(WithArg<2>(InvokeConsumer(result)), Return())); 409 std::vector<PasswordForm> observed; 410 PasswordForm form(MakeSimpleForm()); 411 observed.push_back(form); 412 manager()->OnPasswordFormsParsed(observed); // The initial load. 413 manager()->OnPasswordFormsRendered(observed); // The initial layout. 414 415 manager()->ProvisionallySavePassword(form); 416 417 // The form reappears, and is visible in the layout: 418 // No expected calls to the PasswordStore... 419 manager()->OnPasswordFormsParsed(observed); 420 manager()->OnPasswordFormsRendered(observed); 421} 422 423TEST_F(PasswordManagerTest, FormSubmitInvisibleLogin) { 424 // Tests fix of issue 28911: if the login form reappears on the subsequent 425 // page, but is invisible, it shouldn't count as a failed login. 426 std::vector<PasswordForm*> result; // Empty password store. 427 EXPECT_CALL(driver_, FillPasswordForm(_)).Times(Exactly(0)); 428 EXPECT_CALL(*store_.get(), GetLogins(_, _, _)) 429 .WillRepeatedly(DoAll(WithArg<2>(InvokeConsumer(result)), Return())); 430 std::vector<PasswordForm> observed; 431 PasswordForm form(MakeSimpleForm()); 432 observed.push_back(form); 433 manager()->OnPasswordFormsParsed(observed); // The initial load. 434 manager()->OnPasswordFormsRendered(observed); // The initial layout. 435 436 manager()->ProvisionallySavePassword(form); 437 438 // Expect info bar to appear: 439 scoped_ptr<PasswordFormManager> form_to_save; 440 EXPECT_CALL(client_, PromptUserToSavePassword(_)) 441 .WillOnce(WithArg<0>(SaveToScopedPtr(&form_to_save))); 442 443 // The form reappears, but is not visible in the layout: 444 manager()->OnPasswordFormsParsed(observed); 445 observed.clear(); 446 manager()->OnPasswordFormsRendered(observed); 447 448 ASSERT_TRUE(form_to_save.get()); 449 EXPECT_CALL(*store_.get(), AddLogin(FormMatches(form))); 450 451 // Simulate saving the form. 452 form_to_save->Save(); 453} 454 455TEST_F(PasswordManagerTest, InitiallyInvisibleForm) { 456 // Make sure an invisible login form still gets autofilled. 457 std::vector<PasswordForm*> result; 458 PasswordForm* existing = new PasswordForm(MakeSimpleForm()); 459 result.push_back(existing); 460 EXPECT_CALL(driver_, FillPasswordForm(_)); 461 EXPECT_CALL(*store_.get(), GetLogins(_, _, _)) 462 .WillRepeatedly(DoAll(WithArg<2>(InvokeConsumer(result)), Return())); 463 std::vector<PasswordForm> observed; 464 PasswordForm form(MakeSimpleForm()); 465 observed.push_back(form); 466 manager()->OnPasswordFormsParsed(observed); // The initial load. 467 observed.clear(); 468 manager()->OnPasswordFormsRendered(observed); // The initial layout. 469 470 manager()->OnPasswordFormsParsed(observed); // The post-navigation load. 471 manager()->OnPasswordFormsRendered(observed); // The post-navigation layout. 472} 473 474TEST_F(PasswordManagerTest, SavingDependsOnManagerEnabledPreference) { 475 // Test that saving passwords depends on the password manager enabled 476 // preference. 477 prefs_.SetUserPref(prefs::kPasswordManagerEnabled, 478 base::Value::CreateBooleanValue(true)); 479 EXPECT_TRUE(manager()->IsSavingEnabled()); 480 prefs_.SetUserPref(prefs::kPasswordManagerEnabled, 481 base::Value::CreateBooleanValue(false)); 482 EXPECT_FALSE(manager()->IsSavingEnabled()); 483} 484 485TEST_F(PasswordManagerTest, FillPasswordsOnDisabledManager) { 486 // Test fix for issue 158296: Passwords must be filled even if the password 487 // manager is disabled. 488 std::vector<PasswordForm*> result; 489 PasswordForm* existing = new PasswordForm(MakeSimpleForm()); 490 result.push_back(existing); 491 prefs_.SetUserPref(prefs::kPasswordManagerEnabled, 492 base::Value::CreateBooleanValue(false)); 493 EXPECT_CALL(driver_, FillPasswordForm(_)); 494 EXPECT_CALL(*store_.get(), 495 GetLogins(_, testing::Eq(PasswordStore::DISALLOW_PROMPT), _)) 496 .WillRepeatedly(DoAll(WithArg<2>(InvokeConsumer(result)), Return())); 497 std::vector<PasswordForm> observed; 498 PasswordForm form(MakeSimpleForm()); 499 observed.push_back(form); 500 manager()->OnPasswordFormsParsed(observed); 501} 502 503TEST_F(PasswordManagerTest, FormSavedWithAutocompleteOff) { 504 // Test password form with non-generated password will be saved even if 505 // autocomplete=off. 506 std::vector<PasswordForm*> result; // Empty password store. 507 EXPECT_CALL(driver_, FillPasswordForm(_)).Times(Exactly(0)); 508 EXPECT_CALL(*store_.get(), GetLogins(_, _, _)) 509 .WillOnce(DoAll(WithArg<2>(InvokeConsumer(result)), Return())); 510 std::vector<PasswordForm> observed; 511 PasswordForm form(MakeSimpleForm()); 512 form.password_autocomplete_set = false; 513 observed.push_back(form); 514 manager()->OnPasswordFormsParsed(observed); // The initial load. 515 manager()->OnPasswordFormsRendered(observed); // The initial layout. 516 517 // And the form submit contract is to call ProvisionallySavePassword. 518 manager()->ProvisionallySavePassword(form); 519 520 // Password form should be saved. 521 scoped_ptr<PasswordFormManager> form_to_save; 522 EXPECT_CALL(client_, PromptUserToSavePassword(_)).Times(Exactly(1)).WillOnce( 523 WithArg<0>(SaveToScopedPtr(&form_to_save))); 524 EXPECT_CALL(*store_.get(), AddLogin(FormMatches(form))).Times(Exactly(0)); 525 526 // Now the password manager waits for the navigation to complete. 527 observed.clear(); 528 manager()->OnPasswordFormsParsed(observed); // The post-navigation load. 529 manager()->OnPasswordFormsRendered(observed); // The post-navigation layout. 530 531 ASSERT_TRUE(form_to_save.get()); 532} 533 534TEST_F(PasswordManagerTest, GeneratedPasswordFormSavedAutocompleteOff) { 535 // Test password form with generated password will still be saved if 536 // autocomplete=off. 537 std::vector<PasswordForm*> result; // Empty password store. 538 EXPECT_CALL(driver_, FillPasswordForm(_)).Times(Exactly(0)); 539 EXPECT_CALL(*store_.get(), GetLogins(_, _, _)) 540 .WillOnce(DoAll(WithArg<2>(InvokeConsumer(result)), Return())); 541 std::vector<PasswordForm> observed; 542 PasswordForm form(MakeSimpleForm()); 543 form.password_autocomplete_set = false; 544 observed.push_back(form); 545 manager()->OnPasswordFormsParsed(observed); // The initial load. 546 manager()->OnPasswordFormsRendered(observed); // The initial layout. 547 548 // Simulate the user generating the password and submitting the form. 549 manager()->SetFormHasGeneratedPassword(form); 550 manager()->ProvisionallySavePassword(form); 551 552 // The user should not be presented with an infobar as they have already given 553 // consent by using the generated password. The form should be saved once 554 // navigation occurs. 555 EXPECT_CALL(client_, PromptUserToSavePassword(_)).Times(Exactly(0)); 556 EXPECT_CALL(*store_.get(), AddLogin(FormMatches(form))); 557 558 // Now the password manager waits for the navigation to complete. 559 observed.clear(); 560 manager()->OnPasswordFormsParsed(observed); // The post-navigation load. 561 manager()->OnPasswordFormsRendered(observed); // The post-navigation layout. 562} 563 564TEST_F(PasswordManagerTest, SubmissionCallbackTest) { 565 manager()->AddSubmissionCallback(SubmissionCallback()); 566 PasswordForm form = MakeSimpleForm(); 567 OnPasswordFormSubmitted(form); 568 EXPECT_TRUE(FormsAreEqual(form, submitted_form_)); 569} 570 571TEST_F(PasswordManagerTest, PasswordFormReappearance) { 572 // Test the heuristic to know if a password form reappears. 573 // We assume that if we send our credentials and there 574 // is at least one visible password form in the next page that 575 // means that our previous login attempt failed. 576 std::vector<PasswordForm*> result; // Empty password store. 577 EXPECT_CALL(driver_, FillPasswordForm(_)).Times(0); 578 EXPECT_CALL(*store_.get(), GetLogins(_, _, _)) 579 .WillRepeatedly(DoAll(WithArg<2>(InvokeConsumer(result)), Return())); 580 std::vector<PasswordForm> observed; 581 PasswordForm login_form(MakeTwitterLoginForm()); 582 observed.push_back(login_form); 583 manager()->OnPasswordFormsParsed(observed); // The initial load. 584 manager()->OnPasswordFormsRendered(observed); // The initial layout. 585 586 manager()->ProvisionallySavePassword(login_form); 587 588 PasswordForm failed_login_form(MakeTwitterFailedLoginForm()); 589 observed.clear(); 590 observed.push_back(failed_login_form); 591 // A PasswordForm appears, and is visible in the layout: 592 // No expected calls to the PasswordStore... 593 manager()->OnPasswordFormsParsed(observed); 594 manager()->OnPasswordFormsRendered(observed); 595} 596 597} // namespace password_manager 598