Remove the dependency of PasswordStore on BrowserContextKeyedService
[chromium-blink-merge.git] / chrome / browser / password_manager / password_manager_unittest.cc
blobbea214c6cc9b2b69c1eead072ce048e6f6261267
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/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;
32 using testing::_;
33 using testing::DoAll;
34 using testing::Exactly;
35 using testing::Return;
36 using testing::WithArg;
38 namespace {
40 class MockPasswordManagerDelegate : public PasswordManagerDelegate {
41 public:
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 {
49 public:
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) {
62 scoped->reset(arg0);
65 class TestPasswordManager : public PasswordManager {
66 public:
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);
76 private:
77 DISALLOW_COPY_AND_ASSIGN(TestPasswordManager);
80 } // namespace
82 class PasswordManagerTest : public ChromeRenderViewHostTestHarness {
83 protected:
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() {
108 store_ = NULL;
110 // Destroy the PasswordManager before tearing down the Profile to avoid
111 // crashes due to prefs accesses.
112 manager_.reset();
113 ChromeRenderViewHostTestHarness::TearDown();
116 PasswordForm MakeSimpleForm() {
117 PasswordForm form;
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";
128 return form;
131 // Reproduction of the form present on twitter's login page.
132 PasswordForm MakeTwitterLoginForm() {
133 PasswordForm form;
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";
143 return form;
146 // Reproduction of the form present on twitter's failed login page.
147 PasswordForm MakeTwitterFailedLoginForm() {
148 PasswordForm form;
149 form.origin =
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";
159 return form;
162 bool FormsAreEqual(const autofill::PasswordForm& lhs,
163 const autofill::PasswordForm& rhs) {
164 if (lhs.origin != rhs.origin)
165 return false;
166 if (lhs.action != rhs.action)
167 return false;
168 if (lhs.username_element != rhs.username_element)
169 return false;
170 if (lhs.password_element != rhs.password_element)
171 return false;
172 if (lhs.username_value != rhs.username_value)
173 return false;
174 if (lhs.password_value != rhs.password_value)
175 return false;
176 if (lhs.password_autocomplete_set != rhs.password_autocomplete_set)
177 return false;
178 if (lhs.submit_element != rhs.submit_element)
179 return false;
180 if (lhs.signon_realm != rhs.signon_realm)
181 return false;
182 return true;
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.
238 observed.clear();
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.
274 observed.clear();
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.
304 observed.clear();
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
327 // expected calls.
328 EXPECT_CALL(delegate_, AddSavePasswordInfoBarIfPermitted(_)).Times(0);
329 observed.clear();
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
336 // password infobar.
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)));
360 observed.clear();
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);
390 observed.clear();
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
400 // URL.
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)));
412 observed.clear();
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);
465 observed.clear();
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.
487 observed.clear();
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
496 // preference.
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
527 // autocomplete=off.
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.
550 observed.clear();
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
559 // autocomplete=off.
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.
583 observed.clear();
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());
613 observed.clear();
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);