password_manager_unittest.cc revision cedac228d2dd51db4b79ea1e72c7f249408ee061
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.
4
5#include <vector>
6
7#include "base/message_loop/message_loop.h"
8#include "base/prefs/pref_registry_simple.h"
9#include "base/prefs/pref_service.h"
10#include "base/prefs/testing_pref_service.h"
11#include "base/strings/string_util.h"
12#include "base/strings/utf_string_conversions.h"
13#include "components/password_manager/core/browser/mock_password_manager_driver.h"
14#include "components/password_manager/core/browser/mock_password_store.h"
15#include "components/password_manager/core/browser/password_autofill_manager.h"
16#include "components/password_manager/core/browser/password_manager.h"
17#include "components/password_manager/core/browser/password_manager_driver.h"
18#include "components/password_manager/core/browser/password_store.h"
19#include "components/password_manager/core/browser/stub_password_manager_client.h"
20#include "components/password_manager/core/common/password_manager_pref_names.h"
21#include "testing/gmock/include/gmock/gmock.h"
22#include "testing/gtest/include/gtest/gtest.h"
23
24class PasswordGenerationManager;
25
26using autofill::PasswordForm;
27using base::ASCIIToUTF16;
28using testing::_;
29using testing::AnyNumber;
30using testing::DoAll;
31using testing::Exactly;
32using testing::Return;
33using testing::WithArg;
34
35namespace autofill {
36class AutofillManager;
37}
38
39namespace password_manager {
40
41namespace {
42
43class MockPasswordManagerClient : public StubPasswordManagerClient {
44 public:
45  MOCK_METHOD1(PromptUserToSavePassword, void(PasswordFormManager*));
46  MOCK_METHOD0(GetPasswordStore, PasswordStore*());
47  MOCK_METHOD0(GetPrefs, PrefService*());
48  MOCK_METHOD0(GetDriver, PasswordManagerDriver*());
49};
50
51ACTION_P(InvokeConsumer, forms) { arg0->OnGetPasswordStoreResults(forms); }
52
53ACTION_P(SaveToScopedPtr, scoped) { scoped->reset(arg0); }
54
55class TestPasswordManager : public PasswordManager {
56 public:
57  explicit TestPasswordManager(PasswordManagerClient* client)
58      : PasswordManager(client) {}
59  virtual ~TestPasswordManager() {}
60
61 private:
62  DISALLOW_COPY_AND_ASSIGN(TestPasswordManager);
63};
64
65}  // namespace
66
67class PasswordManagerTest : public testing::Test {
68 protected:
69  virtual void SetUp() {
70    prefs_.registry()->RegisterBooleanPref(prefs::kPasswordManagerEnabled,
71                                           true);
72
73    store_ = new MockPasswordStore;
74    EXPECT_CALL(*store_, ReportMetrics()).Times(AnyNumber());
75    CHECK(store_->Init(syncer::SyncableService::StartSyncFlare()));
76
77    EXPECT_CALL(client_, GetPasswordStore()).WillRepeatedly(Return(store_));
78    EXPECT_CALL(client_, GetPrefs()).WillRepeatedly(Return(&prefs_));
79    EXPECT_CALL(client_, GetDriver()).WillRepeatedly(Return(&driver_));
80
81    manager_.reset(new TestPasswordManager(&client_));
82    password_autofill_manager_.reset(
83        new PasswordAutofillManager(&client_, NULL));
84
85    EXPECT_CALL(driver_, DidLastPageLoadEncounterSSLErrors())
86        .WillRepeatedly(Return(false));
87    EXPECT_CALL(driver_, IsOffTheRecord()).WillRepeatedly(Return(false));
88    EXPECT_CALL(driver_, GetPasswordGenerationManager())
89        .WillRepeatedly(Return(static_cast<PasswordGenerationManager*>(NULL)));
90    EXPECT_CALL(driver_, GetPasswordManager())
91        .WillRepeatedly(Return(manager_.get()));
92    EXPECT_CALL(driver_, AllowPasswordGenerationForForm(_)).Times(AnyNumber());
93    EXPECT_CALL(driver_, GetPasswordAutofillManager())
94        .WillRepeatedly(Return(password_autofill_manager_.get()));
95  }
96
97  virtual void TearDown() {
98    store_->Shutdown();
99    store_ = NULL;
100  }
101
102  PasswordForm MakeSimpleForm() {
103    PasswordForm form;
104    form.origin = GURL("http://www.google.com/a/LoginAuth");
105    form.action = GURL("http://www.google.com/a/Login");
106    form.username_element = ASCIIToUTF16("Email");
107    form.password_element = ASCIIToUTF16("Passwd");
108    form.username_value = ASCIIToUTF16("google");
109    form.password_value = ASCIIToUTF16("password");
110    // Default to true so we only need to add tests in autocomplete=off cases.
111    form.password_autocomplete_set = true;
112    form.submit_element = ASCIIToUTF16("signIn");
113    form.signon_realm = "http://www.google.com";
114    return form;
115  }
116
117  // Reproduction of the form present on twitter's login page.
118  PasswordForm MakeTwitterLoginForm() {
119    PasswordForm form;
120    form.origin = GURL("https://twitter.com/");
121    form.action = GURL("https://twitter.com/sessions");
122    form.username_element = ASCIIToUTF16("Email");
123    form.password_element = ASCIIToUTF16("Passwd");
124    form.username_value = ASCIIToUTF16("twitter");
125    form.password_value = ASCIIToUTF16("password");
126    form.password_autocomplete_set = true;
127    form.submit_element = ASCIIToUTF16("signIn");
128    form.signon_realm = "https://twitter.com";
129    return form;
130  }
131
132  // Reproduction of the form present on twitter's failed login page.
133  PasswordForm MakeTwitterFailedLoginForm() {
134    PasswordForm form;
135    form.origin = GURL("https://twitter.com/login/error?redirect_after_login");
136    form.action = GURL("https://twitter.com/sessions");
137    form.username_element = ASCIIToUTF16("EmailField");
138    form.password_element = ASCIIToUTF16("PasswdField");
139    form.username_value = ASCIIToUTF16("twitter");
140    form.password_value = ASCIIToUTF16("password");
141    form.password_autocomplete_set = true;
142    form.submit_element = ASCIIToUTF16("signIn");
143    form.signon_realm = "https://twitter.com";
144    return form;
145  }
146
147  bool FormsAreEqual(const autofill::PasswordForm& lhs,
148                     const autofill::PasswordForm& rhs) {
149    if (lhs.origin != rhs.origin)
150      return false;
151    if (lhs.action != rhs.action)
152      return false;
153    if (lhs.username_element != rhs.username_element)
154      return false;
155    if (lhs.password_element != rhs.password_element)
156      return false;
157    if (lhs.username_value != rhs.username_value)
158      return false;
159    if (lhs.password_value != rhs.password_value)
160      return false;
161    if (lhs.password_autocomplete_set != rhs.password_autocomplete_set)
162      return false;
163    if (lhs.submit_element != rhs.submit_element)
164      return false;
165    if (lhs.signon_realm != rhs.signon_realm)
166      return false;
167    return true;
168  }
169
170  TestPasswordManager* manager() { return manager_.get(); }
171
172  void OnPasswordFormSubmitted(const autofill::PasswordForm& form) {
173    manager()->OnPasswordFormSubmitted(form);
174  }
175
176  PasswordManager::PasswordSubmittedCallback SubmissionCallback() {
177    return base::Bind(&PasswordManagerTest::FormSubmitted,
178                      base::Unretained(this));
179  }
180
181  void FormSubmitted(const autofill::PasswordForm& form) {
182    submitted_form_ = form;
183  }
184
185  TestingPrefServiceSimple prefs_;
186  scoped_refptr<MockPasswordStore> store_;
187  MockPasswordManagerClient client_;
188  MockPasswordManagerDriver driver_;
189  scoped_ptr<PasswordAutofillManager> password_autofill_manager_;
190  scoped_ptr<TestPasswordManager> manager_;
191  PasswordForm submitted_form_;
192};
193
194MATCHER_P(FormMatches, form, "") {
195  return form.signon_realm == arg.signon_realm && form.origin == arg.origin &&
196         form.action == arg.action &&
197         form.username_element == arg.username_element &&
198         form.password_element == arg.password_element &&
199         form.password_autocomplete_set == arg.password_autocomplete_set &&
200         form.submit_element == arg.submit_element;
201}
202
203TEST_F(PasswordManagerTest, FormSubmitEmptyStore) {
204  // Test that observing a newly submitted form shows the save password bar.
205  std::vector<PasswordForm*> result;  // Empty password store.
206  EXPECT_CALL(driver_, FillPasswordForm(_)).Times(Exactly(0));
207  EXPECT_CALL(*store_.get(), GetLogins(_, _, _))
208      .WillOnce(DoAll(WithArg<2>(InvokeConsumer(result)), Return()));
209  std::vector<PasswordForm> observed;
210  PasswordForm form(MakeSimpleForm());
211  observed.push_back(form);
212  manager()->OnPasswordFormsParsed(observed);    // The initial load.
213  manager()->OnPasswordFormsRendered(observed);  // The initial layout.
214
215  // And the form submit contract is to call ProvisionallySavePassword.
216  manager()->ProvisionallySavePassword(form);
217
218  scoped_ptr<PasswordFormManager> form_to_save;
219  EXPECT_CALL(client_, PromptUserToSavePassword(_))
220      .WillOnce(WithArg<0>(SaveToScopedPtr(&form_to_save)));
221
222  // Now the password manager waits for the navigation to complete.
223  observed.clear();
224  manager()->OnPasswordFormsParsed(observed);    // The post-navigation load.
225  manager()->OnPasswordFormsRendered(observed);  // The post-navigation layout.
226
227  ASSERT_TRUE(form_to_save.get());
228  EXPECT_CALL(*store_.get(), AddLogin(FormMatches(form)));
229
230  // Simulate saving the form, as if the info bar was accepted.
231  form_to_save->Save();
232}
233
234TEST_F(PasswordManagerTest, GeneratedPasswordFormSubmitEmptyStore) {
235  // This test is the same FormSubmitEmptyStore, except that it simulates the
236  // user generating the password through the browser.
237  std::vector<PasswordForm*> result;  // Empty password store.
238  EXPECT_CALL(driver_, FillPasswordForm(_)).Times(Exactly(0));
239  EXPECT_CALL(*store_.get(), GetLogins(_, _, _))
240      .WillOnce(DoAll(WithArg<2>(InvokeConsumer(result)), Return()));
241  std::vector<PasswordForm> observed;
242  PasswordForm form(MakeSimpleForm());
243  observed.push_back(form);
244  manager()->OnPasswordFormsParsed(observed);    // The initial load.
245  manager()->OnPasswordFormsRendered(observed);  // The initial layout.
246
247  // Simulate the user generating the password and submitting the form.
248  manager()->SetFormHasGeneratedPassword(form);
249  manager()->ProvisionallySavePassword(form);
250
251  // The user should not be presented with an infobar as they have already given
252  // consent by using the generated password. The form should be saved once
253  // navigation occurs.
254  EXPECT_CALL(client_, PromptUserToSavePassword(_)).Times(Exactly(0));
255  EXPECT_CALL(*store_.get(), AddLogin(FormMatches(form)));
256
257  // Now the password manager waits for the navigation to complete.
258  observed.clear();
259  manager()->OnPasswordFormsParsed(observed);    // The post-navigation load.
260  manager()->OnPasswordFormsRendered(observed);  // The post-navigation layout.
261}
262
263TEST_F(PasswordManagerTest, FormSubmitNoGoodMatch) {
264  // Same as above, except with an existing form for the same signon realm,
265  // but different origin.  Detailed cases like this are covered by
266  // PasswordFormManagerTest.
267  std::vector<PasswordForm*> result;
268  PasswordForm* existing_different = new PasswordForm(MakeSimpleForm());
269  existing_different->username_value = ASCIIToUTF16("google2");
270  result.push_back(existing_different);
271  EXPECT_CALL(driver_, FillPasswordForm(_));
272  EXPECT_CALL(*store_.get(), GetLogins(_, _, _))
273      .WillOnce(DoAll(WithArg<2>(InvokeConsumer(result)), Return()));
274
275  std::vector<PasswordForm> observed;
276  PasswordForm form(MakeSimpleForm());
277  observed.push_back(form);
278  manager()->OnPasswordFormsParsed(observed);    // The initial load.
279  manager()->OnPasswordFormsRendered(observed);  // The initial layout.
280  manager()->ProvisionallySavePassword(form);
281
282  // We still expect an add, since we didn't have a good match.
283  scoped_ptr<PasswordFormManager> form_to_save;
284  EXPECT_CALL(client_, PromptUserToSavePassword(_))
285      .WillOnce(WithArg<0>(SaveToScopedPtr(&form_to_save)));
286
287  // Now the password manager waits for the navigation to complete.
288  observed.clear();
289  manager()->OnPasswordFormsParsed(observed);    // The post-navigation load.
290  manager()->OnPasswordFormsRendered(observed);  // The post-navigation layout.
291
292  ASSERT_TRUE(form_to_save.get());
293  EXPECT_CALL(*store_.get(), AddLogin(FormMatches(form)));
294
295  // Simulate saving the form.
296  form_to_save->Save();
297}
298
299TEST_F(PasswordManagerTest, FormSeenThenLeftPage) {
300  std::vector<PasswordForm*> result;  // Empty password store.
301  EXPECT_CALL(driver_, FillPasswordForm(_)).Times(Exactly(0));
302  EXPECT_CALL(*store_.get(), GetLogins(_, _, _))
303      .WillOnce(DoAll(WithArg<2>(InvokeConsumer(result)), Return()));
304  std::vector<PasswordForm> observed;
305  PasswordForm form(MakeSimpleForm());
306  observed.push_back(form);
307  manager()->OnPasswordFormsParsed(observed);    // The initial load.
308  manager()->OnPasswordFormsRendered(observed);  // The initial layout.
309
310  // No message from the renderer that a password was submitted. No
311  // expected calls.
312  EXPECT_CALL(client_, PromptUserToSavePassword(_)).Times(0);
313  observed.clear();
314  manager()->OnPasswordFormsParsed(observed);    // The post-navigation load.
315  manager()->OnPasswordFormsRendered(observed);  // The post-navigation layout.
316}
317
318TEST_F(PasswordManagerTest, FormSubmitAfterNavigateInPage) {
319  // Test that navigating in the page does not prevent us from showing the save
320  // password infobar.
321  std::vector<PasswordForm*> result;  // Empty password store.
322  EXPECT_CALL(driver_, FillPasswordForm(_)).Times(Exactly(0));
323  EXPECT_CALL(*store_.get(), GetLogins(_, _, _))
324      .WillOnce(DoAll(WithArg<2>(InvokeConsumer(result)), Return()));
325  std::vector<PasswordForm> observed;
326  PasswordForm form(MakeSimpleForm());
327  observed.push_back(form);
328  manager()->OnPasswordFormsParsed(observed);    // The initial load.
329  manager()->OnPasswordFormsRendered(observed);  // The initial layout.
330
331  // Simulate navigating in the page.
332  manager()->DidNavigateMainFrame(true);
333
334  // Simulate submitting the password.
335  OnPasswordFormSubmitted(form);
336
337  // Now the password manager waits for the navigation to complete.
338  scoped_ptr<PasswordFormManager> form_to_save;
339  EXPECT_CALL(client_, PromptUserToSavePassword(_))
340      .WillOnce(WithArg<0>(SaveToScopedPtr(&form_to_save)));
341
342  observed.clear();
343  manager()->OnPasswordFormsParsed(observed);    // The post-navigation load.
344  manager()->OnPasswordFormsRendered(observed);  // The post-navigation layout.
345
346  ASSERT_FALSE(NULL == form_to_save.get());
347  EXPECT_CALL(*store_.get(), AddLogin(FormMatches(form)));
348
349  // Simulate saving the form, as if the info bar was accepted.
350  form_to_save->Save();
351}
352
353// This test verifies a fix for http://crbug.com/236673
354TEST_F(PasswordManagerTest, FormSubmitWithFormOnPreviousPage) {
355  std::vector<PasswordForm*> result;  // Empty password store.
356  EXPECT_CALL(driver_, FillPasswordForm(_)).Times(Exactly(0));
357  EXPECT_CALL(*store_.get(), GetLogins(_, _, _))
358      .WillRepeatedly(DoAll(WithArg<2>(InvokeConsumer(result)), Return()));
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/";
367
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);
374
375  // Now navigate to a second page.
376  manager()->DidNavigateMainFrame(false);
377
378  // This page contains a form with the same markup, but on a different
379  // URL.
380  observed.push_back(second_form);
381  manager()->OnPasswordFormsParsed(observed);
382  manager()->OnPasswordFormsRendered(observed);
383
384  // Now submit this form
385  OnPasswordFormSubmitted(second_form);
386
387  // Navigation after form submit.
388  scoped_ptr<PasswordFormManager> form_to_save;
389  EXPECT_CALL(client_, PromptUserToSavePassword(_))
390      .WillOnce(WithArg<0>(SaveToScopedPtr(&form_to_save)));
391  observed.clear();
392  manager()->OnPasswordFormsParsed(observed);
393  manager()->OnPasswordFormsRendered(observed);
394
395  // Make sure that the saved form matches the second form, not the first.
396  ASSERT_TRUE(form_to_save.get());
397  EXPECT_CALL(*store_.get(), AddLogin(FormMatches(second_form)));
398
399  // Simulate saving the form, as if the info bar was accepted.
400  form_to_save->Save();
401}
402
403TEST_F(PasswordManagerTest, FormSubmitFailedLogin) {
404  std::vector<PasswordForm*> result;  // Empty password store.
405  EXPECT_CALL(driver_, FillPasswordForm(_)).Times(Exactly(0));
406  EXPECT_CALL(*store_.get(), GetLogins(_, _, _))
407      .WillRepeatedly(DoAll(WithArg<2>(InvokeConsumer(result)), Return()));
408  std::vector<PasswordForm> observed;
409  PasswordForm form(MakeSimpleForm());
410  observed.push_back(form);
411  manager()->OnPasswordFormsParsed(observed);    // The initial load.
412  manager()->OnPasswordFormsRendered(observed);  // The initial layout.
413
414  manager()->ProvisionallySavePassword(form);
415
416  // The form reappears, and is visible in the layout:
417  // No expected calls to the PasswordStore...
418  manager()->OnPasswordFormsParsed(observed);
419  manager()->OnPasswordFormsRendered(observed);
420}
421
422TEST_F(PasswordManagerTest, FormSubmitInvisibleLogin) {
423  // Tests fix of issue 28911: if the login form reappears on the subsequent
424  // page, but is invisible, it shouldn't count as a failed login.
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.
434
435  manager()->ProvisionallySavePassword(form);
436
437  // Expect info bar to appear:
438  scoped_ptr<PasswordFormManager> form_to_save;
439  EXPECT_CALL(client_, PromptUserToSavePassword(_))
440      .WillOnce(WithArg<0>(SaveToScopedPtr(&form_to_save)));
441
442  // The form reappears, but is not visible in the layout:
443  manager()->OnPasswordFormsParsed(observed);
444  observed.clear();
445  manager()->OnPasswordFormsRendered(observed);
446
447  ASSERT_TRUE(form_to_save.get());
448  EXPECT_CALL(*store_.get(), AddLogin(FormMatches(form)));
449
450  // Simulate saving the form.
451  form_to_save->Save();
452}
453
454TEST_F(PasswordManagerTest, InitiallyInvisibleForm) {
455  // Make sure an invisible login form still gets autofilled.
456  std::vector<PasswordForm*> result;
457  PasswordForm* existing = new PasswordForm(MakeSimpleForm());
458  result.push_back(existing);
459  EXPECT_CALL(driver_, FillPasswordForm(_));
460  EXPECT_CALL(*store_.get(), GetLogins(_, _, _))
461      .WillRepeatedly(DoAll(WithArg<2>(InvokeConsumer(result)), Return()));
462  std::vector<PasswordForm> observed;
463  PasswordForm form(MakeSimpleForm());
464  observed.push_back(form);
465  manager()->OnPasswordFormsParsed(observed);  // The initial load.
466  observed.clear();
467  manager()->OnPasswordFormsRendered(observed);  // The initial layout.
468
469  manager()->OnPasswordFormsParsed(observed);    // The post-navigation load.
470  manager()->OnPasswordFormsRendered(observed);  // The post-navigation layout.
471}
472
473TEST_F(PasswordManagerTest, SavingDependsOnManagerEnabledPreference) {
474  // Test that saving passwords depends on the password manager enabled
475  // preference.
476  prefs_.SetUserPref(prefs::kPasswordManagerEnabled,
477                     base::Value::CreateBooleanValue(true));
478  EXPECT_TRUE(manager()->IsSavingEnabled());
479  prefs_.SetUserPref(prefs::kPasswordManagerEnabled,
480                     base::Value::CreateBooleanValue(false));
481  EXPECT_FALSE(manager()->IsSavingEnabled());
482}
483
484TEST_F(PasswordManagerTest, FillPasswordsOnDisabledManager) {
485  // Test fix for issue 158296: Passwords must be filled even if the password
486  // manager is disabled.
487  std::vector<PasswordForm*> result;
488  PasswordForm* existing = new PasswordForm(MakeSimpleForm());
489  result.push_back(existing);
490  prefs_.SetUserPref(prefs::kPasswordManagerEnabled,
491                     base::Value::CreateBooleanValue(false));
492  EXPECT_CALL(driver_, FillPasswordForm(_));
493  EXPECT_CALL(*store_.get(),
494              GetLogins(_, testing::Eq(PasswordStore::DISALLOW_PROMPT), _))
495      .WillRepeatedly(DoAll(WithArg<2>(InvokeConsumer(result)), Return()));
496  std::vector<PasswordForm> observed;
497  PasswordForm form(MakeSimpleForm());
498  observed.push_back(form);
499  manager()->OnPasswordFormsParsed(observed);
500}
501
502TEST_F(PasswordManagerTest, FormSavedWithAutocompleteOff) {
503  // Test password form with non-generated password will be saved even if
504  // autocomplete=off.
505  std::vector<PasswordForm*> result;  // Empty password store.
506  EXPECT_CALL(driver_, FillPasswordForm(_)).Times(Exactly(0));
507  EXPECT_CALL(*store_.get(), GetLogins(_, _, _))
508      .WillOnce(DoAll(WithArg<2>(InvokeConsumer(result)), Return()));
509  std::vector<PasswordForm> observed;
510  PasswordForm form(MakeSimpleForm());
511  form.password_autocomplete_set = false;
512  observed.push_back(form);
513  manager()->OnPasswordFormsParsed(observed);    // The initial load.
514  manager()->OnPasswordFormsRendered(observed);  // The initial layout.
515
516  // And the form submit contract is to call ProvisionallySavePassword.
517  manager()->ProvisionallySavePassword(form);
518
519  // Password form should be saved.
520  scoped_ptr<PasswordFormManager> form_to_save;
521  EXPECT_CALL(client_, PromptUserToSavePassword(_)).Times(Exactly(1)).WillOnce(
522      WithArg<0>(SaveToScopedPtr(&form_to_save)));
523  EXPECT_CALL(*store_.get(), AddLogin(FormMatches(form))).Times(Exactly(0));
524
525  // Now the password manager waits for the navigation to complete.
526  observed.clear();
527  manager()->OnPasswordFormsParsed(observed);    // The post-navigation load.
528  manager()->OnPasswordFormsRendered(observed);  // The post-navigation layout.
529
530  ASSERT_TRUE(form_to_save.get());
531}
532
533TEST_F(PasswordManagerTest, GeneratedPasswordFormSavedAutocompleteOff) {
534  // Test password form with generated password will still be saved if
535  // autocomplete=off.
536  std::vector<PasswordForm*> result;  // Empty password store.
537  EXPECT_CALL(driver_, FillPasswordForm(_)).Times(Exactly(0));
538  EXPECT_CALL(*store_.get(), GetLogins(_, _, _))
539      .WillOnce(DoAll(WithArg<2>(InvokeConsumer(result)), Return()));
540  std::vector<PasswordForm> observed;
541  PasswordForm form(MakeSimpleForm());
542  form.password_autocomplete_set = false;
543  observed.push_back(form);
544  manager()->OnPasswordFormsParsed(observed);    // The initial load.
545  manager()->OnPasswordFormsRendered(observed);  // The initial layout.
546
547  // Simulate the user generating the password and submitting the form.
548  manager()->SetFormHasGeneratedPassword(form);
549  manager()->ProvisionallySavePassword(form);
550
551  // The user should not be presented with an infobar as they have already given
552  // consent by using the generated password. The form should be saved once
553  // navigation occurs.
554  EXPECT_CALL(client_, PromptUserToSavePassword(_)).Times(Exactly(0));
555  EXPECT_CALL(*store_.get(), AddLogin(FormMatches(form)));
556
557  // Now the password manager waits for the navigation to complete.
558  observed.clear();
559  manager()->OnPasswordFormsParsed(observed);    // The post-navigation load.
560  manager()->OnPasswordFormsRendered(observed);  // The post-navigation layout.
561}
562
563TEST_F(PasswordManagerTest, SubmissionCallbackTest) {
564  manager()->AddSubmissionCallback(SubmissionCallback());
565  PasswordForm form = MakeSimpleForm();
566  OnPasswordFormSubmitted(form);
567  EXPECT_TRUE(FormsAreEqual(form, submitted_form_));
568}
569
570TEST_F(PasswordManagerTest, PasswordFormReappearance) {
571  // Test the heuristic to know if a password form reappears.
572  // We assume that if we send our credentials and there
573  // is at least one visible password form in the next page that
574  // means that our previous login attempt failed.
575  std::vector<PasswordForm*> result;  // Empty password store.
576  EXPECT_CALL(driver_, FillPasswordForm(_)).Times(0);
577  EXPECT_CALL(*store_.get(), GetLogins(_, _, _))
578      .WillRepeatedly(DoAll(WithArg<2>(InvokeConsumer(result)), Return()));
579  std::vector<PasswordForm> observed;
580  PasswordForm login_form(MakeTwitterLoginForm());
581  observed.push_back(login_form);
582  manager()->OnPasswordFormsParsed(observed);    // The initial load.
583  manager()->OnPasswordFormsRendered(observed);  // The initial layout.
584
585  manager()->ProvisionallySavePassword(login_form);
586
587  PasswordForm failed_login_form(MakeTwitterFailedLoginForm());
588  observed.clear();
589  observed.push_back(failed_login_form);
590  // A PasswordForm appears, and is visible in the layout:
591  // No expected calls to the PasswordStore...
592  manager()->OnPasswordFormsParsed(observed);
593  manager()->OnPasswordFormsRendered(observed);
594}
595
596}  // namespace password_manager
597