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/mock_password_store_service.h"
12 #include "chrome/browser/password_manager/password_manager.h"
13 #include "chrome/browser/password_manager/password_manager_delegate.h"
14 #include "chrome/browser/password_manager/password_manager_driver.h"
15 #include "chrome/browser/password_manager/password_store.h"
16 #include "chrome/browser/password_manager/password_store_factory.h"
17 #include "chrome/common/pref_names.h"
18 #include "chrome/common/url_constants.h"
19 #include "chrome/test/base/chrome_render_view_host_test_harness.h"
20 #include "chrome/test/base/testing_pref_service_syncable.h"
21 #include "chrome/test/base/testing_profile.h"
22 #include "content/public/browser/navigation_details.h"
23 #include "content/public/common/frame_navigate_params.h"
24 #include "content/public/test/test_browser_thread.h"
25 #include "testing/gmock/include/gmock/gmock.h"
26 #include "testing/gtest/include/gtest/gtest.h"
28 class PasswordGenerationManager
;
30 using autofill::PasswordForm
;
31 using base::ASCIIToUTF16
;
34 using testing::Exactly
;
35 using testing::Return
;
36 using testing::WithArg
;
40 class MockPasswordManagerDelegate
: public PasswordManagerDelegate
{
42 MOCK_METHOD1(AddSavePasswordInfoBarIfPermitted
, void(PasswordFormManager
*));
43 MOCK_METHOD0(GetProfile
, Profile
*());
44 MOCK_METHOD0(GetPrefs
, PrefService
*());
45 MOCK_METHOD0(GetDriver
, PasswordManagerDriver
*());
48 class MockPasswordManagerDriver
: public PasswordManagerDriver
{
50 MOCK_METHOD1(FillPasswordForm
, void(const autofill::PasswordFormFillData
&));
51 MOCK_METHOD0(DidLastPageLoadEncounterSSLErrors
, bool());
52 MOCK_METHOD0(IsOffTheRecord
, bool());
53 MOCK_METHOD0(GetPasswordGenerationManager
, PasswordGenerationManager
*());
54 MOCK_METHOD0(GetPasswordManager
, PasswordManager
*());
57 ACTION_P(InvokeConsumer
, forms
) {
58 arg0
->OnGetPasswordStoreResults(forms
);
61 ACTION_P(SaveToScopedPtr
, scoped
) {
65 class TestPasswordManager
: public PasswordManager
{
67 TestPasswordManager(content::WebContents
* contents
,
68 PasswordManagerDelegate
* delegate
)
69 : PasswordManager(contents
, delegate
) {}
70 virtual ~TestPasswordManager() {}
72 virtual void OnPasswordFormSubmitted(const PasswordForm
& form
) OVERRIDE
{
73 PasswordManager::OnPasswordFormSubmitted(form
);
77 DISALLOW_COPY_AND_ASSIGN(TestPasswordManager
);
82 class PasswordManagerTest
: public ChromeRenderViewHostTestHarness
{
84 virtual void SetUp() {
85 ChromeRenderViewHostTestHarness::SetUp();
86 PasswordStoreFactory
* factory
= PasswordStoreFactory::GetInstance();
87 factory
->SetTestingFactory(profile(), MockPasswordStoreService::Build
);
88 scoped_refptr
<PasswordStore
> store_temp(
89 factory
->GetForProfile(profile(), Profile::IMPLICIT_ACCESS
));
90 store_
= static_cast<MockPasswordStore
*>(store_temp
.get());
92 EXPECT_CALL(delegate_
, GetProfile()).WillRepeatedly(Return(profile()));
93 EXPECT_CALL(delegate_
, GetPrefs()).
94 WillRepeatedly(Return(profile()->GetTestingPrefService()));
95 EXPECT_CALL(delegate_
, GetDriver()).WillRepeatedly(Return(&driver_
));
97 manager_
.reset(new TestPasswordManager(web_contents(), &delegate_
));
99 EXPECT_CALL(driver_
, DidLastPageLoadEncounterSSLErrors())
100 .WillRepeatedly(Return(false));
101 EXPECT_CALL(driver_
, GetPasswordGenerationManager())
102 .WillRepeatedly(Return(static_cast<PasswordGenerationManager
*>(NULL
)));
103 EXPECT_CALL(driver_
, GetPasswordManager())
104 .WillRepeatedly(Return(manager_
.get()));
107 virtual void TearDown() {
110 // Destroy the PasswordManager before tearing down the Profile to avoid
111 // crashes due to prefs accesses.
113 ChromeRenderViewHostTestHarness::TearDown();
116 PasswordForm
MakeSimpleForm() {
118 form
.origin
= GURL("http://www.google.com/a/LoginAuth");
119 form
.action
= GURL("http://www.google.com/a/Login");
120 form
.username_element
= ASCIIToUTF16("Email");
121 form
.password_element
= ASCIIToUTF16("Passwd");
122 form
.username_value
= ASCIIToUTF16("google");
123 form
.password_value
= ASCIIToUTF16("password");
124 // Default to true so we only need to add tests in autocomplete=off cases.
125 form
.password_autocomplete_set
= true;
126 form
.submit_element
= ASCIIToUTF16("signIn");
127 form
.signon_realm
= "http://www.google.com";
131 // Reproduction of the form present on twitter's login page.
132 PasswordForm
MakeTwitterLoginForm() {
134 form
.origin
= GURL("https://twitter.com/");
135 form
.action
= GURL("https://twitter.com/sessions");
136 form
.username_element
= ASCIIToUTF16("Email");
137 form
.password_element
= ASCIIToUTF16("Passwd");
138 form
.username_value
= ASCIIToUTF16("twitter");
139 form
.password_value
= ASCIIToUTF16("password");
140 form
.password_autocomplete_set
= true;
141 form
.submit_element
= ASCIIToUTF16("signIn");
142 form
.signon_realm
= "https://twitter.com";
146 // Reproduction of the form present on twitter's failed login page.
147 PasswordForm
MakeTwitterFailedLoginForm() {
150 GURL("https://twitter.com/login/error?redirect_after_login");
151 form
.action
= GURL("https://twitter.com/sessions");
152 form
.username_element
= ASCIIToUTF16("EmailField");
153 form
.password_element
= ASCIIToUTF16("PasswdField");
154 form
.username_value
= ASCIIToUTF16("twitter");
155 form
.password_value
= ASCIIToUTF16("password");
156 form
.password_autocomplete_set
= true;
157 form
.submit_element
= ASCIIToUTF16("signIn");
158 form
.signon_realm
= "https://twitter.com";
162 bool FormsAreEqual(const autofill::PasswordForm
& lhs
,
163 const autofill::PasswordForm
& rhs
) {
164 if (lhs
.origin
!= rhs
.origin
)
166 if (lhs
.action
!= rhs
.action
)
168 if (lhs
.username_element
!= rhs
.username_element
)
170 if (lhs
.password_element
!= rhs
.password_element
)
172 if (lhs
.username_value
!= rhs
.username_value
)
174 if (lhs
.password_value
!= rhs
.password_value
)
176 if (lhs
.password_autocomplete_set
!= rhs
.password_autocomplete_set
)
178 if (lhs
.submit_element
!= rhs
.submit_element
)
180 if (lhs
.signon_realm
!= rhs
.signon_realm
)
185 TestPasswordManager
* manager() { return manager_
.get(); }
187 void OnPasswordFormSubmitted(const autofill::PasswordForm
& form
) {
188 manager()->OnPasswordFormSubmitted(form
);
191 PasswordManager::PasswordSubmittedCallback
SubmissionCallback() {
192 return base::Bind(&PasswordManagerTest::FormSubmitted
,
193 base::Unretained(this));
196 void FormSubmitted(const autofill::PasswordForm
& form
) {
197 submitted_form_
= form
;
200 scoped_refptr
<MockPasswordStore
> store_
;
201 MockPasswordManagerDelegate delegate_
;
202 MockPasswordManagerDriver driver_
;
203 scoped_ptr
<TestPasswordManager
> manager_
;
204 PasswordForm submitted_form_
;
207 MATCHER_P(FormMatches
, form
, "") {
208 return form
.signon_realm
== arg
.signon_realm
&&
209 form
.origin
== arg
.origin
&&
210 form
.action
== arg
.action
&&
211 form
.username_element
== arg
.username_element
&&
212 form
.password_element
== arg
.password_element
&&
213 form
.password_autocomplete_set
==
214 arg
.password_autocomplete_set
&&
215 form
.submit_element
== arg
.submit_element
;
218 TEST_F(PasswordManagerTest
, FormSubmitEmptyStore
) {
219 // Test that observing a newly submitted form shows the save password bar.
220 std::vector
<PasswordForm
*> result
; // Empty password store.
221 EXPECT_CALL(driver_
, FillPasswordForm(_
)).Times(Exactly(0));
222 EXPECT_CALL(*store_
.get(), GetLogins(_
, _
, _
))
223 .WillOnce(DoAll(WithArg
<2>(InvokeConsumer(result
)), Return()));
224 std::vector
<PasswordForm
> observed
;
225 PasswordForm
form(MakeSimpleForm());
226 observed
.push_back(form
);
227 manager()->OnPasswordFormsParsed(observed
); // The initial load.
228 manager()->OnPasswordFormsRendered(observed
); // The initial layout.
230 // And the form submit contract is to call ProvisionallySavePassword.
231 manager()->ProvisionallySavePassword(form
);
233 scoped_ptr
<PasswordFormManager
> form_to_save
;
234 EXPECT_CALL(delegate_
, AddSavePasswordInfoBarIfPermitted(_
))
235 .WillOnce(WithArg
<0>(SaveToScopedPtr(&form_to_save
)));
237 // Now the password manager waits for the navigation to complete.
239 manager()->OnPasswordFormsParsed(observed
); // The post-navigation load.
240 manager()->OnPasswordFormsRendered(observed
); // The post-navigation layout.
242 ASSERT_TRUE(form_to_save
.get());
243 EXPECT_CALL(*store_
.get(), AddLogin(FormMatches(form
)));
245 // Simulate saving the form, as if the info bar was accepted.
246 form_to_save
->Save();
249 TEST_F(PasswordManagerTest
, GeneratedPasswordFormSubmitEmptyStore
) {
250 // This test is the same FormSubmitEmptyStore, except that it simulates the
251 // user generating the password through the browser.
252 std::vector
<PasswordForm
*> result
; // Empty password store.
253 EXPECT_CALL(driver_
, FillPasswordForm(_
)).Times(Exactly(0));
254 EXPECT_CALL(*store_
.get(), GetLogins(_
, _
, _
))
255 .WillOnce(DoAll(WithArg
<2>(InvokeConsumer(result
)), Return()));
256 std::vector
<PasswordForm
> observed
;
257 PasswordForm
form(MakeSimpleForm());
258 observed
.push_back(form
);
259 manager()->OnPasswordFormsParsed(observed
); // The initial load.
260 manager()->OnPasswordFormsRendered(observed
); // The initial layout.
262 // Simulate the user generating the password and submitting the form.
263 manager()->SetFormHasGeneratedPassword(form
);
264 manager()->ProvisionallySavePassword(form
);
266 // The user should not be presented with an infobar as they have already given
267 // consent by using the generated password. The form should be saved once
268 // navigation occurs.
269 EXPECT_CALL(delegate_
,
270 AddSavePasswordInfoBarIfPermitted(_
)).Times(Exactly(0));
271 EXPECT_CALL(*store_
.get(), AddLogin(FormMatches(form
)));
273 // Now the password manager waits for the navigation to complete.
275 manager()->OnPasswordFormsParsed(observed
); // The post-navigation load.
276 manager()->OnPasswordFormsRendered(observed
); // The post-navigation layout.
279 TEST_F(PasswordManagerTest
, FormSubmitNoGoodMatch
) {
280 // Same as above, except with an existing form for the same signon realm,
281 // but different origin. Detailed cases like this are covered by
282 // PasswordFormManagerTest.
283 std::vector
<PasswordForm
*> result
;
284 PasswordForm
* existing_different
= new PasswordForm(MakeSimpleForm());
285 existing_different
->username_value
= ASCIIToUTF16("google2");
286 result
.push_back(existing_different
);
287 EXPECT_CALL(driver_
, FillPasswordForm(_
));
288 EXPECT_CALL(*store_
.get(), GetLogins(_
, _
, _
))
289 .WillOnce(DoAll(WithArg
<2>(InvokeConsumer(result
)), Return()));
291 std::vector
<PasswordForm
> observed
;
292 PasswordForm
form(MakeSimpleForm());
293 observed
.push_back(form
);
294 manager()->OnPasswordFormsParsed(observed
); // The initial load.
295 manager()->OnPasswordFormsRendered(observed
); // The initial layout.
296 manager()->ProvisionallySavePassword(form
);
298 // We still expect an add, since we didn't have a good match.
299 scoped_ptr
<PasswordFormManager
> form_to_save
;
300 EXPECT_CALL(delegate_
, AddSavePasswordInfoBarIfPermitted(_
))
301 .WillOnce(WithArg
<0>(SaveToScopedPtr(&form_to_save
)));
303 // Now the password manager waits for the navigation to complete.
305 manager()->OnPasswordFormsParsed(observed
); // The post-navigation load.
306 manager()->OnPasswordFormsRendered(observed
); // The post-navigation layout.
308 ASSERT_TRUE(form_to_save
.get());
309 EXPECT_CALL(*store_
.get(), AddLogin(FormMatches(form
)));
311 // Simulate saving the form.
312 form_to_save
->Save();
315 TEST_F(PasswordManagerTest
, FormSeenThenLeftPage
) {
316 std::vector
<PasswordForm
*> result
; // Empty password store.
317 EXPECT_CALL(driver_
, FillPasswordForm(_
)).Times(Exactly(0));
318 EXPECT_CALL(*store_
.get(), GetLogins(_
, _
, _
))
319 .WillOnce(DoAll(WithArg
<2>(InvokeConsumer(result
)), Return()));
320 std::vector
<PasswordForm
> observed
;
321 PasswordForm
form(MakeSimpleForm());
322 observed
.push_back(form
);
323 manager()->OnPasswordFormsParsed(observed
); // The initial load.
324 manager()->OnPasswordFormsRendered(observed
); // The initial layout.
326 // No message from the renderer that a password was submitted. No
328 EXPECT_CALL(delegate_
, AddSavePasswordInfoBarIfPermitted(_
)).Times(0);
330 manager()->OnPasswordFormsParsed(observed
); // The post-navigation load.
331 manager()->OnPasswordFormsRendered(observed
); // The post-navigation layout.
334 TEST_F(PasswordManagerTest
, FormSubmitAfterNavigateSubframe
) {
335 // Test that navigating a subframe does not prevent us from showing the save
337 std::vector
<PasswordForm
*> result
; // Empty password store.
338 EXPECT_CALL(driver_
, FillPasswordForm(_
)).Times(Exactly(0));
339 EXPECT_CALL(*store_
.get(), GetLogins(_
, _
, _
))
340 .WillOnce(DoAll(WithArg
<2>(InvokeConsumer(result
)), Return()));
341 std::vector
<PasswordForm
> observed
;
342 PasswordForm
form(MakeSimpleForm());
343 observed
.push_back(form
);
344 manager()->OnPasswordFormsParsed(observed
); // The initial load.
345 manager()->OnPasswordFormsRendered(observed
); // The initial layout.
347 // Simulate navigating a sub-frame.
348 content::LoadCommittedDetails details
;
349 content::FrameNavigateParams params
;
350 manager()->DidNavigateAnyFrame(details
, params
);
352 // Simulate submitting the password.
353 OnPasswordFormSubmitted(form
);
355 // Now the password manager waits for the navigation to complete.
356 scoped_ptr
<PasswordFormManager
> form_to_save
;
357 EXPECT_CALL(delegate_
, AddSavePasswordInfoBarIfPermitted(_
))
358 .WillOnce(WithArg
<0>(SaveToScopedPtr(&form_to_save
)));
361 manager()->OnPasswordFormsParsed(observed
); // The post-navigation load.
362 manager()->OnPasswordFormsRendered(observed
); // The post-navigation layout.
364 ASSERT_FALSE(NULL
== form_to_save
.get());
365 EXPECT_CALL(*store_
.get(), AddLogin(FormMatches(form
)));
367 // Simulate saving the form, as if the info bar was accepted.
368 form_to_save
->Save();
371 // This test verifies a fix for http://crbug.com/236673
372 TEST_F(PasswordManagerTest
, FormSubmitWithFormOnPreviousPage
) {
373 std::vector
<PasswordForm
*> result
; // Empty password store.
374 EXPECT_CALL(driver_
, FillPasswordForm(_
)).Times(Exactly(0));
375 EXPECT_CALL(*store_
.get(), GetLogins(_
, _
, _
))
376 .WillRepeatedly(DoAll(WithArg
<2>(InvokeConsumer(result
)), Return()));
377 PasswordForm
first_form(MakeSimpleForm());
378 first_form
.origin
= GURL("http://www.nytimes.com/");
379 first_form
.action
= GURL("https://myaccount.nytimes.com/auth/login");
380 first_form
.signon_realm
= "http://www.nytimes.com/";
381 PasswordForm
second_form(MakeSimpleForm());
382 second_form
.origin
= GURL("https://myaccount.nytimes.com/auth/login");
383 second_form
.action
= GURL("https://myaccount.nytimes.com/auth/login");
384 second_form
.signon_realm
= "https://myaccount.nytimes.com/";
386 // Pretend that the form is hidden on the first page.
387 std::vector
<PasswordForm
> observed
;
388 observed
.push_back(first_form
);
389 manager()->OnPasswordFormsParsed(observed
);
391 manager()->OnPasswordFormsRendered(observed
);
393 // Now navigate to a second page.
394 content::LoadCommittedDetails details
;
395 details
.is_main_frame
= true;
396 content::FrameNavigateParams params
;
397 manager()->DidNavigateMainFrame(details
, params
);
399 // This page contains a form with the same markup, but on a different
401 observed
.push_back(second_form
);
402 manager()->OnPasswordFormsParsed(observed
);
403 manager()->OnPasswordFormsRendered(observed
);
405 // Now submit this form
406 OnPasswordFormSubmitted(second_form
);
408 // Navigation after form submit.
409 scoped_ptr
<PasswordFormManager
> form_to_save
;
410 EXPECT_CALL(delegate_
, AddSavePasswordInfoBarIfPermitted(_
))
411 .WillOnce(WithArg
<0>(SaveToScopedPtr(&form_to_save
)));
413 manager()->OnPasswordFormsParsed(observed
);
414 manager()->OnPasswordFormsRendered(observed
);
416 // Make sure that the saved form matches the second form, not the first.
417 ASSERT_TRUE(form_to_save
.get());
418 EXPECT_CALL(*store_
.get(), AddLogin(FormMatches(second_form
)));
420 // Simulate saving the form, as if the info bar was accepted.
421 form_to_save
->Save();
424 TEST_F(PasswordManagerTest
, FormSubmitFailedLogin
) {
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.
435 manager()->ProvisionallySavePassword(form
);
437 // The form reappears, and is visible in the layout:
438 // No expected calls to the PasswordStore...
439 manager()->OnPasswordFormsParsed(observed
);
440 manager()->OnPasswordFormsRendered(observed
);
443 TEST_F(PasswordManagerTest
, FormSubmitInvisibleLogin
) {
444 // Tests fix of issue 28911: if the login form reappears on the subsequent
445 // page, but is invisible, it shouldn't count as a failed login.
446 std::vector
<PasswordForm
*> result
; // Empty password store.
447 EXPECT_CALL(driver_
, FillPasswordForm(_
)).Times(Exactly(0));
448 EXPECT_CALL(*store_
.get(), GetLogins(_
, _
, _
))
449 .WillRepeatedly(DoAll(WithArg
<2>(InvokeConsumer(result
)), Return()));
450 std::vector
<PasswordForm
> observed
;
451 PasswordForm
form(MakeSimpleForm());
452 observed
.push_back(form
);
453 manager()->OnPasswordFormsParsed(observed
); // The initial load.
454 manager()->OnPasswordFormsRendered(observed
); // The initial layout.
456 manager()->ProvisionallySavePassword(form
);
458 // Expect info bar to appear:
459 scoped_ptr
<PasswordFormManager
> form_to_save
;
460 EXPECT_CALL(delegate_
, AddSavePasswordInfoBarIfPermitted(_
))
461 .WillOnce(WithArg
<0>(SaveToScopedPtr(&form_to_save
)));
463 // The form reappears, but is not visible in the layout:
464 manager()->OnPasswordFormsParsed(observed
);
466 manager()->OnPasswordFormsRendered(observed
);
468 ASSERT_TRUE(form_to_save
.get());
469 EXPECT_CALL(*store_
.get(), AddLogin(FormMatches(form
)));
471 // Simulate saving the form.
472 form_to_save
->Save();
475 TEST_F(PasswordManagerTest
, InitiallyInvisibleForm
) {
476 // Make sure an invisible login form still gets autofilled.
477 std::vector
<PasswordForm
*> result
;
478 PasswordForm
* existing
= new PasswordForm(MakeSimpleForm());
479 result
.push_back(existing
);
480 EXPECT_CALL(driver_
, FillPasswordForm(_
));
481 EXPECT_CALL(*store_
.get(), GetLogins(_
, _
, _
))
482 .WillRepeatedly(DoAll(WithArg
<2>(InvokeConsumer(result
)), Return()));
483 std::vector
<PasswordForm
> observed
;
484 PasswordForm
form(MakeSimpleForm());
485 observed
.push_back(form
);
486 manager()->OnPasswordFormsParsed(observed
); // The initial load.
488 manager()->OnPasswordFormsRendered(observed
); // The initial layout.
490 manager()->OnPasswordFormsParsed(observed
); // The post-navigation load.
491 manager()->OnPasswordFormsRendered(observed
); // The post-navigation layout.
494 TEST_F(PasswordManagerTest
, SavingDependsOnManagerEnabledPreference
) {
495 // Test that saving passwords depends on the password manager enabled
497 TestingPrefServiceSyncable
* prefService
= profile()->GetTestingPrefService();
498 prefService
->SetUserPref(prefs::kPasswordManagerEnabled
,
499 base::Value::CreateBooleanValue(true));
500 EXPECT_TRUE(manager()->IsSavingEnabled());
501 prefService
->SetUserPref(prefs::kPasswordManagerEnabled
,
502 base::Value::CreateBooleanValue(false));
503 EXPECT_FALSE(manager()->IsSavingEnabled());
506 TEST_F(PasswordManagerTest
, FillPasswordsOnDisabledManager
) {
507 // Test fix for issue 158296: Passwords must be filled even if the password
508 // manager is disabled.
509 std::vector
<PasswordForm
*> result
;
510 PasswordForm
* existing
= new PasswordForm(MakeSimpleForm());
511 result
.push_back(existing
);
512 TestingPrefServiceSyncable
* prefService
= profile()->GetTestingPrefService();
513 prefService
->SetUserPref(prefs::kPasswordManagerEnabled
,
514 base::Value::CreateBooleanValue(false));
515 EXPECT_CALL(driver_
, FillPasswordForm(_
));
516 EXPECT_CALL(*store_
.get(),
517 GetLogins(_
, testing::Eq(PasswordStore::DISALLOW_PROMPT
), _
))
518 .WillRepeatedly(DoAll(WithArg
<2>(InvokeConsumer(result
)), Return()));
519 std::vector
<PasswordForm
> observed
;
520 PasswordForm
form(MakeSimpleForm());
521 observed
.push_back(form
);
522 manager()->OnPasswordFormsParsed(observed
);
525 TEST_F(PasswordManagerTest
, FormSavedWithAutocompleteOff
) {
526 // Test password form with non-generated password will be saved even if
528 std::vector
<PasswordForm
*> result
; // Empty password store.
529 EXPECT_CALL(driver_
, FillPasswordForm(_
)).Times(Exactly(0));
530 EXPECT_CALL(*store_
.get(), GetLogins(_
, _
, _
))
531 .WillOnce(DoAll(WithArg
<2>(InvokeConsumer(result
)), Return()));
532 std::vector
<PasswordForm
> observed
;
533 PasswordForm
form(MakeSimpleForm());
534 form
.password_autocomplete_set
= false;
535 observed
.push_back(form
);
536 manager()->OnPasswordFormsParsed(observed
); // The initial load.
537 manager()->OnPasswordFormsRendered(observed
); // The initial layout.
539 // And the form submit contract is to call ProvisionallySavePassword.
540 manager()->ProvisionallySavePassword(form
);
542 // Password form should be saved.
543 scoped_ptr
<PasswordFormManager
> form_to_save
;
544 EXPECT_CALL(delegate_
,
545 AddSavePasswordInfoBarIfPermitted(_
)).Times(Exactly(1))
546 .WillOnce(WithArg
<0>(SaveToScopedPtr(&form_to_save
)));
547 EXPECT_CALL(*store_
.get(), AddLogin(FormMatches(form
))).Times(Exactly(0));
549 // Now the password manager waits for the navigation to complete.
551 manager()->OnPasswordFormsParsed(observed
); // The post-navigation load.
552 manager()->OnPasswordFormsRendered(observed
); // The post-navigation layout.
554 ASSERT_TRUE(form_to_save
.get());
557 TEST_F(PasswordManagerTest
, GeneratedPasswordFormSavedAutocompleteOff
) {
558 // Test password form with generated password will still be saved if
560 std::vector
<PasswordForm
*> result
; // Empty password store.
561 EXPECT_CALL(driver_
, FillPasswordForm(_
)).Times(Exactly(0));
562 EXPECT_CALL(*store_
.get(), GetLogins(_
, _
, _
))
563 .WillOnce(DoAll(WithArg
<2>(InvokeConsumer(result
)), Return()));
564 std::vector
<PasswordForm
> observed
;
565 PasswordForm
form(MakeSimpleForm());
566 form
.password_autocomplete_set
= false;
567 observed
.push_back(form
);
568 manager()->OnPasswordFormsParsed(observed
); // The initial load.
569 manager()->OnPasswordFormsRendered(observed
); // The initial layout.
571 // Simulate the user generating the password and submitting the form.
572 manager()->SetFormHasGeneratedPassword(form
);
573 manager()->ProvisionallySavePassword(form
);
575 // The user should not be presented with an infobar as they have already given
576 // consent by using the generated password. The form should be saved once
577 // navigation occurs.
578 EXPECT_CALL(delegate_
,
579 AddSavePasswordInfoBarIfPermitted(_
)).Times(Exactly(0));
580 EXPECT_CALL(*store_
.get(), AddLogin(FormMatches(form
)));
582 // Now the password manager waits for the navigation to complete.
584 manager()->OnPasswordFormsParsed(observed
); // The post-navigation load.
585 manager()->OnPasswordFormsRendered(observed
); // The post-navigation layout.
588 TEST_F(PasswordManagerTest
, SubmissionCallbackTest
) {
589 manager()->AddSubmissionCallback(SubmissionCallback());
590 PasswordForm form
= MakeSimpleForm();
591 OnPasswordFormSubmitted(form
);
592 EXPECT_TRUE(FormsAreEqual(form
, submitted_form_
));
595 TEST_F(PasswordManagerTest
, PasswordFormReappearance
) {
596 // Test the heuristic to know if a password form reappears.
597 // We assume that if we send our credentials and there
598 // is at least one visible password form in the next page that
599 // means that our previous login attempt failed.
600 std::vector
<PasswordForm
*> result
; // Empty password store.
601 EXPECT_CALL(driver_
, FillPasswordForm(_
)).Times(0);
602 EXPECT_CALL(*store_
.get(), GetLogins(_
, _
, _
))
603 .WillRepeatedly(DoAll(WithArg
<2>(InvokeConsumer(result
)), Return()));
604 std::vector
<PasswordForm
> observed
;
605 PasswordForm
login_form(MakeTwitterLoginForm());
606 observed
.push_back(login_form
);
607 manager()->OnPasswordFormsParsed(observed
); // The initial load.
608 manager()->OnPasswordFormsRendered(observed
); // The initial layout.
610 manager()->ProvisionallySavePassword(login_form
);
612 PasswordForm
failed_login_form(MakeTwitterFailedLoginForm());
614 observed
.push_back(failed_login_form
);
615 // A PasswordForm appears, and is visible in the layout:
616 // No expected calls to the PasswordStore...
617 manager()->OnPasswordFormsParsed(observed
);
618 manager()->OnPasswordFormsRendered(observed
);