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