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.
7 #include "base/message_loop/message_loop.h"
8 #include "base/strings/string_util.h"
9 #include "base/strings/utf_string_conversions.h"
10 #include "chrome/browser/password_manager/mock_password_store.h"
11 #include "chrome/browser/password_manager/password_manager.h"
12 #include "chrome/browser/password_manager/password_manager_delegate.h"
13 #include "chrome/browser/password_manager/password_store.h"
14 #include "chrome/browser/password_manager/password_store_factory.h"
15 #include "chrome/common/pref_names.h"
16 #include "chrome/common/url_constants.h"
17 #include "chrome/test/base/chrome_render_view_host_test_harness.h"
18 #include "chrome/test/base/testing_pref_service_syncable.h"
19 #include "chrome/test/base/testing_profile.h"
20 #include "content/public/browser/navigation_details.h"
21 #include "content/public/common/frame_navigate_params.h"
22 #include "content/public/test/test_browser_thread.h"
23 #include "testing/gmock/include/gmock/gmock.h"
24 #include "testing/gtest/include/gtest/gtest.h"
26 using autofill::PasswordForm;
29 using testing::Exactly;
30 using testing::Return;
31 using testing::WithArg;
35 class MockPasswordManagerDelegate : public PasswordManagerDelegate {
37 MOCK_METHOD1(FillPasswordForm, void(const autofill::PasswordFormFillData&));
38 MOCK_METHOD1(AddSavePasswordInfoBarIfPermitted, void(PasswordFormManager*));
39 MOCK_METHOD0(GetProfile, Profile*());
40 MOCK_METHOD0(DidLastPageLoadEncounterSSLErrors, bool());
43 ACTION_P(InvokeConsumer, forms) {
44 arg0->OnGetPasswordStoreResults(forms);
47 ACTION_P(SaveToScopedPtr, scoped) {
51 class TestPasswordManager : public PasswordManager {
53 TestPasswordManager(content::WebContents* contents,
54 PasswordManagerDelegate* delegate)
55 : PasswordManager(contents, delegate) {}
56 virtual ~TestPasswordManager() {}
58 virtual void OnPasswordFormSubmitted(const PasswordForm& form) OVERRIDE {
59 PasswordManager::OnPasswordFormSubmitted(form);
62 static TestPasswordManager* CreateForWebContentsAndDelegate(
63 content::WebContents* contents,
64 PasswordManagerDelegate* delegate) {
65 TestPasswordManager* tpm = new TestPasswordManager(contents, delegate);
66 contents->SetUserData(UserDataKey(), tpm);
71 DISALLOW_COPY_AND_ASSIGN(TestPasswordManager);
76 class PasswordManagerTest : public ChromeRenderViewHostTestHarness {
78 virtual void SetUp() {
79 ChromeRenderViewHostTestHarness::SetUp();
80 store_ = static_cast<MockPasswordStore*>(
81 PasswordStoreFactory::GetInstance()->SetTestingFactoryAndUse(
82 profile(), MockPasswordStore::Build).get());
84 EXPECT_CALL(delegate_, GetProfile()).WillRepeatedly(Return(profile()));
85 manager_ = TestPasswordManager::CreateForWebContentsAndDelegate(
86 web_contents(), &delegate_);
87 EXPECT_CALL(delegate_, DidLastPageLoadEncounterSSLErrors())
88 .WillRepeatedly(Return(false));
91 virtual void TearDown() {
93 ChromeRenderViewHostTestHarness::TearDown();
96 PasswordForm MakeSimpleForm() {
98 form.origin = GURL("http://www.google.com/a/LoginAuth");
99 form.action = GURL("http://www.google.com/a/Login");
100 form.username_element = ASCIIToUTF16("Email");
101 form.password_element = ASCIIToUTF16("Passwd");
102 form.username_value = ASCIIToUTF16("google");
103 form.password_value = ASCIIToUTF16("password");
104 // Default to true so we only need to add tests in autocomplete=off cases.
105 form.password_autocomplete_set = true;
106 form.submit_element = ASCIIToUTF16("signIn");
107 form.signon_realm = "http://www.google.com";
111 // Reproduction of the form present on twitter's login page.
112 PasswordForm MakeTwitterLoginForm() {
114 form.origin = GURL("https://twitter.com/");
115 form.action = GURL("https://twitter.com/sessions");
116 form.username_element = ASCIIToUTF16("Email");
117 form.password_element = ASCIIToUTF16("Passwd");
118 form.username_value = ASCIIToUTF16("twitter");
119 form.password_value = ASCIIToUTF16("password");
120 form.password_autocomplete_set = true;
121 form.submit_element = ASCIIToUTF16("signIn");
122 form.signon_realm = "https://twitter.com";
126 // Reproduction of the form present on twitter's failed login page.
127 PasswordForm MakeTwitterFailedLoginForm() {
130 GURL("https://twitter.com/login/error?redirect_after_login");
131 form.action = GURL("https://twitter.com/sessions");
132 form.username_element = ASCIIToUTF16("EmailField");
133 form.password_element = ASCIIToUTF16("PasswdField");
134 form.username_value = ASCIIToUTF16("twitter");
135 form.password_value = ASCIIToUTF16("password");
136 form.password_autocomplete_set = true;
137 form.submit_element = ASCIIToUTF16("signIn");
138 form.signon_realm = "https://twitter.com";
142 bool FormsAreEqual(const autofill::PasswordForm& lhs,
143 const autofill::PasswordForm& rhs) {
144 if (lhs.origin != rhs.origin)
146 if (lhs.action != rhs.action)
148 if (lhs.username_element != rhs.username_element)
150 if (lhs.password_element != rhs.password_element)
152 if (lhs.username_value != rhs.username_value)
154 if (lhs.password_value != rhs.password_value)
156 if (lhs.password_autocomplete_set != rhs.password_autocomplete_set)
158 if (lhs.submit_element != rhs.submit_element)
160 if (lhs.signon_realm != rhs.signon_realm)
165 TestPasswordManager* manager() {
169 void OnPasswordFormSubmitted(const autofill::PasswordForm& form) {
170 manager()->OnPasswordFormSubmitted(form);
173 PasswordManager::PasswordSubmittedCallback SubmissionCallback() {
174 return base::Bind(&PasswordManagerTest::FormSubmitted,
175 base::Unretained(this));
178 void FormSubmitted(const autofill::PasswordForm& form) {
179 submitted_form_ = form;
182 scoped_refptr<MockPasswordStore> store_;
183 TestPasswordManager* manager_;
184 MockPasswordManagerDelegate delegate_; // Owned by manager_.
185 PasswordForm submitted_form_;
188 MATCHER_P(FormMatches, form, "") {
189 return form.signon_realm == arg.signon_realm &&
190 form.origin == arg.origin &&
191 form.action == arg.action &&
192 form.username_element == arg.username_element &&
193 form.password_element == arg.password_element &&
194 form.password_autocomplete_set ==
195 arg.password_autocomplete_set &&
196 form.submit_element == arg.submit_element;
199 TEST_F(PasswordManagerTest, FormSubmitEmptyStore) {
200 // Test that observing a newly submitted form shows the save password bar.
201 std::vector<PasswordForm*> result; // Empty password store.
202 EXPECT_CALL(delegate_, FillPasswordForm(_)).Times(Exactly(0));
203 EXPECT_CALL(*store_.get(), GetLogins(_, _))
204 .WillOnce(DoAll(WithArg<1>(InvokeConsumer(result)), Return(1)));
205 std::vector<PasswordForm> observed;
206 PasswordForm form(MakeSimpleForm());
207 observed.push_back(form);
208 manager()->OnPasswordFormsParsed(observed); // The initial load.
209 manager()->OnPasswordFormsRendered(observed); // The initial layout.
211 // And the form submit contract is to call ProvisionallySavePassword.
212 manager()->ProvisionallySavePassword(form);
214 scoped_ptr<PasswordFormManager> form_to_save;
215 EXPECT_CALL(delegate_, AddSavePasswordInfoBarIfPermitted(_))
216 .WillOnce(WithArg<0>(SaveToScopedPtr(&form_to_save)));
218 // Now the password manager waits for the navigation to complete.
220 manager()->OnPasswordFormsParsed(observed); // The post-navigation load.
221 manager()->OnPasswordFormsRendered(observed); // The post-navigation layout.
223 ASSERT_TRUE(form_to_save.get());
224 EXPECT_CALL(*store_.get(), AddLogin(FormMatches(form)));
226 // Simulate saving the form, as if the info bar was accepted.
227 form_to_save->Save();
230 TEST_F(PasswordManagerTest, GeneratedPasswordFormSubmitEmptyStore) {
231 // This test is the same FormSubmitEmptyStore, except that it simulates the
232 // user generating the password through the browser.
233 std::vector<PasswordForm*> result; // Empty password store.
234 EXPECT_CALL(delegate_, FillPasswordForm(_)).Times(Exactly(0));
235 EXPECT_CALL(*store_.get(), GetLogins(_, _))
236 .WillOnce(DoAll(WithArg<1>(InvokeConsumer(result)), Return(1)));
237 std::vector<PasswordForm> observed;
238 PasswordForm form(MakeSimpleForm());
239 observed.push_back(form);
240 manager()->OnPasswordFormsParsed(observed); // The initial load.
241 manager()->OnPasswordFormsRendered(observed); // The initial layout.
243 // Simulate the user generating the password and submitting the form.
244 manager()->SetFormHasGeneratedPassword(form);
245 manager()->ProvisionallySavePassword(form);
247 // The user should not be presented with an infobar as they have already given
248 // consent by using the generated password. The form should be saved once
249 // navigation occurs.
250 EXPECT_CALL(delegate_,
251 AddSavePasswordInfoBarIfPermitted(_)).Times(Exactly(0));
252 EXPECT_CALL(*store_.get(), AddLogin(FormMatches(form)));
254 // Now the password manager waits for the navigation to complete.
256 manager()->OnPasswordFormsParsed(observed); // The post-navigation load.
257 manager()->OnPasswordFormsRendered(observed); // The post-navigation layout.
260 TEST_F(PasswordManagerTest, FormSubmitNoGoodMatch) {
261 // Same as above, except with an existing form for the same signon realm,
262 // but different origin. Detailed cases like this are covered by
263 // PasswordFormManagerTest.
264 std::vector<PasswordForm*> result;
265 PasswordForm* existing_different = new PasswordForm(MakeSimpleForm());
266 existing_different->username_value = ASCIIToUTF16("google2");
267 result.push_back(existing_different);
268 EXPECT_CALL(delegate_, FillPasswordForm(_));
269 EXPECT_CALL(*store_.get(), GetLogins(_, _))
270 .WillOnce(DoAll(WithArg<1>(InvokeConsumer(result)), Return(1)));
272 std::vector<PasswordForm> observed;
273 PasswordForm form(MakeSimpleForm());
274 observed.push_back(form);
275 manager()->OnPasswordFormsParsed(observed); // The initial load.
276 manager()->OnPasswordFormsRendered(observed); // The initial layout.
277 manager()->ProvisionallySavePassword(form);
279 // We still expect an add, since we didn't have a good match.
280 scoped_ptr<PasswordFormManager> form_to_save;
281 EXPECT_CALL(delegate_, AddSavePasswordInfoBarIfPermitted(_))
282 .WillOnce(WithArg<0>(SaveToScopedPtr(&form_to_save)));
284 // Now the password manager waits for the navigation to complete.
286 manager()->OnPasswordFormsParsed(observed); // The post-navigation load.
287 manager()->OnPasswordFormsRendered(observed); // The post-navigation layout.
289 ASSERT_TRUE(form_to_save.get());
290 EXPECT_CALL(*store_.get(), AddLogin(FormMatches(form)));
292 // Simulate saving the form.
293 form_to_save->Save();
296 TEST_F(PasswordManagerTest, FormSeenThenLeftPage) {
297 std::vector<PasswordForm*> result; // Empty password store.
298 EXPECT_CALL(delegate_, FillPasswordForm(_)).Times(Exactly(0));
299 EXPECT_CALL(*store_.get(), GetLogins(_, _))
300 .WillOnce(DoAll(WithArg<1>(InvokeConsumer(result)), Return(1)));
301 std::vector<PasswordForm> observed;
302 PasswordForm form(MakeSimpleForm());
303 observed.push_back(form);
304 manager()->OnPasswordFormsParsed(observed); // The initial load.
305 manager()->OnPasswordFormsRendered(observed); // The initial layout.
307 // No message from the renderer that a password was submitted. No
309 EXPECT_CALL(delegate_, AddSavePasswordInfoBarIfPermitted(_)).Times(0);
311 manager()->OnPasswordFormsParsed(observed); // The post-navigation load.
312 manager()->OnPasswordFormsRendered(observed); // The post-navigation layout.
315 TEST_F(PasswordManagerTest, FormSubmitAfterNavigateSubframe) {
316 // Test that navigating a subframe does not prevent us from showing the save
318 std::vector<PasswordForm*> result; // Empty password store.
319 EXPECT_CALL(delegate_, FillPasswordForm(_)).Times(Exactly(0));
320 EXPECT_CALL(*store_.get(), GetLogins(_, _))
321 .WillOnce(DoAll(WithArg<1>(InvokeConsumer(result)), Return(1)));
322 std::vector<PasswordForm> observed;
323 PasswordForm form(MakeSimpleForm());
324 observed.push_back(form);
325 manager()->OnPasswordFormsParsed(observed); // The initial load.
326 manager()->OnPasswordFormsRendered(observed); // The initial layout.
328 // Simulate navigating a sub-frame.
329 content::LoadCommittedDetails details;
330 content::FrameNavigateParams params;
331 manager()->DidNavigateAnyFrame(details, params);
333 // Simulate submitting the password.
334 OnPasswordFormSubmitted(form);
336 // Now the password manager waits for the navigation to complete.
337 scoped_ptr<PasswordFormManager> form_to_save;
338 EXPECT_CALL(delegate_, AddSavePasswordInfoBarIfPermitted(_))
339 .WillOnce(WithArg<0>(SaveToScopedPtr(&form_to_save)));
342 manager()->OnPasswordFormsParsed(observed); // The post-navigation load.
343 manager()->OnPasswordFormsRendered(observed); // The post-navigation layout.
345 ASSERT_FALSE(NULL == form_to_save.get());
346 EXPECT_CALL(*store_.get(), AddLogin(FormMatches(form)));
348 // Simulate saving the form, as if the info bar was accepted.
349 form_to_save->Save();
352 // This test verifies a fix for http://crbug.com/236673
353 TEST_F(PasswordManagerTest, FormSubmitWithFormOnPreviousPage) {
354 std::vector<PasswordForm*> result; // Empty password store.
355 EXPECT_CALL(delegate_, FillPasswordForm(_)).Times(Exactly(0));
356 EXPECT_CALL(*store_.get(), GetLogins(_, _))
357 .WillRepeatedly(DoAll(WithArg<1>(InvokeConsumer(result)), Return(1)));
358 PasswordForm first_form(MakeSimpleForm());
359 first_form.origin = GURL("http://www.nytimes.com/");
360 first_form.action = GURL("https://myaccount.nytimes.com/auth/login");
361 first_form.signon_realm = "http://www.nytimes.com/";
362 PasswordForm second_form(MakeSimpleForm());
363 second_form.origin = GURL("https://myaccount.nytimes.com/auth/login");
364 second_form.action = GURL("https://myaccount.nytimes.com/auth/login");
365 second_form.signon_realm = "https://myaccount.nytimes.com/";
367 // Pretend that the form is hidden on the first page.
368 std::vector<PasswordForm> observed;
369 observed.push_back(first_form);
370 manager()->OnPasswordFormsParsed(observed);
372 manager()->OnPasswordFormsRendered(observed);
374 // Now navigate to a second page.
375 content::LoadCommittedDetails details;
376 details.is_main_frame = true;
377 content::FrameNavigateParams params;
378 manager()->DidNavigateMainFrame(details, params);
380 // This page contains a form with the same markup, but on a different
382 observed.push_back(second_form);
383 manager()->OnPasswordFormsParsed(observed);
384 manager()->OnPasswordFormsRendered(observed);
386 // Now submit this form
387 OnPasswordFormSubmitted(second_form);
389 // Navigation after form submit.
390 scoped_ptr<PasswordFormManager> form_to_save;
391 EXPECT_CALL(delegate_, AddSavePasswordInfoBarIfPermitted(_))
392 .WillOnce(WithArg<0>(SaveToScopedPtr(&form_to_save)));
394 manager()->OnPasswordFormsParsed(observed);
395 manager()->OnPasswordFormsRendered(observed);
397 // Make sure that the saved form matches the second form, not the first.
398 ASSERT_TRUE(form_to_save.get());
399 EXPECT_CALL(*store_.get(), AddLogin(FormMatches(second_form)));
401 // Simulate saving the form, as if the info bar was accepted.
402 form_to_save->Save();
405 TEST_F(PasswordManagerTest, FormSubmitFailedLogin) {
406 std::vector<PasswordForm*> result; // Empty password store.
407 EXPECT_CALL(delegate_, FillPasswordForm(_)).Times(Exactly(0));
408 EXPECT_CALL(*store_.get(), GetLogins(_, _))
409 .WillRepeatedly(DoAll(WithArg<1>(InvokeConsumer(result)), Return(1)));
410 std::vector<PasswordForm> observed;
411 PasswordForm form(MakeSimpleForm());
412 observed.push_back(form);
413 manager()->OnPasswordFormsParsed(observed); // The initial load.
414 manager()->OnPasswordFormsRendered(observed); // The initial layout.
416 manager()->ProvisionallySavePassword(form);
418 // The form reappears, and is visible in the layout:
419 // No expected calls to the PasswordStore...
420 manager()->OnPasswordFormsParsed(observed);
421 manager()->OnPasswordFormsRendered(observed);
424 TEST_F(PasswordManagerTest, FormSubmitInvisibleLogin) {
425 // Tests fix of issue 28911: if the login form reappears on the subsequent
426 // page, but is invisible, it shouldn't count as a failed login.
427 std::vector<PasswordForm*> result; // Empty password store.
428 EXPECT_CALL(delegate_, FillPasswordForm(_)).Times(Exactly(0));
429 EXPECT_CALL(*store_.get(), GetLogins(_, _))
430 .WillRepeatedly(DoAll(WithArg<1>(InvokeConsumer(result)), Return(1)));
431 std::vector<PasswordForm> observed;
432 PasswordForm form(MakeSimpleForm());
433 observed.push_back(form);
434 manager()->OnPasswordFormsParsed(observed); // The initial load.
435 manager()->OnPasswordFormsRendered(observed); // The initial layout.
437 manager()->ProvisionallySavePassword(form);
439 // Expect info bar to appear:
440 scoped_ptr<PasswordFormManager> form_to_save;
441 EXPECT_CALL(delegate_, AddSavePasswordInfoBarIfPermitted(_))
442 .WillOnce(WithArg<0>(SaveToScopedPtr(&form_to_save)));
444 // The form reappears, but is not visible in the layout:
445 manager()->OnPasswordFormsParsed(observed);
447 manager()->OnPasswordFormsRendered(observed);
449 ASSERT_TRUE(form_to_save.get());
450 EXPECT_CALL(*store_.get(), AddLogin(FormMatches(form)));
452 // Simulate saving the form.
453 form_to_save->Save();
456 TEST_F(PasswordManagerTest, InitiallyInvisibleForm) {
457 // Make sure an invisible login form still gets autofilled.
458 std::vector<PasswordForm*> result;
459 PasswordForm* existing = new PasswordForm(MakeSimpleForm());
460 result.push_back(existing);
461 EXPECT_CALL(delegate_, FillPasswordForm(_));
462 EXPECT_CALL(*store_.get(), GetLogins(_, _))
463 .WillRepeatedly(DoAll(WithArg<1>(InvokeConsumer(result)), Return(1)));
464 std::vector<PasswordForm> observed;
465 PasswordForm form(MakeSimpleForm());
466 observed.push_back(form);
467 manager()->OnPasswordFormsParsed(observed); // The initial load.
469 manager()->OnPasswordFormsRendered(observed); // The initial layout.
471 manager()->OnPasswordFormsParsed(observed); // The post-navigation load.
472 manager()->OnPasswordFormsRendered(observed); // The post-navigation layout.
475 TEST_F(PasswordManagerTest, SavingDependsOnManagerEnabledPreference) {
476 // Test that saving passwords depends on the password manager enabled
478 TestingPrefServiceSyncable* prefService = profile()->GetTestingPrefService();
479 prefService->SetUserPref(prefs::kPasswordManagerEnabled,
480 Value::CreateBooleanValue(true));
481 EXPECT_TRUE(manager()->IsSavingEnabled());
482 prefService->SetUserPref(prefs::kPasswordManagerEnabled,
483 Value::CreateBooleanValue(false));
484 EXPECT_FALSE(manager()->IsSavingEnabled());
487 TEST_F(PasswordManagerTest, FillPasswordsOnDisabledManager) {
488 // Test fix for issue 158296: Passwords must be filled even if the password
489 // manager is disabled.
490 std::vector<PasswordForm*> result;
491 PasswordForm* existing = new PasswordForm(MakeSimpleForm());
492 result.push_back(existing);
493 TestingPrefServiceSyncable* prefService = profile()->GetTestingPrefService();
494 prefService->SetUserPref(prefs::kPasswordManagerEnabled,
495 Value::CreateBooleanValue(false));
496 EXPECT_CALL(delegate_, FillPasswordForm(_));
497 EXPECT_CALL(*store_.get(), GetLogins(_, _))
498 .WillRepeatedly(DoAll(WithArg<1>(InvokeConsumer(result)), Return(1)));
499 std::vector<PasswordForm> observed;
500 PasswordForm form(MakeSimpleForm());
501 observed.push_back(form);
502 manager()->OnPasswordFormsParsed(observed);
505 TEST_F(PasswordManagerTest, FormNotSavedAutocompleteOff) {
506 // Test password form with non-generated password will not be saved if
508 std::vector<PasswordForm*> result; // Empty password store.
509 EXPECT_CALL(delegate_, FillPasswordForm(_)).Times(Exactly(0));
510 EXPECT_CALL(*store_.get(), GetLogins(_, _))
511 .WillOnce(DoAll(WithArg<1>(InvokeConsumer(result)), Return(1)));
512 std::vector<PasswordForm> observed;
513 PasswordForm form(MakeSimpleForm());
514 form.password_autocomplete_set = false;
515 observed.push_back(form);
516 manager()->OnPasswordFormsParsed(observed); // The initial load.
517 manager()->OnPasswordFormsRendered(observed); // The initial layout.
519 // And the form submit contract is to call ProvisionallySavePassword.
520 manager()->ProvisionallySavePassword(form);
522 // Password form should not be saved.
523 EXPECT_CALL(delegate_,
524 AddSavePasswordInfoBarIfPermitted(_)).Times(Exactly(0));
525 EXPECT_CALL(*store_.get(), AddLogin(FormMatches(form))).Times(Exactly(0));
527 // Now the password manager waits for the navigation to complete.
529 manager()->OnPasswordFormsParsed(observed); // The post-navigation load.
530 manager()->OnPasswordFormsRendered(observed); // The post-navigation layout.
533 TEST_F(PasswordManagerTest, GeneratedPasswordFormSavedAutocompleteOff) {
534 // Test password form with generated password will still be saved if
536 std::vector<PasswordForm*> result; // Empty password store.
537 EXPECT_CALL(delegate_, FillPasswordForm(_)).Times(Exactly(0));
538 EXPECT_CALL(*store_.get(), GetLogins(_, _))
539 .WillOnce(DoAll(WithArg<1>(InvokeConsumer(result)), Return(1)));
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.
547 // Simulate the user generating the password and submitting the form.
548 manager()->SetFormHasGeneratedPassword(form);
549 manager()->ProvisionallySavePassword(form);
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(delegate_,
555 AddSavePasswordInfoBarIfPermitted(_)).Times(Exactly(0));
556 EXPECT_CALL(*store_.get(), AddLogin(FormMatches(form)));
558 // Now the password manager waits for the navigation to complete.
560 manager()->OnPasswordFormsParsed(observed); // The post-navigation load.
561 manager()->OnPasswordFormsRendered(observed); // The post-navigation layout.
564 TEST_F(PasswordManagerTest, SubmissionCallbackTest) {
565 manager()->AddSubmissionCallback(SubmissionCallback());
566 PasswordForm form = MakeSimpleForm();
567 OnPasswordFormSubmitted(form);
568 EXPECT_TRUE(FormsAreEqual(form, submitted_form_));
571 TEST_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(delegate_, FillPasswordForm(_)).Times(0);
578 EXPECT_CALL(*store_.get(), GetLogins(_, _))
579 .WillRepeatedly(DoAll(WithArg<1>(InvokeConsumer(result)), Return(1)));
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.
586 manager()->ProvisionallySavePassword(login_form);
588 PasswordForm failed_login_form(MakeTwitterFailedLoginForm());
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);