Disable view source for Developer Tools.
[chromium-blink-merge.git] / chrome / browser / password_manager / password_manager_unittest.cc
blob1c47b1f330dcf3657905695468a2da22e7b538f7
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.
5 #include <vector>
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;
27 using base::ASCIIToUTF16;
28 using testing::_;
29 using testing::DoAll;
30 using testing::Exactly;
31 using testing::Return;
32 using testing::WithArg;
34 namespace {
36 class MockPasswordManagerDelegate : public PasswordManagerDelegate {
37 public:
38 MOCK_METHOD1(FillPasswordForm, void(const autofill::PasswordFormFillData&));
39 MOCK_METHOD1(AddSavePasswordInfoBarIfPermitted, void(PasswordFormManager*));
40 MOCK_METHOD0(GetProfile, Profile*());
41 MOCK_METHOD0(DidLastPageLoadEncounterSSLErrors, bool());
44 ACTION_P(InvokeConsumer, forms) {
45 arg0->OnGetPasswordStoreResults(forms);
48 ACTION_P(SaveToScopedPtr, scoped) {
49 scoped->reset(arg0);
52 class TestPasswordManager : public PasswordManager {
53 public:
54 TestPasswordManager(content::WebContents* contents,
55 PasswordManagerDelegate* delegate)
56 : PasswordManager(contents, delegate) {}
57 virtual ~TestPasswordManager() {}
59 virtual void OnPasswordFormSubmitted(const PasswordForm& form) OVERRIDE {
60 PasswordManager::OnPasswordFormSubmitted(form);
63 static TestPasswordManager* CreateForWebContentsAndDelegate(
64 content::WebContents* contents,
65 PasswordManagerDelegate* delegate) {
66 TestPasswordManager* tpm = new TestPasswordManager(contents, delegate);
67 contents->SetUserData(UserDataKey(), tpm);
68 return tpm;
71 private:
72 DISALLOW_COPY_AND_ASSIGN(TestPasswordManager);
75 } // namespace
77 class PasswordManagerTest : public ChromeRenderViewHostTestHarness {
78 protected:
79 virtual void SetUp() {
80 ChromeRenderViewHostTestHarness::SetUp();
81 store_ = static_cast<MockPasswordStore*>(
82 PasswordStoreFactory::GetInstance()->SetTestingFactoryAndUse(
83 profile(), MockPasswordStore::Build).get());
85 EXPECT_CALL(delegate_, GetProfile()).WillRepeatedly(Return(profile()));
86 manager_ = TestPasswordManager::CreateForWebContentsAndDelegate(
87 web_contents(), &delegate_);
88 EXPECT_CALL(delegate_, DidLastPageLoadEncounterSSLErrors())
89 .WillRepeatedly(Return(false));
92 virtual void TearDown() {
93 store_ = NULL;
94 ChromeRenderViewHostTestHarness::TearDown();
97 PasswordForm MakeSimpleForm() {
98 PasswordForm form;
99 form.origin = GURL("http://www.google.com/a/LoginAuth");
100 form.action = GURL("http://www.google.com/a/Login");
101 form.username_element = ASCIIToUTF16("Email");
102 form.password_element = ASCIIToUTF16("Passwd");
103 form.username_value = ASCIIToUTF16("google");
104 form.password_value = ASCIIToUTF16("password");
105 // Default to true so we only need to add tests in autocomplete=off cases.
106 form.password_autocomplete_set = true;
107 form.submit_element = ASCIIToUTF16("signIn");
108 form.signon_realm = "http://www.google.com";
109 return form;
112 // Reproduction of the form present on twitter's login page.
113 PasswordForm MakeTwitterLoginForm() {
114 PasswordForm form;
115 form.origin = GURL("https://twitter.com/");
116 form.action = GURL("https://twitter.com/sessions");
117 form.username_element = ASCIIToUTF16("Email");
118 form.password_element = ASCIIToUTF16("Passwd");
119 form.username_value = ASCIIToUTF16("twitter");
120 form.password_value = ASCIIToUTF16("password");
121 form.password_autocomplete_set = true;
122 form.submit_element = ASCIIToUTF16("signIn");
123 form.signon_realm = "https://twitter.com";
124 return form;
127 // Reproduction of the form present on twitter's failed login page.
128 PasswordForm MakeTwitterFailedLoginForm() {
129 PasswordForm form;
130 form.origin =
131 GURL("https://twitter.com/login/error?redirect_after_login");
132 form.action = GURL("https://twitter.com/sessions");
133 form.username_element = ASCIIToUTF16("EmailField");
134 form.password_element = ASCIIToUTF16("PasswdField");
135 form.username_value = ASCIIToUTF16("twitter");
136 form.password_value = ASCIIToUTF16("password");
137 form.password_autocomplete_set = true;
138 form.submit_element = ASCIIToUTF16("signIn");
139 form.signon_realm = "https://twitter.com";
140 return form;
143 bool FormsAreEqual(const autofill::PasswordForm& lhs,
144 const autofill::PasswordForm& rhs) {
145 if (lhs.origin != rhs.origin)
146 return false;
147 if (lhs.action != rhs.action)
148 return false;
149 if (lhs.username_element != rhs.username_element)
150 return false;
151 if (lhs.password_element != rhs.password_element)
152 return false;
153 if (lhs.username_value != rhs.username_value)
154 return false;
155 if (lhs.password_value != rhs.password_value)
156 return false;
157 if (lhs.password_autocomplete_set != rhs.password_autocomplete_set)
158 return false;
159 if (lhs.submit_element != rhs.submit_element)
160 return false;
161 if (lhs.signon_realm != rhs.signon_realm)
162 return false;
163 return true;
166 TestPasswordManager* manager() {
167 return manager_;
170 void OnPasswordFormSubmitted(const autofill::PasswordForm& form) {
171 manager()->OnPasswordFormSubmitted(form);
174 PasswordManager::PasswordSubmittedCallback SubmissionCallback() {
175 return base::Bind(&PasswordManagerTest::FormSubmitted,
176 base::Unretained(this));
179 void FormSubmitted(const autofill::PasswordForm& form) {
180 submitted_form_ = form;
183 scoped_refptr<MockPasswordStore> store_;
184 TestPasswordManager* manager_;
185 MockPasswordManagerDelegate delegate_; // Owned by manager_.
186 PasswordForm submitted_form_;
189 MATCHER_P(FormMatches, form, "") {
190 return form.signon_realm == arg.signon_realm &&
191 form.origin == arg.origin &&
192 form.action == arg.action &&
193 form.username_element == arg.username_element &&
194 form.password_element == arg.password_element &&
195 form.password_autocomplete_set ==
196 arg.password_autocomplete_set &&
197 form.submit_element == arg.submit_element;
200 TEST_F(PasswordManagerTest, FormSubmitEmptyStore) {
201 // Test that observing a newly submitted form shows the save password bar.
202 std::vector<PasswordForm*> result; // Empty password store.
203 EXPECT_CALL(delegate_, FillPasswordForm(_)).Times(Exactly(0));
204 EXPECT_CALL(*store_.get(), GetLogins(_, _, _))
205 .WillOnce(DoAll(WithArg<2>(InvokeConsumer(result)), Return(1)));
206 std::vector<PasswordForm> observed;
207 PasswordForm form(MakeSimpleForm());
208 observed.push_back(form);
209 manager()->OnPasswordFormsParsed(observed); // The initial load.
210 manager()->OnPasswordFormsRendered(observed); // The initial layout.
212 // And the form submit contract is to call ProvisionallySavePassword.
213 manager()->ProvisionallySavePassword(form);
215 scoped_ptr<PasswordFormManager> form_to_save;
216 EXPECT_CALL(delegate_, AddSavePasswordInfoBarIfPermitted(_))
217 .WillOnce(WithArg<0>(SaveToScopedPtr(&form_to_save)));
219 // Now the password manager waits for the navigation to complete.
220 observed.clear();
221 manager()->OnPasswordFormsParsed(observed); // The post-navigation load.
222 manager()->OnPasswordFormsRendered(observed); // The post-navigation layout.
224 ASSERT_TRUE(form_to_save.get());
225 EXPECT_CALL(*store_.get(), AddLogin(FormMatches(form)));
227 // Simulate saving the form, as if the info bar was accepted.
228 form_to_save->Save();
231 TEST_F(PasswordManagerTest, GeneratedPasswordFormSubmitEmptyStore) {
232 // This test is the same FormSubmitEmptyStore, except that it simulates the
233 // user generating the password through the browser.
234 std::vector<PasswordForm*> result; // Empty password store.
235 EXPECT_CALL(delegate_, FillPasswordForm(_)).Times(Exactly(0));
236 EXPECT_CALL(*store_.get(), GetLogins(_, _, _))
237 .WillOnce(DoAll(WithArg<2>(InvokeConsumer(result)), Return(1)));
238 std::vector<PasswordForm> observed;
239 PasswordForm form(MakeSimpleForm());
240 observed.push_back(form);
241 manager()->OnPasswordFormsParsed(observed); // The initial load.
242 manager()->OnPasswordFormsRendered(observed); // The initial layout.
244 // Simulate the user generating the password and submitting the form.
245 manager()->SetFormHasGeneratedPassword(form);
246 manager()->ProvisionallySavePassword(form);
248 // The user should not be presented with an infobar as they have already given
249 // consent by using the generated password. The form should be saved once
250 // navigation occurs.
251 EXPECT_CALL(delegate_,
252 AddSavePasswordInfoBarIfPermitted(_)).Times(Exactly(0));
253 EXPECT_CALL(*store_.get(), AddLogin(FormMatches(form)));
255 // Now the password manager waits for the navigation to complete.
256 observed.clear();
257 manager()->OnPasswordFormsParsed(observed); // The post-navigation load.
258 manager()->OnPasswordFormsRendered(observed); // The post-navigation layout.
261 TEST_F(PasswordManagerTest, FormSubmitNoGoodMatch) {
262 // Same as above, except with an existing form for the same signon realm,
263 // but different origin. Detailed cases like this are covered by
264 // PasswordFormManagerTest.
265 std::vector<PasswordForm*> result;
266 PasswordForm* existing_different = new PasswordForm(MakeSimpleForm());
267 existing_different->username_value = ASCIIToUTF16("google2");
268 result.push_back(existing_different);
269 EXPECT_CALL(delegate_, FillPasswordForm(_));
270 EXPECT_CALL(*store_.get(), GetLogins(_, _, _))
271 .WillOnce(DoAll(WithArg<2>(InvokeConsumer(result)), Return(1)));
273 std::vector<PasswordForm> observed;
274 PasswordForm form(MakeSimpleForm());
275 observed.push_back(form);
276 manager()->OnPasswordFormsParsed(observed); // The initial load.
277 manager()->OnPasswordFormsRendered(observed); // The initial layout.
278 manager()->ProvisionallySavePassword(form);
280 // We still expect an add, since we didn't have a good match.
281 scoped_ptr<PasswordFormManager> form_to_save;
282 EXPECT_CALL(delegate_, AddSavePasswordInfoBarIfPermitted(_))
283 .WillOnce(WithArg<0>(SaveToScopedPtr(&form_to_save)));
285 // Now the password manager waits for the navigation to complete.
286 observed.clear();
287 manager()->OnPasswordFormsParsed(observed); // The post-navigation load.
288 manager()->OnPasswordFormsRendered(observed); // The post-navigation layout.
290 ASSERT_TRUE(form_to_save.get());
291 EXPECT_CALL(*store_.get(), AddLogin(FormMatches(form)));
293 // Simulate saving the form.
294 form_to_save->Save();
297 TEST_F(PasswordManagerTest, FormSeenThenLeftPage) {
298 std::vector<PasswordForm*> result; // Empty password store.
299 EXPECT_CALL(delegate_, FillPasswordForm(_)).Times(Exactly(0));
300 EXPECT_CALL(*store_.get(), GetLogins(_, _, _))
301 .WillOnce(DoAll(WithArg<2>(InvokeConsumer(result)), Return(1)));
302 std::vector<PasswordForm> observed;
303 PasswordForm form(MakeSimpleForm());
304 observed.push_back(form);
305 manager()->OnPasswordFormsParsed(observed); // The initial load.
306 manager()->OnPasswordFormsRendered(observed); // The initial layout.
308 // No message from the renderer that a password was submitted. No
309 // expected calls.
310 EXPECT_CALL(delegate_, AddSavePasswordInfoBarIfPermitted(_)).Times(0);
311 observed.clear();
312 manager()->OnPasswordFormsParsed(observed); // The post-navigation load.
313 manager()->OnPasswordFormsRendered(observed); // The post-navigation layout.
316 TEST_F(PasswordManagerTest, FormSubmitAfterNavigateSubframe) {
317 // Test that navigating a subframe does not prevent us from showing the save
318 // password infobar.
319 std::vector<PasswordForm*> result; // Empty password store.
320 EXPECT_CALL(delegate_, FillPasswordForm(_)).Times(Exactly(0));
321 EXPECT_CALL(*store_.get(), GetLogins(_, _, _))
322 .WillOnce(DoAll(WithArg<2>(InvokeConsumer(result)), Return(1)));
323 std::vector<PasswordForm> observed;
324 PasswordForm form(MakeSimpleForm());
325 observed.push_back(form);
326 manager()->OnPasswordFormsParsed(observed); // The initial load.
327 manager()->OnPasswordFormsRendered(observed); // The initial layout.
329 // Simulate navigating a sub-frame.
330 content::LoadCommittedDetails details;
331 content::FrameNavigateParams params;
332 manager()->DidNavigateAnyFrame(details, params);
334 // Simulate submitting the password.
335 OnPasswordFormSubmitted(form);
337 // Now the password manager waits for the navigation to complete.
338 scoped_ptr<PasswordFormManager> form_to_save;
339 EXPECT_CALL(delegate_, AddSavePasswordInfoBarIfPermitted(_))
340 .WillOnce(WithArg<0>(SaveToScopedPtr(&form_to_save)));
342 observed.clear();
343 manager()->OnPasswordFormsParsed(observed); // The post-navigation load.
344 manager()->OnPasswordFormsRendered(observed); // The post-navigation layout.
346 ASSERT_FALSE(NULL == form_to_save.get());
347 EXPECT_CALL(*store_.get(), AddLogin(FormMatches(form)));
349 // Simulate saving the form, as if the info bar was accepted.
350 form_to_save->Save();
353 // This test verifies a fix for http://crbug.com/236673
354 TEST_F(PasswordManagerTest, FormSubmitWithFormOnPreviousPage) {
355 std::vector<PasswordForm*> result; // Empty password store.
356 EXPECT_CALL(delegate_, FillPasswordForm(_)).Times(Exactly(0));
357 EXPECT_CALL(*store_.get(), GetLogins(_, _, _))
358 .WillRepeatedly(DoAll(WithArg<2>(InvokeConsumer(result)), Return(1)));
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/";
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);
375 // Now navigate to a second page.
376 content::LoadCommittedDetails details;
377 details.is_main_frame = true;
378 content::FrameNavigateParams params;
379 manager()->DidNavigateMainFrame(details, params);
381 // This page contains a form with the same markup, but on a different
382 // URL.
383 observed.push_back(second_form);
384 manager()->OnPasswordFormsParsed(observed);
385 manager()->OnPasswordFormsRendered(observed);
387 // Now submit this form
388 OnPasswordFormSubmitted(second_form);
390 // Navigation after form submit.
391 scoped_ptr<PasswordFormManager> form_to_save;
392 EXPECT_CALL(delegate_, AddSavePasswordInfoBarIfPermitted(_))
393 .WillOnce(WithArg<0>(SaveToScopedPtr(&form_to_save)));
394 observed.clear();
395 manager()->OnPasswordFormsParsed(observed);
396 manager()->OnPasswordFormsRendered(observed);
398 // Make sure that the saved form matches the second form, not the first.
399 ASSERT_TRUE(form_to_save.get());
400 EXPECT_CALL(*store_.get(), AddLogin(FormMatches(second_form)));
402 // Simulate saving the form, as if the info bar was accepted.
403 form_to_save->Save();
406 TEST_F(PasswordManagerTest, FormSubmitFailedLogin) {
407 std::vector<PasswordForm*> result; // Empty password store.
408 EXPECT_CALL(delegate_, FillPasswordForm(_)).Times(Exactly(0));
409 EXPECT_CALL(*store_.get(), GetLogins(_, _, _))
410 .WillRepeatedly(DoAll(WithArg<2>(InvokeConsumer(result)), Return(1)));
411 std::vector<PasswordForm> observed;
412 PasswordForm form(MakeSimpleForm());
413 observed.push_back(form);
414 manager()->OnPasswordFormsParsed(observed); // The initial load.
415 manager()->OnPasswordFormsRendered(observed); // The initial layout.
417 manager()->ProvisionallySavePassword(form);
419 // The form reappears, and is visible in the layout:
420 // No expected calls to the PasswordStore...
421 manager()->OnPasswordFormsParsed(observed);
422 manager()->OnPasswordFormsRendered(observed);
425 TEST_F(PasswordManagerTest, FormSubmitInvisibleLogin) {
426 // Tests fix of issue 28911: if the login form reappears on the subsequent
427 // page, but is invisible, it shouldn't count as a failed login.
428 std::vector<PasswordForm*> result; // Empty password store.
429 EXPECT_CALL(delegate_, FillPasswordForm(_)).Times(Exactly(0));
430 EXPECT_CALL(*store_.get(), GetLogins(_, _, _))
431 .WillRepeatedly(DoAll(WithArg<2>(InvokeConsumer(result)), Return(1)));
432 std::vector<PasswordForm> observed;
433 PasswordForm form(MakeSimpleForm());
434 observed.push_back(form);
435 manager()->OnPasswordFormsParsed(observed); // The initial load.
436 manager()->OnPasswordFormsRendered(observed); // The initial layout.
438 manager()->ProvisionallySavePassword(form);
440 // Expect info bar to appear:
441 scoped_ptr<PasswordFormManager> form_to_save;
442 EXPECT_CALL(delegate_, AddSavePasswordInfoBarIfPermitted(_))
443 .WillOnce(WithArg<0>(SaveToScopedPtr(&form_to_save)));
445 // The form reappears, but is not visible in the layout:
446 manager()->OnPasswordFormsParsed(observed);
447 observed.clear();
448 manager()->OnPasswordFormsRendered(observed);
450 ASSERT_TRUE(form_to_save.get());
451 EXPECT_CALL(*store_.get(), AddLogin(FormMatches(form)));
453 // Simulate saving the form.
454 form_to_save->Save();
457 TEST_F(PasswordManagerTest, InitiallyInvisibleForm) {
458 // Make sure an invisible login form still gets autofilled.
459 std::vector<PasswordForm*> result;
460 PasswordForm* existing = new PasswordForm(MakeSimpleForm());
461 result.push_back(existing);
462 EXPECT_CALL(delegate_, FillPasswordForm(_));
463 EXPECT_CALL(*store_.get(), GetLogins(_, _, _))
464 .WillRepeatedly(DoAll(WithArg<2>(InvokeConsumer(result)), Return(1)));
465 std::vector<PasswordForm> observed;
466 PasswordForm form(MakeSimpleForm());
467 observed.push_back(form);
468 manager()->OnPasswordFormsParsed(observed); // The initial load.
469 observed.clear();
470 manager()->OnPasswordFormsRendered(observed); // The initial layout.
472 manager()->OnPasswordFormsParsed(observed); // The post-navigation load.
473 manager()->OnPasswordFormsRendered(observed); // The post-navigation layout.
476 TEST_F(PasswordManagerTest, SavingDependsOnManagerEnabledPreference) {
477 // Test that saving passwords depends on the password manager enabled
478 // preference.
479 TestingPrefServiceSyncable* prefService = profile()->GetTestingPrefService();
480 prefService->SetUserPref(prefs::kPasswordManagerEnabled,
481 base::Value::CreateBooleanValue(true));
482 EXPECT_TRUE(manager()->IsSavingEnabled());
483 prefService->SetUserPref(prefs::kPasswordManagerEnabled,
484 base::Value::CreateBooleanValue(false));
485 EXPECT_FALSE(manager()->IsSavingEnabled());
488 TEST_F(PasswordManagerTest, FillPasswordsOnDisabledManager) {
489 // Test fix for issue 158296: Passwords must be filled even if the password
490 // manager is disabled.
491 std::vector<PasswordForm*> result;
492 PasswordForm* existing = new PasswordForm(MakeSimpleForm());
493 result.push_back(existing);
494 TestingPrefServiceSyncable* prefService = profile()->GetTestingPrefService();
495 prefService->SetUserPref(prefs::kPasswordManagerEnabled,
496 base::Value::CreateBooleanValue(false));
497 EXPECT_CALL(delegate_, FillPasswordForm(_));
498 EXPECT_CALL(*store_.get(),
499 GetLogins(_, testing::Eq(PasswordStore::DISALLOW_PROMPT), _))
500 .WillRepeatedly(DoAll(WithArg<2>(InvokeConsumer(result)), Return(1)));
501 std::vector<PasswordForm> observed;
502 PasswordForm form(MakeSimpleForm());
503 observed.push_back(form);
504 manager()->OnPasswordFormsParsed(observed);
507 TEST_F(PasswordManagerTest, FormNotSavedAutocompleteOff) {
508 // Test password form with non-generated password will not be saved if
509 // autocomplete=off.
510 std::vector<PasswordForm*> result; // Empty password store.
511 EXPECT_CALL(delegate_, FillPasswordForm(_)).Times(Exactly(0));
512 EXPECT_CALL(*store_.get(), GetLogins(_, _, _))
513 .WillOnce(DoAll(WithArg<2>(InvokeConsumer(result)), Return(1)));
514 std::vector<PasswordForm> observed;
515 PasswordForm form(MakeSimpleForm());
516 form.password_autocomplete_set = false;
517 observed.push_back(form);
518 manager()->OnPasswordFormsParsed(observed); // The initial load.
519 manager()->OnPasswordFormsRendered(observed); // The initial layout.
521 // And the form submit contract is to call ProvisionallySavePassword.
522 manager()->ProvisionallySavePassword(form);
524 // Password form should not be saved.
525 EXPECT_CALL(delegate_,
526 AddSavePasswordInfoBarIfPermitted(_)).Times(Exactly(0));
527 EXPECT_CALL(*store_.get(), AddLogin(FormMatches(form))).Times(Exactly(0));
529 // Now the password manager waits for the navigation to complete.
530 observed.clear();
531 manager()->OnPasswordFormsParsed(observed); // The post-navigation load.
532 manager()->OnPasswordFormsRendered(observed); // The post-navigation layout.
535 TEST_F(PasswordManagerTest, GeneratedPasswordFormSavedAutocompleteOff) {
536 // Test password form with generated password will still be saved if
537 // autocomplete=off.
538 std::vector<PasswordForm*> result; // Empty password store.
539 EXPECT_CALL(delegate_, FillPasswordForm(_)).Times(Exactly(0));
540 EXPECT_CALL(*store_.get(), GetLogins(_, _, _))
541 .WillOnce(DoAll(WithArg<2>(InvokeConsumer(result)), Return(1)));
542 std::vector<PasswordForm> observed;
543 PasswordForm form(MakeSimpleForm());
544 form.password_autocomplete_set = false;
545 observed.push_back(form);
546 manager()->OnPasswordFormsParsed(observed); // The initial load.
547 manager()->OnPasswordFormsRendered(observed); // The initial layout.
549 // Simulate the user generating the password and submitting the form.
550 manager()->SetFormHasGeneratedPassword(form);
551 manager()->ProvisionallySavePassword(form);
553 // The user should not be presented with an infobar as they have already given
554 // consent by using the generated password. The form should be saved once
555 // navigation occurs.
556 EXPECT_CALL(delegate_,
557 AddSavePasswordInfoBarIfPermitted(_)).Times(Exactly(0));
558 EXPECT_CALL(*store_.get(), AddLogin(FormMatches(form)));
560 // Now the password manager waits for the navigation to complete.
561 observed.clear();
562 manager()->OnPasswordFormsParsed(observed); // The post-navigation load.
563 manager()->OnPasswordFormsRendered(observed); // The post-navigation layout.
566 TEST_F(PasswordManagerTest, SubmissionCallbackTest) {
567 manager()->AddSubmissionCallback(SubmissionCallback());
568 PasswordForm form = MakeSimpleForm();
569 OnPasswordFormSubmitted(form);
570 EXPECT_TRUE(FormsAreEqual(form, submitted_form_));
573 TEST_F(PasswordManagerTest, PasswordFormReappearance) {
574 // Test the heuristic to know if a password form reappears.
575 // We assume that if we send our credentials and there
576 // is at least one visible password form in the next page that
577 // means that our previous login attempt failed.
578 std::vector<PasswordForm*> result; // Empty password store.
579 EXPECT_CALL(delegate_, FillPasswordForm(_)).Times(0);
580 EXPECT_CALL(*store_.get(), GetLogins(_, _, _))
581 .WillRepeatedly(DoAll(WithArg<2>(InvokeConsumer(result)), Return(1)));
582 std::vector<PasswordForm> observed;
583 PasswordForm login_form(MakeTwitterLoginForm());
584 observed.push_back(login_form);
585 manager()->OnPasswordFormsParsed(observed); // The initial load.
586 manager()->OnPasswordFormsRendered(observed); // The initial layout.
588 manager()->ProvisionallySavePassword(login_form);
590 PasswordForm failed_login_form(MakeTwitterFailedLoginForm());
591 observed.clear();
592 observed.push_back(failed_login_form);
593 // A PasswordForm appears, and is visible in the layout:
594 // No expected calls to the PasswordStore...
595 manager()->OnPasswordFormsParsed(observed);
596 manager()->OnPasswordFormsRendered(observed);