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 "base/memory/scoped_ptr.h"
6 #include "base/message_loop/message_loop.h"
7 #include "base/prefs/pref_registry_simple.h"
8 #include "base/prefs/pref_service.h"
9 #include "base/prefs/testing_pref_service.h"
10 #include "base/run_loop.h"
11 #include "base/strings/string_util.h"
12 #include "base/strings/utf_string_conversions.h"
13 #include "components/autofill/core/common/password_form.h"
14 #include "components/password_manager/core/browser/mock_password_store.h"
15 #include "components/password_manager/core/browser/password_form_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/browser/stub_password_manager_driver.h"
21 #include "components/password_manager/core/browser/test_password_store.h"
22 #include "components/password_manager/core/common/password_manager_pref_names.h"
23 #include "testing/gmock/include/gmock/gmock.h"
24 #include "testing/gtest/include/gtest/gtest.h"
26 using autofill::PasswordForm;
27 using base::ASCIIToUTF16;
30 using ::testing::Mock;
31 using ::testing::Return;
34 class AutofillManager;
37 namespace password_manager {
41 void RunAllPendingTasks() {
42 base::RunLoop run_loop;
43 base::MessageLoop::current()->PostTask(
44 FROM_HERE, base::MessageLoop::QuitWhenIdleClosure());
48 class MockPasswordManagerDriver : public StubPasswordManagerDriver {
50 MOCK_METHOD0(IsOffTheRecord, bool());
51 MOCK_METHOD1(AllowPasswordGenerationForForm,
52 void(const autofill::PasswordForm&));
55 class TestPasswordManagerClient : public StubPasswordManagerClient {
57 explicit TestPasswordManagerClient(PasswordStore* password_store)
58 : password_store_(password_store) {
59 prefs_.registry()->RegisterBooleanPref(prefs::kPasswordManagerSavingEnabled,
63 virtual bool ShouldFilterAutofillResult(
64 const autofill::PasswordForm& form) OVERRIDE {
65 if (form == form_to_filter_)
70 virtual void PromptUserToSavePassword(
71 scoped_ptr<PasswordFormManager> form_to_save) OVERRIDE {}
72 virtual PrefService* GetPrefs() OVERRIDE { return &prefs_; }
73 virtual PasswordStore* GetPasswordStore() OVERRIDE { return password_store_; }
74 virtual PasswordManagerDriver* GetDriver() OVERRIDE { return &driver_; }
75 virtual void AuthenticateAutofillAndFillForm(
76 scoped_ptr<autofill::PasswordFormFillData> fill_data) OVERRIDE {
77 driver_.FillPasswordForm(*fill_data.get());
80 void SetFormToFilter(const autofill::PasswordForm& form) {
81 form_to_filter_ = form;
84 MockPasswordManagerDriver* GetMockDriver() { return &driver_; }
87 autofill::PasswordForm form_to_filter_;
89 TestingPrefServiceSimple prefs_;
90 PasswordStore* password_store_;
91 MockPasswordManagerDriver driver_;
94 class TestPasswordManager : public PasswordManager {
96 explicit TestPasswordManager(PasswordManagerClient* client)
97 : PasswordManager(client) {}
99 virtual void Autofill(const autofill::PasswordForm& form_for_autofill,
100 const autofill::PasswordFormMap& best_matches,
101 const autofill::PasswordForm& preferred_match,
102 bool wait_for_username) const OVERRIDE {
103 best_matches_ = best_matches;
106 const autofill::PasswordFormMap& GetLatestBestMatches() {
107 return best_matches_;
111 // Marked mutable to get around constness of Autofill().
112 mutable autofill::PasswordFormMap best_matches_;
117 class PasswordFormManagerTest : public testing::Test {
119 PasswordFormManagerTest() : client_(NULL /*password_store*/) {}
121 // Types of possible outcomes of simulated matching, see
122 // SimulateMatchingPhase.
123 enum ResultOfSimulatedMatching { RESULT_MATCH_FOUND, RESULT_NO_MATCH };
125 virtual void SetUp() {
126 observed_form_.origin = GURL("http://accounts.google.com/a/LoginAuth");
127 observed_form_.action = GURL("http://accounts.google.com/a/Login");
128 observed_form_.username_element = ASCIIToUTF16("Email");
129 observed_form_.password_element = ASCIIToUTF16("Passwd");
130 observed_form_.submit_element = ASCIIToUTF16("signIn");
131 observed_form_.signon_realm = "http://accounts.google.com";
133 saved_match_ = observed_form_;
134 saved_match_.origin = GURL("http://accounts.google.com/a/ServiceLoginAuth");
135 saved_match_.action = GURL("http://accounts.google.com/a/ServiceLogin");
136 saved_match_.preferred = true;
137 saved_match_.username_value = ASCIIToUTF16("test@gmail.com");
138 saved_match_.password_value = ASCIIToUTF16("test1");
139 saved_match_.other_possible_usernames.push_back(
140 ASCIIToUTF16("test2@gmail.com"));
143 virtual void TearDown() {
145 mock_store_->Shutdown();
148 void InitializeMockStore() {
150 mock_store_ = new MockPasswordStore();
151 ASSERT_TRUE(mock_store_);
155 MockPasswordStore* mock_store() const { return mock_store_.get(); }
157 PasswordForm* GetPendingCredentials(PasswordFormManager* p) {
158 return &p->pending_credentials_;
161 void SimulateMatchingPhase(PasswordFormManager* p,
162 ResultOfSimulatedMatching result) {
163 // Roll up the state to mock out the matching phase.
164 p->state_ = PasswordFormManager::POST_MATCHING_PHASE;
165 if (result == RESULT_NO_MATCH)
168 PasswordForm* match = new PasswordForm(saved_match_);
169 // Heap-allocated form is owned by p.
170 p->best_matches_[match->username_value] = match;
171 p->preferred_match_ = match;
174 void SimulateFetchMatchingLoginsFromPasswordStore(
175 PasswordFormManager* manager) {
176 // Just need to update the internal states.
177 manager->state_ = PasswordFormManager::MATCHING_PHASE;
180 void SimulateResponseFromPasswordStore(
181 PasswordFormManager* manager,
182 const std::vector<PasswordForm*>& result) {
183 // Simply call the callback method when request done. This will transfer
184 // the ownership of the objects in |result| to the |manager|.
185 manager->OnGetPasswordStoreResults(result);
188 void SanitizePossibleUsernames(PasswordFormManager* p, PasswordForm* form) {
189 p->SanitizePossibleUsernames(form);
192 bool IgnoredResult(PasswordFormManager* p, PasswordForm* form) {
193 return p->ShouldIgnoreResult(*form);
196 PasswordForm* observed_form() { return &observed_form_; }
197 PasswordForm* saved_match() { return &saved_match_; }
198 PasswordForm* CreateSavedMatch(bool blacklisted) {
199 // Owned by the caller of this method.
200 PasswordForm* match = new PasswordForm(saved_match_);
201 match->blacklisted_by_user = blacklisted;
205 TestPasswordManagerClient* client() { return &client_; }
208 PasswordForm observed_form_;
209 PasswordForm saved_match_;
210 scoped_refptr<MockPasswordStore> mock_store_;
211 TestPasswordManagerClient client_;
214 TEST_F(PasswordFormManagerTest, TestNewLogin) {
215 PasswordFormManager manager(NULL, client(), NULL, *observed_form(), false);
216 SimulateMatchingPhase(&manager, RESULT_NO_MATCH);
218 // User submits credentials for the observed form.
219 PasswordForm credentials = *observed_form();
220 credentials.username_value = saved_match()->username_value;
221 credentials.password_value = saved_match()->password_value;
222 credentials.preferred = true;
223 manager.ProvisionallySave(
224 credentials, PasswordFormManager::IGNORE_OTHER_POSSIBLE_USERNAMES);
226 // Successful login. The PasswordManager would instruct PasswordFormManager
227 // to save, which should know this is a new login.
228 EXPECT_TRUE(manager.IsNewLogin());
229 // Make sure the credentials that would be submitted on successful login
230 // are going to match the stored entry in the db.
231 EXPECT_EQ(observed_form()->origin.spec(),
232 GetPendingCredentials(&manager)->origin.spec());
233 EXPECT_EQ(observed_form()->signon_realm,
234 GetPendingCredentials(&manager)->signon_realm);
235 EXPECT_EQ(observed_form()->action, GetPendingCredentials(&manager)->action);
236 EXPECT_TRUE(GetPendingCredentials(&manager)->preferred);
237 EXPECT_EQ(saved_match()->password_value,
238 GetPendingCredentials(&manager)->password_value);
239 EXPECT_EQ(saved_match()->username_value,
240 GetPendingCredentials(&manager)->username_value);
241 EXPECT_TRUE(GetPendingCredentials(&manager)->new_password_element.empty());
242 EXPECT_TRUE(GetPendingCredentials(&manager)->new_password_value.empty());
244 // Now, suppose the user re-visits the site and wants to save an additional
245 // login for the site with a new username. In this case, the matching phase
246 // will yield the previously saved login.
247 SimulateMatchingPhase(&manager, RESULT_MATCH_FOUND);
248 // Set up the new login.
249 base::string16 new_user = ASCIIToUTF16("newuser");
250 base::string16 new_pass = ASCIIToUTF16("newpass");
251 credentials.username_value = new_user;
252 credentials.password_value = new_pass;
253 manager.ProvisionallySave(
254 credentials, PasswordFormManager::IGNORE_OTHER_POSSIBLE_USERNAMES);
256 // Again, the PasswordFormManager should know this is still a new login.
257 EXPECT_TRUE(manager.IsNewLogin());
258 // And make sure everything squares up again.
259 EXPECT_EQ(observed_form()->origin.spec(),
260 GetPendingCredentials(&manager)->origin.spec());
261 EXPECT_EQ(observed_form()->signon_realm,
262 GetPendingCredentials(&manager)->signon_realm);
263 EXPECT_TRUE(GetPendingCredentials(&manager)->preferred);
264 EXPECT_EQ(new_pass, GetPendingCredentials(&manager)->password_value);
265 EXPECT_EQ(new_user, GetPendingCredentials(&manager)->username_value);
266 EXPECT_TRUE(GetPendingCredentials(&manager)->new_password_element.empty());
267 EXPECT_TRUE(GetPendingCredentials(&manager)->new_password_value.empty());
270 // If PSL-matched credentials had been suggested, but the user has overwritten
271 // the password, the provisionally saved credentials should no longer be
272 // considered as PSL-matched, so that the exception for not prompting before
273 // saving PSL-matched credentials should no longer apply.
274 TEST_F(PasswordFormManagerTest,
275 OverriddenPSLMatchedCredentialsNotMarkedAsPSLMatched) {
276 PasswordFormManager manager(NULL, client(), NULL, *observed_form(), false);
278 // The suggestion needs to be PSL-matched.
279 saved_match()->original_signon_realm = "www.example.org";
280 SimulateMatchingPhase(&manager, RESULT_MATCH_FOUND);
282 // User modifies the suggested password and submits the form.
283 PasswordForm credentials(*observed_form());
284 credentials.username_value = saved_match()->username_value;
285 credentials.password_value =
286 saved_match()->password_value + ASCIIToUTF16("modify");
287 manager.ProvisionallySave(
288 credentials, PasswordFormManager::IGNORE_OTHER_POSSIBLE_USERNAMES);
290 EXPECT_TRUE(manager.IsNewLogin());
291 EXPECT_FALSE(manager.IsPendingCredentialsPublicSuffixMatch());
294 TEST_F(PasswordFormManagerTest, TestNewLoginFromNewPasswordElement) {
295 // Add a new password field to the test form. The PasswordFormManager should
296 // save the password from this field, instead of the current password field.
297 observed_form()->new_password_element = ASCIIToUTF16("NewPasswd");
299 PasswordFormManager manager(NULL, client(), NULL, *observed_form(), false);
300 SimulateMatchingPhase(&manager, RESULT_NO_MATCH);
302 // User enters current and new credentials to the observed form.
303 PasswordForm credentials(*observed_form());
304 credentials.username_value = saved_match()->username_value;
305 credentials.password_value = saved_match()->password_value;
306 credentials.new_password_value = ASCIIToUTF16("newpassword");
307 credentials.preferred = true;
308 manager.ProvisionallySave(
309 credentials, PasswordFormManager::IGNORE_OTHER_POSSIBLE_USERNAMES);
311 // Successful login. The PasswordManager would instruct PasswordFormManager
312 // to save, which should know this is a new login.
313 EXPECT_TRUE(manager.IsNewLogin());
314 EXPECT_EQ(credentials.origin, GetPendingCredentials(&manager)->origin);
315 EXPECT_EQ(credentials.signon_realm,
316 GetPendingCredentials(&manager)->signon_realm);
317 EXPECT_EQ(credentials.action, GetPendingCredentials(&manager)->action);
318 EXPECT_TRUE(GetPendingCredentials(&manager)->preferred);
319 EXPECT_EQ(credentials.username_value,
320 GetPendingCredentials(&manager)->username_value);
322 // By this point, the PasswordFormManager should have promoted the new
323 // password value to be the current password, and should have wiped the
324 // password element names: they are likely going to be different on a login
325 // form, so it is not worth remembering them.
326 EXPECT_EQ(credentials.new_password_value,
327 GetPendingCredentials(&manager)->password_value);
328 EXPECT_TRUE(GetPendingCredentials(&manager)->password_element.empty());
329 EXPECT_TRUE(GetPendingCredentials(&manager)->new_password_element.empty());
330 EXPECT_TRUE(GetPendingCredentials(&manager)->new_password_value.empty());
333 TEST_F(PasswordFormManagerTest, TestUpdatePassword) {
334 // Create a PasswordFormManager with observed_form, as if we just
335 // saw this form and need to find matching logins.
336 PasswordFormManager manager(NULL, client(), NULL, *observed_form(), false);
338 SimulateMatchingPhase(&manager, RESULT_MATCH_FOUND);
340 // User submits credentials for the observed form using a username previously
341 // stored, but a new password. Note that the observed form may have different
342 // origin URL (as it does in this case) than the saved_match, but we want to
343 // make sure the updated password is reflected in saved_match, because that is
344 // what we autofilled.
345 base::string16 new_pass = ASCIIToUTF16("test2");
346 PasswordForm credentials = *observed_form();
347 credentials.username_value = saved_match()->username_value;
348 credentials.password_value = new_pass;
349 credentials.preferred = true;
350 manager.ProvisionallySave(
351 credentials, PasswordFormManager::IGNORE_OTHER_POSSIBLE_USERNAMES);
353 // Successful login. The PasswordManager would instruct PasswordFormManager
354 // to save, and since this is an update, it should know not to save as a new
356 EXPECT_FALSE(manager.IsNewLogin());
358 // Make sure the credentials that would be submitted on successful login
359 // are going to match the stored entry in the db. (This verifies correct
360 // behaviour for bug 1074420).
361 EXPECT_EQ(GetPendingCredentials(&manager)->origin.spec(),
362 saved_match()->origin.spec());
363 EXPECT_EQ(GetPendingCredentials(&manager)->signon_realm,
364 saved_match()->signon_realm);
365 EXPECT_TRUE(GetPendingCredentials(&manager)->preferred);
366 EXPECT_EQ(new_pass, GetPendingCredentials(&manager)->password_value);
369 TEST_F(PasswordFormManagerTest, TestUpdatePasswordFromNewPasswordElement) {
370 // Add a new password field to the test form. The PasswordFormManager should
371 // save the password from this field, instead of the current password field.
372 observed_form()->new_password_element = ASCIIToUTF16("NewPasswd");
374 // Given that |observed_form| was most likely a change password form, it
375 // should not serve as a source for updating meta-information stored with the
376 // old credentials, such as element names, as they are likely going to be
377 // different between change password and login forms. To test this in depth,
378 // forcibly wipe |submit_element|, which should normally trigger updating this
379 // field from |observed_form| in the UpdateLogin() step as a special case. We
380 // will verify in the end that this did not happen.
381 saved_match()->submit_element.clear();
383 InitializeMockStore();
384 TestPasswordManagerClient client_with_store(mock_store());
385 PasswordFormManager manager(NULL,
387 client_with_store.GetDriver(),
390 EXPECT_CALL(*client_with_store.GetMockDriver(), IsOffTheRecord())
391 .WillRepeatedly(Return(false));
392 SimulateMatchingPhase(&manager, RESULT_MATCH_FOUND);
394 // User submits current and new credentials to the observed form.
395 PasswordForm credentials(*observed_form());
396 credentials.username_value = saved_match()->username_value;
397 credentials.password_value = saved_match()->password_value;
398 credentials.new_password_value = ASCIIToUTF16("test2");
399 credentials.preferred = true;
400 manager.ProvisionallySave(
401 credentials, PasswordFormManager::IGNORE_OTHER_POSSIBLE_USERNAMES);
403 // Successful login. The PasswordManager would instruct PasswordFormManager
404 // to save, and since this is an update, it should know not to save as a new
406 EXPECT_FALSE(manager.IsNewLogin());
408 // By now, the PasswordFormManager should have promoted the new password value
409 // already to be the current password, and should no longer maintain any info
410 // about the new password.
411 EXPECT_EQ(credentials.new_password_value,
412 GetPendingCredentials(&manager)->password_value);
413 EXPECT_TRUE(GetPendingCredentials(&manager)->new_password_element.empty());
414 EXPECT_TRUE(GetPendingCredentials(&manager)->new_password_value.empty());
416 // Trigger saving to exercise some special case handling in UpdateLogin().
417 PasswordForm new_credentials;
418 EXPECT_CALL(*mock_store(), UpdateLogin(_))
419 .WillOnce(testing::SaveArg<0>(&new_credentials));
421 Mock::VerifyAndClearExpectations(mock_store());
423 // No meta-information should be updated, only the password.
424 EXPECT_EQ(credentials.new_password_value, new_credentials.password_value);
425 EXPECT_EQ(saved_match()->username_element, new_credentials.username_element);
426 EXPECT_EQ(saved_match()->password_element, new_credentials.password_element);
427 EXPECT_EQ(saved_match()->submit_element, new_credentials.submit_element);
430 TEST_F(PasswordFormManagerTest, TestIgnoreResult) {
431 PasswordFormManager manager(NULL, client(), NULL, *observed_form(), false);
433 // Make sure we don't match a PasswordForm if it was originally saved on
434 // an SSL-valid page and we are now on a page with invalid certificate.
435 saved_match()->ssl_valid = true;
436 EXPECT_TRUE(IgnoredResult(&manager, saved_match()));
438 saved_match()->ssl_valid = false;
439 // Different paths for action / origin are okay.
440 saved_match()->action = GURL("http://www.google.com/b/Login");
441 saved_match()->origin = GURL("http://www.google.com/foo");
442 EXPECT_FALSE(IgnoredResult(&manager, saved_match()));
444 // Results should be ignored if the client requests it.
445 client()->SetFormToFilter(*saved_match());
446 EXPECT_TRUE(IgnoredResult(&manager, saved_match()));
449 TEST_F(PasswordFormManagerTest, TestEmptyAction) {
450 PasswordFormManager manager(NULL, client(), NULL, *observed_form(), false);
452 saved_match()->action = GURL();
453 SimulateMatchingPhase(&manager, RESULT_MATCH_FOUND);
454 // User logs in with the autofilled username / password from saved_match.
455 PasswordForm login = *observed_form();
456 login.username_value = saved_match()->username_value;
457 login.password_value = saved_match()->password_value;
458 manager.ProvisionallySave(
459 login, PasswordFormManager::IGNORE_OTHER_POSSIBLE_USERNAMES);
460 EXPECT_FALSE(manager.IsNewLogin());
461 // We bless our saved PasswordForm entry with the action URL of the
463 EXPECT_EQ(observed_form()->action, GetPendingCredentials(&manager)->action);
466 TEST_F(PasswordFormManagerTest, TestUpdateAction) {
467 PasswordFormManager manager(NULL, client(), NULL, *observed_form(), false);
469 SimulateMatchingPhase(&manager, RESULT_MATCH_FOUND);
470 // User logs in with the autofilled username / password from saved_match.
471 PasswordForm login = *observed_form();
472 login.username_value = saved_match()->username_value;
473 login.password_value = saved_match()->password_value;
475 manager.ProvisionallySave(
476 login, PasswordFormManager::IGNORE_OTHER_POSSIBLE_USERNAMES);
477 EXPECT_FALSE(manager.IsNewLogin());
478 // The observed action URL is different from the previously saved one, and
479 // is the same as the one that would be submitted on successful login.
480 EXPECT_NE(observed_form()->action, saved_match()->action);
481 EXPECT_EQ(observed_form()->action, GetPendingCredentials(&manager)->action);
484 TEST_F(PasswordFormManagerTest, TestDynamicAction) {
485 PasswordFormManager manager(NULL, client(), NULL, *observed_form(), false);
487 SimulateMatchingPhase(&manager, RESULT_NO_MATCH);
488 PasswordForm login(*observed_form());
489 // The submitted action URL is different from the one observed on page load.
490 GURL new_action = GURL("http://www.google.com/new_action");
491 login.action = new_action;
493 manager.ProvisionallySave(
494 login, PasswordFormManager::IGNORE_OTHER_POSSIBLE_USERNAMES);
495 EXPECT_TRUE(manager.IsNewLogin());
496 // Check that the provisionally saved action URL is the same as the submitted
497 // action URL, not the one observed on page load.
498 EXPECT_EQ(new_action, GetPendingCredentials(&manager)->action);
501 TEST_F(PasswordFormManagerTest, TestAlternateUsername) {
502 // Need a MessageLoop for callbacks.
503 base::MessageLoop message_loop;
504 scoped_refptr<TestPasswordStore> password_store = new TestPasswordStore;
505 CHECK(password_store->Init(syncer::SyncableService::StartSyncFlare(), ""));
507 TestPasswordManagerClient client_with_store(password_store.get());
508 TestPasswordManager password_manager(&client_with_store);
509 PasswordFormManager manager(&password_manager,
511 client_with_store.GetDriver(),
514 EXPECT_CALL(*client_with_store.GetMockDriver(),
515 AllowPasswordGenerationForForm(_)).Times(1);
516 EXPECT_CALL(*client_with_store.GetMockDriver(), IsOffTheRecord())
517 .WillRepeatedly(Return(false));
519 password_store->AddLogin(*saved_match());
520 manager.FetchMatchingLoginsFromPasswordStore(PasswordStore::ALLOW_PROMPT);
521 RunAllPendingTasks();
523 // The saved match has the right username already.
524 PasswordForm login(*observed_form());
525 login.username_value = saved_match()->username_value;
526 login.password_value = saved_match()->password_value;
527 login.preferred = true;
528 manager.ProvisionallySave(
529 login, PasswordFormManager::ALLOW_OTHER_POSSIBLE_USERNAMES);
531 EXPECT_FALSE(manager.IsNewLogin());
533 RunAllPendingTasks();
535 // Should be only one password stored, and should not have
536 // |other_possible_usernames| set anymore.
537 TestPasswordStore::PasswordMap passwords = password_store->stored_passwords();
538 EXPECT_EQ(1U, passwords.size());
539 ASSERT_EQ(1U, passwords[saved_match()->signon_realm].size());
540 EXPECT_EQ(saved_match()->username_value,
541 passwords[saved_match()->signon_realm][0].username_value);
543 passwords[saved_match()->signon_realm][0]
544 .other_possible_usernames.size());
546 // This time use an alternate username
547 PasswordFormManager manager_alt(&password_manager,
549 client_with_store.GetDriver(),
552 EXPECT_CALL(*client_with_store.GetMockDriver(),
553 AllowPasswordGenerationForForm(_)).Times(1);
554 password_store->Clear();
555 password_store->AddLogin(*saved_match());
556 manager_alt.FetchMatchingLoginsFromPasswordStore(PasswordStore::ALLOW_PROMPT);
557 RunAllPendingTasks();
559 base::string16 new_username = saved_match()->other_possible_usernames[0];
560 login.username_value = new_username;
561 manager_alt.ProvisionallySave(
562 login, PasswordFormManager::ALLOW_OTHER_POSSIBLE_USERNAMES);
564 EXPECT_FALSE(manager_alt.IsNewLogin());
566 RunAllPendingTasks();
568 // |other_possible_usernames| should also be empty, but username_value should
569 // be changed to match |new_username|
570 passwords = password_store->stored_passwords();
571 EXPECT_EQ(1U, passwords.size());
572 ASSERT_EQ(1U, passwords[saved_match()->signon_realm].size());
573 EXPECT_EQ(new_username,
574 passwords[saved_match()->signon_realm][0].username_value);
576 passwords[saved_match()->signon_realm][0]
577 .other_possible_usernames.size());
578 password_store->Shutdown();
581 TEST_F(PasswordFormManagerTest, TestValidForms) {
582 // User submits credentials for the observed form.
583 PasswordForm credentials = *observed_form();
584 credentials.scheme = PasswordForm::SCHEME_HTML;
585 credentials.username_value = saved_match()->username_value;
586 credentials.password_value = saved_match()->password_value;
588 // An alternate version of the form that also has a new_password_element.
589 PasswordForm new_credentials(*observed_form());
590 new_credentials.new_password_element = ASCIIToUTF16("NewPasswd");
591 new_credentials.new_password_value = ASCIIToUTF16("test1new");
593 // Form with both username_element and password_element.
594 PasswordFormManager manager1(NULL, NULL, NULL, credentials, false);
595 SimulateMatchingPhase(&manager1, RESULT_NO_MATCH);
596 EXPECT_TRUE(manager1.HasValidPasswordForm());
598 // Form with username_element, password_element, and new_password_element.
599 PasswordFormManager manager2(NULL, NULL, NULL, new_credentials, false);
600 SimulateMatchingPhase(&manager2, RESULT_NO_MATCH);
601 EXPECT_TRUE(manager2.HasValidPasswordForm());
603 // Form with username_element and only new_password_element.
604 new_credentials.password_element.clear();
605 PasswordFormManager manager3(NULL, NULL, NULL, new_credentials, false);
606 SimulateMatchingPhase(&manager3, RESULT_NO_MATCH);
607 EXPECT_TRUE(manager3.HasValidPasswordForm());
609 // Form without a username_element but with a password_element.
610 credentials.username_element.clear();
611 PasswordFormManager manager4(NULL, NULL, NULL, credentials, false);
612 SimulateMatchingPhase(&manager4, RESULT_NO_MATCH);
613 EXPECT_FALSE(manager4.HasValidPasswordForm());
615 // Form without a username_element but with a new_password_element.
616 new_credentials.username_element.clear();
617 PasswordFormManager manager5(NULL, NULL, NULL, new_credentials, false);
618 SimulateMatchingPhase(&manager5, RESULT_NO_MATCH);
619 EXPECT_FALSE(manager5.HasValidPasswordForm());
621 // Form without a password_element but with a username_element.
622 credentials.username_element = saved_match()->username_element;
623 credentials.password_element.clear();
624 PasswordFormManager manager6(NULL, NULL, NULL, credentials, false);
625 SimulateMatchingPhase(&manager6, RESULT_NO_MATCH);
626 EXPECT_FALSE(manager6.HasValidPasswordForm());
628 // Form with neither a password_element nor a username_element.
629 credentials.username_element.clear();
630 credentials.password_element.clear();
631 PasswordFormManager manager7(NULL, NULL, NULL, credentials, false);
632 SimulateMatchingPhase(&manager7, RESULT_NO_MATCH);
633 EXPECT_FALSE(manager7.HasValidPasswordForm());
636 TEST_F(PasswordFormManagerTest, TestValidFormsBasic) {
637 // User submits credentials for the observed form.
638 PasswordForm credentials = *observed_form();
639 credentials.scheme = PasswordForm::SCHEME_BASIC;
640 credentials.username_value = saved_match()->username_value;
641 credentials.password_value = saved_match()->password_value;
643 // Form with both username_element and password_element.
644 PasswordFormManager manager1(NULL, NULL, NULL, credentials, false);
645 SimulateMatchingPhase(&manager1, RESULT_NO_MATCH);
646 EXPECT_TRUE(manager1.HasValidPasswordForm());
648 // Form without a username_element but with a password_element.
649 credentials.username_element.clear();
650 PasswordFormManager manager2(NULL, NULL, NULL, credentials, false);
651 SimulateMatchingPhase(&manager2, RESULT_NO_MATCH);
652 EXPECT_TRUE(manager2.HasValidPasswordForm());
654 // Form without a password_element but with a username_element.
655 credentials.username_element = saved_match()->username_element;
656 credentials.password_element.clear();
657 PasswordFormManager manager3(NULL, NULL, NULL, credentials, false);
658 SimulateMatchingPhase(&manager3, RESULT_NO_MATCH);
659 EXPECT_TRUE(manager3.HasValidPasswordForm());
661 // Form with neither a password_element nor a username_element.
662 credentials.username_element.clear();
663 credentials.password_element.clear();
664 PasswordFormManager manager4(NULL, NULL, NULL, credentials, false);
665 SimulateMatchingPhase(&manager4, RESULT_NO_MATCH);
666 EXPECT_TRUE(manager4.HasValidPasswordForm());
669 TEST_F(PasswordFormManagerTest, TestSendNotBlacklistedMessage) {
670 base::MessageLoop message_loop;
672 TestPasswordManager password_manager(client());
673 PasswordFormManager manager_no_creds(&password_manager,
675 client()->GetDriver(),
679 // First time sign-up attempt. Password store does not contain matching
680 // credentials. AllowPasswordGenerationForForm should be called to send the
681 // "not blacklisted" message.
682 EXPECT_CALL(*(client()->GetMockDriver()), AllowPasswordGenerationForForm(_))
684 SimulateFetchMatchingLoginsFromPasswordStore(&manager_no_creds);
685 std::vector<PasswordForm*> result;
686 SimulateResponseFromPasswordStore(&manager_no_creds, result);
687 Mock::VerifyAndClearExpectations(client()->GetMockDriver());
689 // Signing up on a previously visited site. Credentials are found in the
690 // password store, and are not blacklisted. AllowPasswordGenerationForForm
691 // should be called to send the "not blacklisted" message.
692 PasswordFormManager manager_creds(&password_manager,
694 client()->GetDriver(),
697 EXPECT_CALL(*(client()->GetMockDriver()), AllowPasswordGenerationForForm(_))
699 EXPECT_CALL(*(client()->GetMockDriver()), IsOffTheRecord())
700 .WillRepeatedly(Return(false));
701 SimulateFetchMatchingLoginsFromPasswordStore(&manager_creds);
702 // We need add heap allocated objects to result.
703 result.push_back(CreateSavedMatch(false));
704 SimulateResponseFromPasswordStore(&manager_creds, result);
705 Mock::VerifyAndClearExpectations(client()->GetMockDriver());
707 // Signing up on a previously visited site. Credentials are found in the
708 // password store, but they are blacklisted. AllowPasswordGenerationForForm
709 // should not be called and no "not blacklisted" message sent.
710 PasswordFormManager manager_blacklisted(&password_manager,
712 client()->GetDriver(),
715 EXPECT_CALL(*(client()->GetMockDriver()), AllowPasswordGenerationForForm(_))
717 SimulateFetchMatchingLoginsFromPasswordStore(&manager_blacklisted);
719 result.push_back(CreateSavedMatch(true));
720 SimulateResponseFromPasswordStore(&manager_blacklisted, result);
721 Mock::VerifyAndClearExpectations(client()->GetMockDriver());
724 TEST_F(PasswordFormManagerTest, TestForceInclusionOfGeneratedPasswords) {
725 base::MessageLoop message_loop;
727 // Simulate having two matches for this origin, one of which was from a form
728 // with different HTML tags for elements. Because of scoring differences,
729 // only the first form will be sent to Autofill().
730 TestPasswordManager password_manager(client());
731 PasswordFormManager manager_match(&password_manager,
733 client()->GetDriver(),
736 EXPECT_CALL(*(client()->GetMockDriver()), AllowPasswordGenerationForForm(_))
738 EXPECT_CALL(*(client()->GetMockDriver()), IsOffTheRecord())
739 .WillRepeatedly(Return(false));
741 std::vector<PasswordForm*> results;
742 results.push_back(CreateSavedMatch(false));
743 results.push_back(CreateSavedMatch(false));
744 results[1]->username_value = ASCIIToUTF16("other@gmail.com");
745 results[1]->password_element = ASCIIToUTF16("signup_password");
746 results[1]->username_element = ASCIIToUTF16("signup_username");
747 SimulateFetchMatchingLoginsFromPasswordStore(&manager_match);
748 SimulateResponseFromPasswordStore(&manager_match, results);
749 EXPECT_EQ(1u, password_manager.GetLatestBestMatches().size());
752 // Same thing, except this time the credentials that don't match quite as
753 // well are generated. They should now be sent to Autofill().
754 PasswordFormManager manager_no_match(&password_manager,
756 client()->GetDriver(),
759 EXPECT_CALL(*(client()->GetMockDriver()), AllowPasswordGenerationForForm(_))
762 results.push_back(CreateSavedMatch(false));
763 results.push_back(CreateSavedMatch(false));
764 results[1]->username_value = ASCIIToUTF16("other@gmail.com");
765 results[1]->password_element = ASCIIToUTF16("signup_password");
766 results[1]->username_element = ASCIIToUTF16("signup_username");
767 results[1]->type = PasswordForm::TYPE_GENERATED;
768 SimulateFetchMatchingLoginsFromPasswordStore(&manager_no_match);
769 SimulateResponseFromPasswordStore(&manager_no_match, results);
770 EXPECT_EQ(2u, password_manager.GetLatestBestMatches().size());
773 TEST_F(PasswordFormManagerTest, TestSanitizePossibleUsernames) {
774 PasswordFormManager manager(NULL, client(), NULL, *observed_form(), false);
775 PasswordForm credentials(*observed_form());
776 credentials.other_possible_usernames.push_back(ASCIIToUTF16("543-43-1234"));
777 credentials.other_possible_usernames.push_back(
778 ASCIIToUTF16("378282246310005"));
779 credentials.other_possible_usernames.push_back(
780 ASCIIToUTF16("other username"));
781 credentials.username_value = ASCIIToUTF16("test@gmail.com");
783 SanitizePossibleUsernames(&manager, &credentials);
785 // Possible credit card number and SSN are stripped.
786 std::vector<base::string16> expected;
787 expected.push_back(ASCIIToUTF16("other username"));
788 EXPECT_THAT(credentials.other_possible_usernames, Eq(expected));
790 credentials.other_possible_usernames.clear();
791 credentials.other_possible_usernames.push_back(ASCIIToUTF16("511-32-9830"));
792 credentials.other_possible_usernames.push_back(ASCIIToUTF16("duplicate"));
793 credentials.other_possible_usernames.push_back(ASCIIToUTF16("duplicate"));
794 credentials.other_possible_usernames.push_back(ASCIIToUTF16("random"));
795 credentials.other_possible_usernames.push_back(
796 ASCIIToUTF16("test@gmail.com"));
798 SanitizePossibleUsernames(&manager, &credentials);
800 // SSN, duplicate in |other_possible_usernames| and duplicate of
801 // |username_value| all removed.
803 expected.push_back(ASCIIToUTF16("duplicate"));
804 expected.push_back(ASCIIToUTF16("random"));
805 EXPECT_THAT(credentials.other_possible_usernames, Eq(expected));
808 TEST_F(PasswordFormManagerTest, TestUpdateIncompleteCredentials) {
809 InitializeMockStore();
811 // We've found this form on a website:
812 PasswordForm encountered_form;
813 encountered_form.origin = GURL("http://accounts.google.com/LoginAuth");
814 encountered_form.signon_realm = "http://accounts.google.com/";
815 encountered_form.action = GURL("http://accounts.google.com/Login");
816 encountered_form.username_element = ASCIIToUTF16("Email");
817 encountered_form.password_element = ASCIIToUTF16("Passwd");
818 encountered_form.submit_element = ASCIIToUTF16("signIn");
820 TestPasswordManagerClient client_with_store(mock_store());
821 EXPECT_CALL(*(client_with_store.GetMockDriver()), IsOffTheRecord())
822 .WillRepeatedly(Return(false));
823 EXPECT_CALL(*(client_with_store.GetMockDriver()),
824 AllowPasswordGenerationForForm(_));
826 TestPasswordManager manager(&client_with_store);
827 PasswordFormManager form_manager(&manager,
829 client_with_store.GetMockDriver(),
833 const PasswordStore::AuthorizationPromptPolicy auth_policy =
834 PasswordStore::DISALLOW_PROMPT;
835 EXPECT_CALL(*mock_store(),
836 GetLogins(encountered_form, auth_policy, &form_manager));
837 form_manager.FetchMatchingLoginsFromPasswordStore(auth_policy);
839 // Password store only has these incomplete credentials.
840 PasswordForm* incomplete_form = new PasswordForm();
841 incomplete_form->origin = GURL("http://accounts.google.com/LoginAuth");
842 incomplete_form->signon_realm = "http://accounts.google.com/";
843 incomplete_form->password_value = ASCIIToUTF16("my_password");
844 incomplete_form->username_value = ASCIIToUTF16("my_username");
845 incomplete_form->preferred = true;
846 incomplete_form->ssl_valid = false;
847 incomplete_form->scheme = PasswordForm::SCHEME_HTML;
849 // We expect to see this form eventually sent to the Password store. It
850 // has password/username values from the store and 'username_element',
851 // 'password_element', 'submit_element' and 'action' fields copied from
852 // the encountered form.
853 PasswordForm complete_form(*incomplete_form);
854 complete_form.action = encountered_form.action;
855 complete_form.password_element = encountered_form.password_element;
856 complete_form.username_element = encountered_form.username_element;
857 complete_form.submit_element = encountered_form.submit_element;
859 PasswordForm obsolete_form(*incomplete_form);
860 obsolete_form.action = encountered_form.action;
862 // Feed the incomplete credentials to the manager.
863 std::vector<PasswordForm*> results;
864 results.push_back(incomplete_form); // Takes ownership.
865 form_manager.OnRequestDone(results);
867 form_manager.ProvisionallySave(
868 complete_form, PasswordFormManager::IGNORE_OTHER_POSSIBLE_USERNAMES);
869 // By now that form has been used once.
870 complete_form.times_used = 1;
871 obsolete_form.times_used = 1;
873 // Check that PasswordStore receives an update request with the complete form.
874 EXPECT_CALL(*mock_store(), RemoveLogin(obsolete_form));
875 EXPECT_CALL(*mock_store(), AddLogin(complete_form));
879 TEST_F(PasswordFormManagerTest, TestScoringPublicSuffixMatch) {
880 base::MessageLoop message_loop;
882 EXPECT_CALL(*(client()->GetMockDriver()), IsOffTheRecord())
883 .WillRepeatedly(Return(false));
884 EXPECT_CALL(*(client()->GetMockDriver()), AllowPasswordGenerationForForm(_));
886 TestPasswordManager password_manager(client());
887 PasswordFormManager manager(&password_manager,
889 client()->GetMockDriver(),
893 // Simulate having two matches for this form, first comes from different
894 // signon realm, but reports the same origin and action as matched form.
895 // Second candidate has the same signon realm as the form, but has a different
896 // origin and action. Public suffix match is the most important criterion so
897 // the second candidate should be selected.
898 std::vector<PasswordForm*> results;
899 results.push_back(CreateSavedMatch(false));
900 results.push_back(CreateSavedMatch(false));
901 results[0]->original_signon_realm = "http://accounts2.google.com";
902 results[1]->origin = GURL("http://accounts.google.com/a/ServiceLoginAuth2");
903 results[1]->action = GURL("http://accounts.google.com/a/ServiceLogin2");
904 SimulateFetchMatchingLoginsFromPasswordStore(&manager);
905 SimulateResponseFromPasswordStore(&manager, results);
906 EXPECT_EQ(1u, password_manager.GetLatestBestMatches().size());
907 EXPECT_EQ("", password_manager.GetLatestBestMatches().begin()
908 ->second->original_signon_realm);
911 TEST_F(PasswordFormManagerTest, InvalidActionURLsDoNotMatch) {
912 PasswordFormManager manager(NULL, client(), NULL, *observed_form(), false);
914 PasswordForm invalid_action_form(*observed_form());
915 invalid_action_form.action = GURL("http://");
916 ASSERT_FALSE(invalid_action_form.action.is_valid());
917 ASSERT_FALSE(invalid_action_form.action.is_empty());
918 // Non-empty invalid action URLs should not match other actions.
919 // First when the compared form has an invalid URL:
921 manager.DoesManage(invalid_action_form) &
922 PasswordFormManager::RESULT_ACTION_MATCH);
923 // Then when the observed form has an invalid URL:
924 PasswordForm valid_action_form(*observed_form());
925 PasswordFormManager invalid_manager(
926 NULL, client(), NULL, invalid_action_form, false);
928 invalid_manager.DoesManage(valid_action_form) &
929 PasswordFormManager::RESULT_ACTION_MATCH);
932 TEST_F(PasswordFormManagerTest, EmptyActionURLsDoNotMatchNonEmpty) {
933 PasswordFormManager manager(NULL, client(), NULL, *observed_form(), false);
935 PasswordForm empty_action_form(*observed_form());
936 empty_action_form.action = GURL();
937 ASSERT_FALSE(empty_action_form.action.is_valid());
938 ASSERT_TRUE(empty_action_form.action.is_empty());
939 // First when the compared form has an empty URL:
941 manager.DoesManage(empty_action_form) &
942 PasswordFormManager::RESULT_ACTION_MATCH);
943 // Then when the observed form has an empty URL:
944 PasswordForm valid_action_form(*observed_form());
945 PasswordFormManager empty_action_manager(
946 NULL, client(), NULL, empty_action_form, false);
948 empty_action_manager.DoesManage(valid_action_form) &
949 PasswordFormManager::RESULT_ACTION_MATCH);
952 TEST_F(PasswordFormManagerTest, NonHTMLFormsDoNotMatchHTMLForms) {
953 PasswordFormManager manager(NULL, client(), NULL, *observed_form(), false);
955 ASSERT_EQ(PasswordForm::SCHEME_HTML, observed_form()->scheme);
956 PasswordForm non_html_form(*observed_form());
957 non_html_form.scheme = PasswordForm::SCHEME_DIGEST;
959 manager.DoesManage(non_html_form) &
960 PasswordFormManager::RESULT_MANDATORY_ATTRIBUTES_MATCH);
962 // The other way round: observing a non-HTML form, don't match a HTML form.
963 PasswordForm html_form(*observed_form());
964 PasswordFormManager non_html_manager(
965 NULL, client(), NULL, non_html_form, false);
967 non_html_manager.DoesManage(html_form) &
968 PasswordFormManager::RESULT_MANDATORY_ATTRIBUTES_MATCH);
971 TEST_F(PasswordFormManagerTest, OriginCheck_HostsMatchExactly) {
972 // Host part of origins must match exactly, not just by prefix.
973 PasswordFormManager manager(NULL, client(), NULL, *observed_form(), false);
975 PasswordForm form_longer_host(*observed_form());
976 form_longer_host.origin = GURL("http://accounts.google.com.au/a/LoginAuth");
977 // Check that accounts.google.com does not match accounts.google.com.au.
979 manager.DoesManage(form_longer_host) &
980 PasswordFormManager::RESULT_MANDATORY_ATTRIBUTES_MATCH);
983 TEST_F(PasswordFormManagerTest, OriginCheck_MoreSecureSchemePathsMatchPrefix) {
984 // If the URL scheme of the observed form is HTTP, and the compared form is
985 // HTTPS, then the compared form can extend the path.
986 PasswordFormManager manager(NULL, client(), NULL, *observed_form(), false);
988 PasswordForm form_longer_path(*observed_form());
989 form_longer_path.origin = GURL("https://accounts.google.com/a/LoginAuth/sec");
991 manager.DoesManage(form_longer_path) &
992 PasswordFormManager::RESULT_MANDATORY_ATTRIBUTES_MATCH);
995 TEST_F(PasswordFormManagerTest,
996 OriginCheck_NotMoreSecureSchemePathsMatchExactly) {
997 // If the origin URL scheme of the compared form is not more secure than that
998 // of the observed form, then the paths must match exactly.
999 PasswordFormManager manager(NULL, client(), NULL, *observed_form(), false);
1001 PasswordForm form_longer_path(*observed_form());
1002 form_longer_path.origin = GURL("http://accounts.google.com/a/LoginAuth/sec");
1003 // Check that /a/LoginAuth does not match /a/LoginAuth/more.
1005 manager.DoesManage(form_longer_path) &
1006 PasswordFormManager::RESULT_MANDATORY_ATTRIBUTES_MATCH);
1008 PasswordForm secure_observed_form(*observed_form());
1009 secure_observed_form.origin = GURL("https://accounts.google.com/a/LoginAuth");
1010 PasswordFormManager secure_manager(
1011 NULL, client(), NULL, secure_observed_form, true);
1012 // Also for HTTPS in the observed form, and HTTP in the compared form, an
1013 // exact path match is expected.
1015 secure_manager.DoesManage(form_longer_path) &
1016 PasswordFormManager::RESULT_MANDATORY_ATTRIBUTES_MATCH);
1017 // Not even upgrade to HTTPS in the compared form should help.
1018 form_longer_path.origin = GURL("https://accounts.google.com/a/LoginAuth/sec");
1020 secure_manager.DoesManage(form_longer_path) &
1021 PasswordFormManager::RESULT_MANDATORY_ATTRIBUTES_MATCH);
1024 TEST_F(PasswordFormManagerTest, CorrectlyUpdatePasswordsWithSameUsername) {
1025 // Need a MessageLoop for callbacks.
1026 base::MessageLoop message_loop;
1027 scoped_refptr<TestPasswordStore> password_store = new TestPasswordStore;
1028 CHECK(password_store->Init(syncer::SyncableService::StartSyncFlare(), ""));
1030 TestPasswordManagerClient client_with_store(password_store.get());
1031 TestPasswordManager password_manager(&client_with_store);
1032 EXPECT_CALL(*client_with_store.GetMockDriver(),
1033 AllowPasswordGenerationForForm(_)).Times(2);
1034 EXPECT_CALL(*client_with_store.GetMockDriver(), IsOffTheRecord())
1035 .WillRepeatedly(Return(false));
1037 // Add two credentials with the same username. Both should score the same
1038 // and be seen as candidates to autofill.
1039 PasswordForm first(*saved_match());
1040 first.action = observed_form()->action;
1041 first.password_value = ASCIIToUTF16("first");
1042 password_store->AddLogin(first);
1044 PasswordForm second(first);
1045 second.origin = GURL("http://accounts.google.com/a/AddLogin");
1046 second.password_value = ASCIIToUTF16("second");
1047 second.preferred = false;
1048 password_store->AddLogin(second);
1050 PasswordFormManager storing_manager(&password_manager,
1052 client_with_store.GetDriver(),
1055 storing_manager.FetchMatchingLoginsFromPasswordStore(
1056 PasswordStore::ALLOW_PROMPT);
1057 RunAllPendingTasks();
1059 // We always take the last credential with a particular username, regardless
1060 // of which ones are labeled preferred.
1061 EXPECT_EQ(ASCIIToUTF16("second"),
1062 storing_manager.preferred_match()->password_value);
1064 PasswordForm login(*observed_form());
1065 login.username_value = saved_match()->username_value;
1066 login.password_value = ASCIIToUTF16("third");
1067 login.preferred = true;
1068 storing_manager.ProvisionallySave(
1069 login, PasswordFormManager::IGNORE_OTHER_POSSIBLE_USERNAMES);
1071 EXPECT_FALSE(storing_manager.IsNewLogin());
1072 storing_manager.Save();
1073 RunAllPendingTasks();
1075 PasswordFormManager retrieving_manager(&password_manager,
1077 client_with_store.GetDriver(),
1081 retrieving_manager.FetchMatchingLoginsFromPasswordStore(
1082 PasswordStore::ALLOW_PROMPT);
1083 RunAllPendingTasks();
1085 // Make sure that the preferred match is updated appropriately.
1086 EXPECT_EQ(ASCIIToUTF16("third"),
1087 retrieving_manager.preferred_match()->password_value);
1088 password_store->Shutdown();
1091 } // namespace password_manager