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