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
;
27 using base::ASCIIToUTF16
;
30 using testing::Exactly
;
31 using testing::Return
;
32 using testing::WithArg
;
36 class MockPasswordManagerDelegate
: public PasswordManagerDelegate
{
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
) {
52 class TestPasswordManager
: public PasswordManager
{
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
);
72 DISALLOW_COPY_AND_ASSIGN(TestPasswordManager
);
77 class PasswordManagerTest
: public ChromeRenderViewHostTestHarness
{
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() {
94 ChromeRenderViewHostTestHarness::TearDown();
97 PasswordForm
MakeSimpleForm() {
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";
112 // Reproduction of the form present on twitter's login page.
113 PasswordForm
MakeTwitterLoginForm() {
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";
127 // Reproduction of the form present on twitter's failed login page.
128 PasswordForm
MakeTwitterFailedLoginForm() {
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";
143 bool FormsAreEqual(const autofill::PasswordForm
& lhs
,
144 const autofill::PasswordForm
& rhs
) {
145 if (lhs
.origin
!= rhs
.origin
)
147 if (lhs
.action
!= rhs
.action
)
149 if (lhs
.username_element
!= rhs
.username_element
)
151 if (lhs
.password_element
!= rhs
.password_element
)
153 if (lhs
.username_value
!= rhs
.username_value
)
155 if (lhs
.password_value
!= rhs
.password_value
)
157 if (lhs
.password_autocomplete_set
!= rhs
.password_autocomplete_set
)
159 if (lhs
.submit_element
!= rhs
.submit_element
)
161 if (lhs
.signon_realm
!= rhs
.signon_realm
)
166 TestPasswordManager
* 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.
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.
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.
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
310 EXPECT_CALL(delegate_
, AddSavePasswordInfoBarIfPermitted(_
)).Times(0);
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
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
)));
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
);
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
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
)));
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
);
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.
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
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
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.
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
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.
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());
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
);