Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(310)

Side by Side Diff: chrome/browser/password_manager/password_manager_unittest.cc

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

Powered by Google App Engine
This is Rietveld 408576698