password_form_manager_unittest.cc revision 116680a4aac90f2aa7413d9095a592090648e557
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 "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"
25
26using autofill::PasswordForm;
27using base::ASCIIToUTF16;
28using ::testing::_;
29using ::testing::Eq;
30using ::testing::Mock;
31using ::testing::Return;
32
33namespace autofill {
34class AutofillManager;
35}
36
37namespace password_manager {
38
39namespace {
40
41void RunAllPendingTasks() {
42  base::RunLoop run_loop;
43  base::MessageLoop::current()->PostTask(
44      FROM_HERE, base::MessageLoop::QuitWhenIdleClosure());
45  run_loop.Run();
46}
47
48class MockPasswordManagerDriver : public StubPasswordManagerDriver {
49 public:
50  MOCK_METHOD0(IsOffTheRecord, bool());
51  MOCK_METHOD1(AllowPasswordGenerationForForm,
52               void(const autofill::PasswordForm&));
53};
54
55class TestPasswordManagerClient : public StubPasswordManagerClient {
56 public:
57  explicit TestPasswordManagerClient(PasswordStore* password_store)
58      : password_store_(password_store) {
59    prefs_.registry()->RegisterBooleanPref(prefs::kPasswordManagerSavingEnabled,
60                                           true);
61  }
62
63  virtual void PromptUserToSavePassword(PasswordFormManager* form_to_save)
64      OVERRIDE {}
65  virtual PrefService* GetPrefs() OVERRIDE { return &prefs_; }
66  virtual PasswordStore* GetPasswordStore() OVERRIDE { return password_store_; }
67  virtual PasswordManagerDriver* GetDriver() OVERRIDE { return &driver_; }
68  virtual void AuthenticateAutofillAndFillForm(
69      scoped_ptr<autofill::PasswordFormFillData> fill_data) OVERRIDE {
70    driver_.FillPasswordForm(*fill_data.get());
71  }
72
73  MockPasswordManagerDriver* GetMockDriver() { return &driver_; }
74
75 private:
76  TestingPrefServiceSimple prefs_;
77  PasswordStore* password_store_;
78  MockPasswordManagerDriver driver_;
79};
80
81class TestPasswordManager : public PasswordManager {
82 public:
83  explicit TestPasswordManager(PasswordManagerClient* client)
84      : PasswordManager(client) {}
85
86  virtual void Autofill(const autofill::PasswordForm& form_for_autofill,
87                        const autofill::PasswordFormMap& best_matches,
88                        const autofill::PasswordForm& preferred_match,
89                        bool wait_for_username) const OVERRIDE {
90    best_matches_ = best_matches;
91  }
92
93  const autofill::PasswordFormMap& GetLatestBestMatches() {
94    return best_matches_;
95  }
96
97 private:
98  // Marked mutable to get around constness of Autofill().
99  mutable autofill::PasswordFormMap best_matches_;
100};
101
102}  // namespace
103
104class PasswordFormManagerTest : public testing::Test {
105 public:
106  PasswordFormManagerTest() : client_(NULL /*password_store*/) {}
107
108  virtual void SetUp() {
109    observed_form_.origin = GURL("http://accounts.google.com/a/LoginAuth");
110    observed_form_.action = GURL("http://accounts.google.com/a/Login");
111    observed_form_.username_element = ASCIIToUTF16("Email");
112    observed_form_.password_element = ASCIIToUTF16("Passwd");
113    observed_form_.submit_element = ASCIIToUTF16("signIn");
114    observed_form_.signon_realm = "http://accounts.google.com";
115
116    saved_match_ = observed_form_;
117    saved_match_.origin = GURL("http://accounts.google.com/a/ServiceLoginAuth");
118    saved_match_.action = GURL("http://accounts.google.com/a/ServiceLogin");
119    saved_match_.preferred = true;
120    saved_match_.username_value = ASCIIToUTF16("test@gmail.com");
121    saved_match_.password_value = ASCIIToUTF16("test1");
122    saved_match_.other_possible_usernames.push_back(
123        ASCIIToUTF16("test2@gmail.com"));
124  }
125
126  virtual void TearDown() {
127    if (mock_store_)
128      mock_store_->Shutdown();
129  }
130
131  void InitializeMockStore() {
132    if (!mock_store_) {
133      mock_store_ = new MockPasswordStore();
134      ASSERT_TRUE(mock_store_);
135    }
136  }
137
138  MockPasswordStore* mock_store() const { return mock_store_.get(); }
139
140  PasswordForm* GetPendingCredentials(PasswordFormManager* p) {
141    return &p->pending_credentials_;
142  }
143
144  void SimulateMatchingPhase(PasswordFormManager* p, bool find_match) {
145    // Roll up the state to mock out the matching phase.
146    p->state_ = PasswordFormManager::POST_MATCHING_PHASE;
147    if (!find_match)
148      return;
149
150    PasswordForm* match = new PasswordForm(saved_match_);
151    // Heap-allocated form is owned by p.
152    p->best_matches_[match->username_value] = match;
153    p->preferred_match_ = match;
154  }
155
156  void SimulateFetchMatchingLoginsFromPasswordStore(
157      PasswordFormManager* manager) {
158    // Just need to update the internal states.
159    manager->state_ = PasswordFormManager::MATCHING_PHASE;
160  }
161
162  void SimulateResponseFromPasswordStore(
163      PasswordFormManager* manager,
164      const std::vector<PasswordForm*>& result) {
165    // Simply call the callback method when request done. This will transfer
166    // the ownership of the objects in |result| to the |manager|.
167    manager->OnGetPasswordStoreResults(result);
168  }
169
170  void SanitizePossibleUsernames(PasswordFormManager* p, PasswordForm* form) {
171    p->SanitizePossibleUsernames(form);
172  }
173
174  bool IgnoredResult(PasswordFormManager* p, PasswordForm* form) {
175    return p->IgnoreResult(*form);
176  }
177
178  PasswordForm* observed_form() { return &observed_form_; }
179  PasswordForm* saved_match() { return &saved_match_; }
180  PasswordForm* CreateSavedMatch(bool blacklisted) {
181    // Owned by the caller of this method.
182    PasswordForm* match = new PasswordForm(saved_match_);
183    match->blacklisted_by_user = blacklisted;
184    return match;
185  }
186
187  TestPasswordManagerClient* client() { return &client_; }
188
189 private:
190  PasswordForm observed_form_;
191  PasswordForm saved_match_;
192  scoped_refptr<MockPasswordStore> mock_store_;
193  TestPasswordManagerClient client_;
194};
195
196TEST_F(PasswordFormManagerTest, TestNewLogin) {
197  PasswordFormManager manager(NULL, client(), NULL, *observed_form(), false);
198  SimulateMatchingPhase(&manager, false);
199
200  // User submits credentials for the observed form.
201  PasswordForm credentials = *observed_form();
202  credentials.username_value = saved_match()->username_value;
203  credentials.password_value = saved_match()->password_value;
204  credentials.preferred = true;
205  manager.ProvisionallySave(
206      credentials, PasswordFormManager::IGNORE_OTHER_POSSIBLE_USERNAMES);
207
208  // Successful login. The PasswordManager would instruct PasswordFormManager
209  // to save, which should know this is a new login.
210  EXPECT_TRUE(manager.IsNewLogin());
211  // Make sure the credentials that would be submitted on successful login
212  // are going to match the stored entry in the db.
213  EXPECT_EQ(observed_form()->origin.spec(),
214            GetPendingCredentials(&manager)->origin.spec());
215  EXPECT_EQ(observed_form()->signon_realm,
216            GetPendingCredentials(&manager)->signon_realm);
217  EXPECT_EQ(observed_form()->action, GetPendingCredentials(&manager)->action);
218  EXPECT_TRUE(GetPendingCredentials(&manager)->preferred);
219  EXPECT_EQ(saved_match()->password_value,
220            GetPendingCredentials(&manager)->password_value);
221  EXPECT_EQ(saved_match()->username_value,
222            GetPendingCredentials(&manager)->username_value);
223  EXPECT_TRUE(GetPendingCredentials(&manager)->new_password_element.empty());
224  EXPECT_TRUE(GetPendingCredentials(&manager)->new_password_value.empty());
225
226  // Now, suppose the user re-visits the site and wants to save an additional
227  // login for the site with a new username. In this case, the matching phase
228  // will yield the previously saved login.
229  SimulateMatchingPhase(&manager, true);
230  // Set up the new login.
231  base::string16 new_user = ASCIIToUTF16("newuser");
232  base::string16 new_pass = ASCIIToUTF16("newpass");
233  credentials.username_value = new_user;
234  credentials.password_value = new_pass;
235  manager.ProvisionallySave(
236      credentials, PasswordFormManager::IGNORE_OTHER_POSSIBLE_USERNAMES);
237
238  // Again, the PasswordFormManager should know this is still a new login.
239  EXPECT_TRUE(manager.IsNewLogin());
240  // And make sure everything squares up again.
241  EXPECT_EQ(observed_form()->origin.spec(),
242            GetPendingCredentials(&manager)->origin.spec());
243  EXPECT_EQ(observed_form()->signon_realm,
244            GetPendingCredentials(&manager)->signon_realm);
245  EXPECT_TRUE(GetPendingCredentials(&manager)->preferred);
246  EXPECT_EQ(new_pass, GetPendingCredentials(&manager)->password_value);
247  EXPECT_EQ(new_user, GetPendingCredentials(&manager)->username_value);
248  EXPECT_TRUE(GetPendingCredentials(&manager)->new_password_element.empty());
249  EXPECT_TRUE(GetPendingCredentials(&manager)->new_password_value.empty());
250}
251
252TEST_F(PasswordFormManagerTest, TestNewLoginFromNewPasswordElement) {
253  // Add a new password field to the test form. The PasswordFormManager should
254  // save the password from this field, instead of the current password field.
255  observed_form()->new_password_element = ASCIIToUTF16("NewPasswd");
256
257  PasswordFormManager manager(NULL, client(), NULL, *observed_form(), false);
258  SimulateMatchingPhase(&manager, false);
259
260  // User enters current and new credentials to the observed form.
261  PasswordForm credentials(*observed_form());
262  credentials.username_value = saved_match()->username_value;
263  credentials.password_value = saved_match()->password_value;
264  credentials.new_password_value = ASCIIToUTF16("newpassword");
265  credentials.preferred = true;
266  manager.ProvisionallySave(
267      credentials, PasswordFormManager::IGNORE_OTHER_POSSIBLE_USERNAMES);
268
269  // Successful login. The PasswordManager would instruct PasswordFormManager
270  // to save, which should know this is a new login.
271  EXPECT_TRUE(manager.IsNewLogin());
272  EXPECT_EQ(credentials.origin, GetPendingCredentials(&manager)->origin);
273  EXPECT_EQ(credentials.signon_realm,
274            GetPendingCredentials(&manager)->signon_realm);
275  EXPECT_EQ(credentials.action, GetPendingCredentials(&manager)->action);
276  EXPECT_TRUE(GetPendingCredentials(&manager)->preferred);
277  EXPECT_EQ(credentials.username_value,
278            GetPendingCredentials(&manager)->username_value);
279
280  // By this point, the PasswordFormManager should have promoted the new
281  // password value to be the current password, and should have wiped the
282  // password element names: they are likely going to be different on a login
283  // form, so it is not worth remembering them.
284  EXPECT_EQ(credentials.new_password_value,
285            GetPendingCredentials(&manager)->password_value);
286  EXPECT_TRUE(GetPendingCredentials(&manager)->password_element.empty());
287  EXPECT_TRUE(GetPendingCredentials(&manager)->new_password_element.empty());
288  EXPECT_TRUE(GetPendingCredentials(&manager)->new_password_value.empty());
289}
290
291TEST_F(PasswordFormManagerTest, TestUpdatePassword) {
292  // Create a PasswordFormManager with observed_form, as if we just
293  // saw this form and need to find matching logins.
294  PasswordFormManager manager(NULL, client(), NULL, *observed_form(), false);
295
296  SimulateMatchingPhase(&manager, true);
297
298  // User submits credentials for the observed form using a username previously
299  // stored, but a new password. Note that the observed form may have different
300  // origin URL (as it does in this case) than the saved_match, but we want to
301  // make sure the updated password is reflected in saved_match, because that is
302  // what we autofilled.
303  base::string16 new_pass = ASCIIToUTF16("test2");
304  PasswordForm credentials = *observed_form();
305  credentials.username_value = saved_match()->username_value;
306  credentials.password_value = new_pass;
307  credentials.preferred = true;
308  manager.ProvisionallySave(
309      credentials, PasswordFormManager::IGNORE_OTHER_POSSIBLE_USERNAMES);
310
311  // Successful login. The PasswordManager would instruct PasswordFormManager
312  // to save, and since this is an update, it should know not to save as a new
313  // login.
314  EXPECT_FALSE(manager.IsNewLogin());
315
316  // Make sure the credentials that would be submitted on successful login
317  // are going to match the stored entry in the db. (This verifies correct
318  // behaviour for bug 1074420).
319  EXPECT_EQ(GetPendingCredentials(&manager)->origin.spec(),
320            saved_match()->origin.spec());
321  EXPECT_EQ(GetPendingCredentials(&manager)->signon_realm,
322            saved_match()->signon_realm);
323  EXPECT_TRUE(GetPendingCredentials(&manager)->preferred);
324  EXPECT_EQ(new_pass, GetPendingCredentials(&manager)->password_value);
325}
326
327TEST_F(PasswordFormManagerTest, TestUpdatePasswordFromNewPasswordElement) {
328  // Add a new password field to the test form. The PasswordFormManager should
329  // save the password from this field, instead of the current password field.
330  observed_form()->new_password_element = ASCIIToUTF16("NewPasswd");
331
332  // Given that |observed_form| was most likely a change password form, it
333  // should not serve as a source for updating meta-information stored with the
334  // old credentials, such as element names, as they are likely going to be
335  // different between change password and login forms. To test this in depth,
336  // forcibly wipe |submit_element|, which should normally trigger updating this
337  // field from |observed_form| in the UpdateLogin() step as a special case. We
338  // will verify in the end that this did not happen.
339  saved_match()->submit_element.clear();
340
341  InitializeMockStore();
342  TestPasswordManagerClient client_with_store(mock_store());
343  PasswordFormManager manager(NULL,
344                              &client_with_store,
345                              client_with_store.GetDriver(),
346                              *observed_form(),
347                              false);
348  EXPECT_CALL(*client_with_store.GetMockDriver(), IsOffTheRecord())
349      .WillRepeatedly(Return(false));
350  SimulateMatchingPhase(&manager, true);
351
352  // User submits current and new credentials to the observed form.
353  PasswordForm credentials(*observed_form());
354  credentials.username_value = saved_match()->username_value;
355  credentials.password_value = saved_match()->password_value;
356  credentials.new_password_value = ASCIIToUTF16("test2");
357  credentials.preferred = true;
358  manager.ProvisionallySave(
359      credentials, PasswordFormManager::IGNORE_OTHER_POSSIBLE_USERNAMES);
360
361  // Successful login. The PasswordManager would instruct PasswordFormManager
362  // to save, and since this is an update, it should know not to save as a new
363  // login.
364  EXPECT_FALSE(manager.IsNewLogin());
365
366  // By now, the PasswordFormManager should have promoted the new password value
367  // already to be the current password, and should no longer maintain any info
368  // about the new password.
369  EXPECT_EQ(credentials.new_password_value,
370            GetPendingCredentials(&manager)->password_value);
371  EXPECT_TRUE(GetPendingCredentials(&manager)->new_password_element.empty());
372  EXPECT_TRUE(GetPendingCredentials(&manager)->new_password_value.empty());
373
374  // Trigger saving to exercise some special case handling in UpdateLogin().
375  PasswordForm new_credentials;
376  EXPECT_CALL(*mock_store(), UpdateLogin(_))
377      .WillOnce(testing::SaveArg<0>(&new_credentials));
378  manager.Save();
379  Mock::VerifyAndClearExpectations(mock_store());
380
381  // No meta-information should be updated, only the password.
382  EXPECT_EQ(credentials.new_password_value, new_credentials.password_value);
383  EXPECT_EQ(saved_match()->username_element, new_credentials.username_element);
384  EXPECT_EQ(saved_match()->password_element, new_credentials.password_element);
385  EXPECT_EQ(saved_match()->submit_element, new_credentials.submit_element);
386}
387
388TEST_F(PasswordFormManagerTest, TestIgnoreResult) {
389  PasswordFormManager manager(NULL, client(), NULL, *observed_form(), false);
390
391  // Make sure we don't match a PasswordForm if it was originally saved on
392  // an SSL-valid page and we are now on a page with invalid certificate.
393  saved_match()->ssl_valid = true;
394  EXPECT_TRUE(IgnoredResult(&manager, saved_match()));
395
396  saved_match()->ssl_valid = false;
397  // Different paths for action / origin are okay.
398  saved_match()->action = GURL("http://www.google.com/b/Login");
399  saved_match()->origin = GURL("http://www.google.com/foo");
400  EXPECT_FALSE(IgnoredResult(&manager, saved_match()));
401}
402
403TEST_F(PasswordFormManagerTest, TestEmptyAction) {
404  PasswordFormManager manager(NULL, client(), NULL, *observed_form(), false);
405
406  saved_match()->action = GURL();
407  SimulateMatchingPhase(&manager, true);
408  // User logs in with the autofilled username / password from saved_match.
409  PasswordForm login = *observed_form();
410  login.username_value = saved_match()->username_value;
411  login.password_value = saved_match()->password_value;
412  manager.ProvisionallySave(
413      login, PasswordFormManager::IGNORE_OTHER_POSSIBLE_USERNAMES);
414  EXPECT_FALSE(manager.IsNewLogin());
415  // We bless our saved PasswordForm entry with the action URL of the
416  // observed form.
417  EXPECT_EQ(observed_form()->action, GetPendingCredentials(&manager)->action);
418}
419
420TEST_F(PasswordFormManagerTest, TestUpdateAction) {
421  PasswordFormManager manager(NULL, client(), NULL, *observed_form(), false);
422
423  SimulateMatchingPhase(&manager, true);
424  // User logs in with the autofilled username / password from saved_match.
425  PasswordForm login = *observed_form();
426  login.username_value = saved_match()->username_value;
427  login.password_value = saved_match()->password_value;
428
429  manager.ProvisionallySave(
430      login, PasswordFormManager::IGNORE_OTHER_POSSIBLE_USERNAMES);
431  EXPECT_FALSE(manager.IsNewLogin());
432  // The observed action URL is different from the previously saved one, and
433  // is the same as the one that would be submitted on successful login.
434  EXPECT_NE(observed_form()->action, saved_match()->action);
435  EXPECT_EQ(observed_form()->action, GetPendingCredentials(&manager)->action);
436}
437
438TEST_F(PasswordFormManagerTest, TestDynamicAction) {
439  PasswordFormManager manager(NULL, client(), NULL, *observed_form(), false);
440
441  SimulateMatchingPhase(&manager, false);
442  PasswordForm login(*observed_form());
443  // The submitted action URL is different from the one observed on page load.
444  GURL new_action = GURL("http://www.google.com/new_action");
445  login.action = new_action;
446
447  manager.ProvisionallySave(
448      login, PasswordFormManager::IGNORE_OTHER_POSSIBLE_USERNAMES);
449  EXPECT_TRUE(manager.IsNewLogin());
450  // Check that the provisionally saved action URL is the same as the submitted
451  // action URL, not the one observed on page load.
452  EXPECT_EQ(new_action, GetPendingCredentials(&manager)->action);
453}
454
455TEST_F(PasswordFormManagerTest, TestAlternateUsername) {
456  // Need a MessageLoop for callbacks.
457  base::MessageLoop message_loop;
458  scoped_refptr<TestPasswordStore> password_store = new TestPasswordStore;
459  CHECK(password_store->Init(syncer::SyncableService::StartSyncFlare(), ""));
460
461  TestPasswordManagerClient client_with_store(password_store.get());
462  TestPasswordManager password_manager(&client_with_store);
463  PasswordFormManager manager(&password_manager,
464                              &client_with_store,
465                              client_with_store.GetDriver(),
466                              *observed_form(),
467                              false);
468  EXPECT_CALL(*client_with_store.GetMockDriver(),
469              AllowPasswordGenerationForForm(_)).Times(1);
470  EXPECT_CALL(*client_with_store.GetMockDriver(), IsOffTheRecord())
471      .WillRepeatedly(Return(false));
472
473  password_store->AddLogin(*saved_match());
474  manager.FetchMatchingLoginsFromPasswordStore(PasswordStore::ALLOW_PROMPT);
475  RunAllPendingTasks();
476
477  // The saved match has the right username already.
478  PasswordForm login(*observed_form());
479  login.username_value = saved_match()->username_value;
480  login.password_value = saved_match()->password_value;
481  login.preferred = true;
482  manager.ProvisionallySave(
483      login, PasswordFormManager::ALLOW_OTHER_POSSIBLE_USERNAMES);
484
485  EXPECT_FALSE(manager.IsNewLogin());
486  manager.Save();
487  RunAllPendingTasks();
488
489  // Should be only one password stored, and should not have
490  // |other_possible_usernames| set anymore.
491  TestPasswordStore::PasswordMap passwords = password_store->stored_passwords();
492  EXPECT_EQ(1U, passwords.size());
493  ASSERT_EQ(1U, passwords[saved_match()->signon_realm].size());
494  EXPECT_EQ(saved_match()->username_value,
495            passwords[saved_match()->signon_realm][0].username_value);
496  EXPECT_EQ(0U,
497            passwords[saved_match()->signon_realm][0]
498                .other_possible_usernames.size());
499
500  // This time use an alternate username
501  PasswordFormManager manager_alt(&password_manager,
502                                  &client_with_store,
503                                  client_with_store.GetDriver(),
504                                  *observed_form(),
505                                  false);
506  EXPECT_CALL(*client_with_store.GetMockDriver(),
507              AllowPasswordGenerationForForm(_)).Times(1);
508  password_store->Clear();
509  password_store->AddLogin(*saved_match());
510  manager_alt.FetchMatchingLoginsFromPasswordStore(PasswordStore::ALLOW_PROMPT);
511  RunAllPendingTasks();
512
513  base::string16 new_username = saved_match()->other_possible_usernames[0];
514  login.username_value = new_username;
515  manager_alt.ProvisionallySave(
516      login, PasswordFormManager::ALLOW_OTHER_POSSIBLE_USERNAMES);
517
518  EXPECT_FALSE(manager_alt.IsNewLogin());
519  manager_alt.Save();
520  RunAllPendingTasks();
521
522  // |other_possible_usernames| should also be empty, but username_value should
523  // be changed to match |new_username|
524  passwords = password_store->stored_passwords();
525  EXPECT_EQ(1U, passwords.size());
526  ASSERT_EQ(1U, passwords[saved_match()->signon_realm].size());
527  EXPECT_EQ(new_username,
528            passwords[saved_match()->signon_realm][0].username_value);
529  EXPECT_EQ(0U,
530            passwords[saved_match()->signon_realm][0]
531                .other_possible_usernames.size());
532  password_store->Shutdown();
533}
534
535TEST_F(PasswordFormManagerTest, TestValidForms) {
536  // User submits credentials for the observed form.
537  PasswordForm credentials = *observed_form();
538  credentials.scheme = PasswordForm::SCHEME_HTML;
539  credentials.username_value = saved_match()->username_value;
540  credentials.password_value = saved_match()->password_value;
541
542  // An alternate version of the form that also has a new_password_element.
543  PasswordForm new_credentials(*observed_form());
544  new_credentials.new_password_element = ASCIIToUTF16("NewPasswd");
545  new_credentials.new_password_value = ASCIIToUTF16("test1new");
546
547  // Form with both username_element and password_element.
548  PasswordFormManager manager1(NULL, NULL, NULL, credentials, false);
549  SimulateMatchingPhase(&manager1, false);
550  EXPECT_TRUE(manager1.HasValidPasswordForm());
551
552  // Form with username_element, password_element, and new_password_element.
553  PasswordFormManager manager2(NULL, NULL, NULL, new_credentials, false);
554  SimulateMatchingPhase(&manager2, false);
555  EXPECT_TRUE(manager2.HasValidPasswordForm());
556
557  // Form with username_element and only new_password_element.
558  new_credentials.password_element.clear();
559  PasswordFormManager manager3(NULL, NULL, NULL, new_credentials, false);
560  SimulateMatchingPhase(&manager3, false);
561  EXPECT_TRUE(manager3.HasValidPasswordForm());
562
563  // Form without a username_element but with a password_element.
564  credentials.username_element.clear();
565  PasswordFormManager manager4(NULL, NULL, NULL, credentials, false);
566  SimulateMatchingPhase(&manager4, false);
567  EXPECT_FALSE(manager4.HasValidPasswordForm());
568
569  // Form without a username_element but with a new_password_element.
570  new_credentials.username_element.clear();
571  PasswordFormManager manager5(NULL, NULL, NULL, new_credentials, false);
572  SimulateMatchingPhase(&manager5, false);
573  EXPECT_FALSE(manager5.HasValidPasswordForm());
574
575  // Form without a password_element but with a username_element.
576  credentials.username_element = saved_match()->username_element;
577  credentials.password_element.clear();
578  PasswordFormManager manager6(NULL, NULL, NULL, credentials, false);
579  SimulateMatchingPhase(&manager6, false);
580  EXPECT_FALSE(manager6.HasValidPasswordForm());
581
582  // Form with neither a password_element nor a username_element.
583  credentials.username_element.clear();
584  credentials.password_element.clear();
585  PasswordFormManager manager7(NULL, NULL, NULL, credentials, false);
586  SimulateMatchingPhase(&manager7, false);
587  EXPECT_FALSE(manager7.HasValidPasswordForm());
588}
589
590TEST_F(PasswordFormManagerTest, TestValidFormsBasic) {
591  // User submits credentials for the observed form.
592  PasswordForm credentials = *observed_form();
593  credentials.scheme = PasswordForm::SCHEME_BASIC;
594  credentials.username_value = saved_match()->username_value;
595  credentials.password_value = saved_match()->password_value;
596
597  // Form with both username_element and password_element.
598  PasswordFormManager manager1(NULL, NULL, NULL, credentials, false);
599  SimulateMatchingPhase(&manager1, false);
600  EXPECT_TRUE(manager1.HasValidPasswordForm());
601
602  // Form without a username_element but with a password_element.
603  credentials.username_element.clear();
604  PasswordFormManager manager2(NULL, NULL, NULL, credentials, false);
605  SimulateMatchingPhase(&manager2, false);
606  EXPECT_TRUE(manager2.HasValidPasswordForm());
607
608  // Form without a password_element but with a username_element.
609  credentials.username_element = saved_match()->username_element;
610  credentials.password_element.clear();
611  PasswordFormManager manager3(NULL, NULL, NULL, credentials, false);
612  SimulateMatchingPhase(&manager3, false);
613  EXPECT_TRUE(manager3.HasValidPasswordForm());
614
615  // Form with neither a password_element nor a username_element.
616  credentials.username_element.clear();
617  credentials.password_element.clear();
618  PasswordFormManager manager4(NULL, NULL, NULL, credentials, false);
619  SimulateMatchingPhase(&manager4, false);
620  EXPECT_TRUE(manager4.HasValidPasswordForm());
621}
622
623TEST_F(PasswordFormManagerTest, TestSendNotBlacklistedMessage) {
624  base::MessageLoop message_loop;
625
626  TestPasswordManager password_manager(client());
627  PasswordFormManager manager_no_creds(&password_manager,
628                                       client(),
629                                       client()->GetDriver(),
630                                       *observed_form(),
631                                       false);
632
633  // First time sign-up attempt. Password store does not contain matching
634  // credentials. AllowPasswordGenerationForForm should be called to send the
635  // "not blacklisted" message.
636  EXPECT_CALL(*(client()->GetMockDriver()), AllowPasswordGenerationForForm(_))
637      .Times(1);
638  SimulateFetchMatchingLoginsFromPasswordStore(&manager_no_creds);
639  std::vector<PasswordForm*> result;
640  SimulateResponseFromPasswordStore(&manager_no_creds, result);
641  Mock::VerifyAndClearExpectations(client()->GetMockDriver());
642
643  // Signing up on a previously visited site. Credentials are found in the
644  // password store, and are not blacklisted. AllowPasswordGenerationForForm
645  // should be called to send the "not blacklisted" message.
646  PasswordFormManager manager_creds(&password_manager,
647                                    client(),
648                                    client()->GetDriver(),
649                                    *observed_form(),
650                                    false);
651  EXPECT_CALL(*(client()->GetMockDriver()), AllowPasswordGenerationForForm(_))
652      .Times(1);
653  EXPECT_CALL(*(client()->GetMockDriver()), IsOffTheRecord())
654      .WillRepeatedly(Return(false));
655  SimulateFetchMatchingLoginsFromPasswordStore(&manager_creds);
656  // We need add heap allocated objects to result.
657  result.push_back(CreateSavedMatch(false));
658  SimulateResponseFromPasswordStore(&manager_creds, result);
659  Mock::VerifyAndClearExpectations(client()->GetMockDriver());
660
661  // Signing up on a previously visited site. Credentials are found in the
662  // password store, but they are blacklisted. AllowPasswordGenerationForForm
663  // should not be called and no "not blacklisted" message sent.
664  PasswordFormManager manager_blacklisted(&password_manager,
665                                          client(),
666                                          client()->GetDriver(),
667                                          *observed_form(),
668                                          false);
669  EXPECT_CALL(*(client()->GetMockDriver()), AllowPasswordGenerationForForm(_))
670      .Times(0);
671  SimulateFetchMatchingLoginsFromPasswordStore(&manager_blacklisted);
672  result.clear();
673  result.push_back(CreateSavedMatch(true));
674  SimulateResponseFromPasswordStore(&manager_blacklisted, result);
675  Mock::VerifyAndClearExpectations(client()->GetMockDriver());
676}
677
678TEST_F(PasswordFormManagerTest, TestForceInclusionOfGeneratedPasswords) {
679  base::MessageLoop message_loop;
680
681  // Simulate having two matches for this origin, one of which was from a form
682  // with different HTML tags for elements. Because of scoring differences,
683  // only the first form will be sent to Autofill().
684  TestPasswordManager password_manager(client());
685  PasswordFormManager manager_match(&password_manager,
686                                    client(),
687                                    client()->GetDriver(),
688                                    *observed_form(),
689                                    false);
690  EXPECT_CALL(*(client()->GetMockDriver()), AllowPasswordGenerationForForm(_))
691      .Times(1);
692  EXPECT_CALL(*(client()->GetMockDriver()), IsOffTheRecord())
693      .WillRepeatedly(Return(false));
694
695  std::vector<PasswordForm*> results;
696  results.push_back(CreateSavedMatch(false));
697  results.push_back(CreateSavedMatch(false));
698  results[1]->username_value = ASCIIToUTF16("other@gmail.com");
699  results[1]->password_element = ASCIIToUTF16("signup_password");
700  results[1]->username_element = ASCIIToUTF16("signup_username");
701  SimulateFetchMatchingLoginsFromPasswordStore(&manager_match);
702  SimulateResponseFromPasswordStore(&manager_match, results);
703  EXPECT_EQ(1u, password_manager.GetLatestBestMatches().size());
704  results.clear();
705
706  // Same thing, except this time the credentials that don't match quite as
707  // well are generated. They should now be sent to Autofill().
708  PasswordFormManager manager_no_match(&password_manager,
709                                       client(),
710                                       client()->GetDriver(),
711                                       *observed_form(),
712                                       false);
713  EXPECT_CALL(*(client()->GetMockDriver()), AllowPasswordGenerationForForm(_))
714      .Times(1);
715
716  results.push_back(CreateSavedMatch(false));
717  results.push_back(CreateSavedMatch(false));
718  results[1]->username_value = ASCIIToUTF16("other@gmail.com");
719  results[1]->password_element = ASCIIToUTF16("signup_password");
720  results[1]->username_element = ASCIIToUTF16("signup_username");
721  results[1]->type = PasswordForm::TYPE_GENERATED;
722  SimulateFetchMatchingLoginsFromPasswordStore(&manager_no_match);
723  SimulateResponseFromPasswordStore(&manager_no_match, results);
724  EXPECT_EQ(2u, password_manager.GetLatestBestMatches().size());
725}
726
727TEST_F(PasswordFormManagerTest, TestSanitizePossibleUsernames) {
728  PasswordFormManager manager(NULL, client(), NULL, *observed_form(), false);
729  PasswordForm credentials(*observed_form());
730  credentials.other_possible_usernames.push_back(ASCIIToUTF16("543-43-1234"));
731  credentials.other_possible_usernames.push_back(
732      ASCIIToUTF16("378282246310005"));
733  credentials.other_possible_usernames.push_back(
734      ASCIIToUTF16("other username"));
735  credentials.username_value = ASCIIToUTF16("test@gmail.com");
736
737  SanitizePossibleUsernames(&manager, &credentials);
738
739  // Possible credit card number and SSN are stripped.
740  std::vector<base::string16> expected;
741  expected.push_back(ASCIIToUTF16("other username"));
742  EXPECT_THAT(credentials.other_possible_usernames, Eq(expected));
743
744  credentials.other_possible_usernames.clear();
745  credentials.other_possible_usernames.push_back(ASCIIToUTF16("511-32-9830"));
746  credentials.other_possible_usernames.push_back(ASCIIToUTF16("duplicate"));
747  credentials.other_possible_usernames.push_back(ASCIIToUTF16("duplicate"));
748  credentials.other_possible_usernames.push_back(ASCIIToUTF16("random"));
749  credentials.other_possible_usernames.push_back(
750      ASCIIToUTF16("test@gmail.com"));
751
752  SanitizePossibleUsernames(&manager, &credentials);
753
754  // SSN, duplicate in |other_possible_usernames| and duplicate of
755  // |username_value| all removed.
756  expected.clear();
757  expected.push_back(ASCIIToUTF16("duplicate"));
758  expected.push_back(ASCIIToUTF16("random"));
759  EXPECT_THAT(credentials.other_possible_usernames, Eq(expected));
760}
761
762TEST_F(PasswordFormManagerTest, TestUpdateIncompleteCredentials) {
763  InitializeMockStore();
764
765  // We've found this form on a website:
766  PasswordForm encountered_form;
767  encountered_form.origin = GURL("http://accounts.google.com/LoginAuth");
768  encountered_form.signon_realm = "http://accounts.google.com/";
769  encountered_form.action = GURL("http://accounts.google.com/Login");
770  encountered_form.username_element = ASCIIToUTF16("Email");
771  encountered_form.password_element = ASCIIToUTF16("Passwd");
772  encountered_form.submit_element = ASCIIToUTF16("signIn");
773
774  TestPasswordManagerClient client_with_store(mock_store());
775  EXPECT_CALL(*(client_with_store.GetMockDriver()), IsOffTheRecord())
776      .WillRepeatedly(Return(false));
777  EXPECT_CALL(*(client_with_store.GetMockDriver()),
778              AllowPasswordGenerationForForm(_));
779
780  TestPasswordManager manager(&client_with_store);
781  PasswordFormManager form_manager(&manager,
782                                   &client_with_store,
783                                   client_with_store.GetMockDriver(),
784                                   encountered_form,
785                                   false);
786
787  const PasswordStore::AuthorizationPromptPolicy auth_policy =
788      PasswordStore::DISALLOW_PROMPT;
789  EXPECT_CALL(*mock_store(),
790              GetLogins(encountered_form, auth_policy, &form_manager));
791  form_manager.FetchMatchingLoginsFromPasswordStore(auth_policy);
792
793  // Password store only has these incomplete credentials.
794  PasswordForm* incomplete_form = new PasswordForm();
795  incomplete_form->origin = GURL("http://accounts.google.com/LoginAuth");
796  incomplete_form->signon_realm = "http://accounts.google.com/";
797  incomplete_form->password_value = ASCIIToUTF16("my_password");
798  incomplete_form->username_value = ASCIIToUTF16("my_username");
799  incomplete_form->preferred = true;
800  incomplete_form->ssl_valid = false;
801  incomplete_form->scheme = PasswordForm::SCHEME_HTML;
802
803  // We expect to see this form eventually sent to the Password store. It
804  // has password/username values from the store and 'username_element',
805  // 'password_element', 'submit_element' and 'action' fields copied from
806  // the encountered form.
807  PasswordForm complete_form(*incomplete_form);
808  complete_form.action = encountered_form.action;
809  complete_form.password_element = encountered_form.password_element;
810  complete_form.username_element = encountered_form.username_element;
811  complete_form.submit_element = encountered_form.submit_element;
812
813  PasswordForm obsolete_form(*incomplete_form);
814  obsolete_form.action = encountered_form.action;
815
816  // Feed the incomplete credentials to the manager.
817  std::vector<PasswordForm*> results;
818  results.push_back(incomplete_form);  // Takes ownership.
819  form_manager.OnRequestDone(results);
820
821  form_manager.ProvisionallySave(
822      complete_form, PasswordFormManager::IGNORE_OTHER_POSSIBLE_USERNAMES);
823  // By now that form has been used once.
824  complete_form.times_used = 1;
825  obsolete_form.times_used = 1;
826
827  // Check that PasswordStore receives an update request with the complete form.
828  EXPECT_CALL(*mock_store(), RemoveLogin(obsolete_form));
829  EXPECT_CALL(*mock_store(), AddLogin(complete_form));
830  form_manager.Save();
831}
832
833TEST_F(PasswordFormManagerTest, TestScoringPublicSuffixMatch) {
834  base::MessageLoop message_loop;
835
836  EXPECT_CALL(*(client()->GetMockDriver()), IsOffTheRecord())
837      .WillRepeatedly(Return(false));
838  EXPECT_CALL(*(client()->GetMockDriver()), AllowPasswordGenerationForForm(_));
839
840  TestPasswordManager password_manager(client());
841  PasswordFormManager manager(&password_manager,
842                              client(),
843                              client()->GetMockDriver(),
844                              *observed_form(),
845                              false);
846
847  // Simulate having two matches for this form, first comes from different
848  // signon realm, but reports the same origin and action as matched form.
849  // Second candidate has the same signon realm as the form, but has a different
850  // origin and action. Public suffix match is the most important criterion so
851  // the second candidate should be selected.
852  std::vector<PasswordForm*> results;
853  results.push_back(CreateSavedMatch(false));
854  results.push_back(CreateSavedMatch(false));
855  results[0]->original_signon_realm = "http://accounts2.google.com";
856  results[1]->origin = GURL("http://accounts.google.com/a/ServiceLoginAuth2");
857  results[1]->action = GURL("http://accounts.google.com/a/ServiceLogin2");
858  SimulateFetchMatchingLoginsFromPasswordStore(&manager);
859  SimulateResponseFromPasswordStore(&manager, results);
860  EXPECT_EQ(1u, password_manager.GetLatestBestMatches().size());
861  EXPECT_EQ("", password_manager.GetLatestBestMatches().begin()
862      ->second->original_signon_realm);
863}
864
865TEST_F(PasswordFormManagerTest, InvalidActionURLsDoNotMatch) {
866  PasswordFormManager manager(NULL, client(), NULL, *observed_form(), false);
867
868  PasswordForm invalid_action_form(*observed_form());
869  invalid_action_form.action = GURL("http://");
870  ASSERT_FALSE(invalid_action_form.action.is_valid());
871  ASSERT_FALSE(invalid_action_form.action.is_empty());
872  // Non-empty invalid action URLs should not match other actions.
873  // First when the compared form has an invalid URL:
874  EXPECT_EQ(0,
875            manager.DoesManage(invalid_action_form) &
876                PasswordFormManager::RESULT_ACTION_MATCH);
877  // Then when the observed form has an invalid URL:
878  PasswordForm valid_action_form(*observed_form());
879  PasswordFormManager invalid_manager(
880      NULL, client(), NULL, invalid_action_form, false);
881  EXPECT_EQ(0,
882            invalid_manager.DoesManage(valid_action_form) &
883                PasswordFormManager::RESULT_ACTION_MATCH);
884}
885
886TEST_F(PasswordFormManagerTest, EmptyActionURLsDoNotMatchNonEmpty) {
887  PasswordFormManager manager(NULL, client(), NULL, *observed_form(), false);
888
889  PasswordForm empty_action_form(*observed_form());
890  empty_action_form.action = GURL();
891  ASSERT_FALSE(empty_action_form.action.is_valid());
892  ASSERT_TRUE(empty_action_form.action.is_empty());
893  // First when the compared form has an empty URL:
894  EXPECT_EQ(0,
895            manager.DoesManage(empty_action_form) &
896                PasswordFormManager::RESULT_ACTION_MATCH);
897  // Then when the observed form has an empty URL:
898  PasswordForm valid_action_form(*observed_form());
899  PasswordFormManager empty_action_manager(
900      NULL, client(), NULL, empty_action_form, false);
901  EXPECT_EQ(0,
902            empty_action_manager.DoesManage(valid_action_form) &
903                PasswordFormManager::RESULT_ACTION_MATCH);
904}
905
906TEST_F(PasswordFormManagerTest, NonHTMLFormsDoNotMatchHTMLForms) {
907  PasswordFormManager manager(NULL, client(), NULL, *observed_form(), false);
908
909  ASSERT_EQ(PasswordForm::SCHEME_HTML, observed_form()->scheme);
910  PasswordForm non_html_form(*observed_form());
911  non_html_form.scheme = PasswordForm::SCHEME_DIGEST;
912  EXPECT_EQ(0,
913            manager.DoesManage(non_html_form) &
914                PasswordFormManager::RESULT_MANDATORY_ATTRIBUTES_MATCH);
915
916  // The other way round: observing a non-HTML form, don't match a HTML form.
917  PasswordForm html_form(*observed_form());
918  PasswordFormManager non_html_manager(
919      NULL, client(), NULL, non_html_form, false);
920  EXPECT_EQ(0,
921            non_html_manager.DoesManage(html_form) &
922                PasswordFormManager::RESULT_MANDATORY_ATTRIBUTES_MATCH);
923}
924
925TEST_F(PasswordFormManagerTest, OriginCheck_HostsMatchExactly) {
926  // Host part of origins must match exactly, not just by prefix.
927  PasswordFormManager manager(NULL, client(), NULL, *observed_form(), false);
928
929  PasswordForm form_longer_host(*observed_form());
930  form_longer_host.origin = GURL("http://accounts.google.com.au/a/LoginAuth");
931  // Check that accounts.google.com does not match accounts.google.com.au.
932  EXPECT_EQ(0,
933            manager.DoesManage(form_longer_host) &
934                PasswordFormManager::RESULT_MANDATORY_ATTRIBUTES_MATCH);
935}
936
937TEST_F(PasswordFormManagerTest, OriginCheck_MoreSecureSchemePathsMatchPrefix) {
938  // If the URL scheme of the observed form is HTTP, and the compared form is
939  // HTTPS, then the compared form can extend the path.
940  PasswordFormManager manager(NULL, client(), NULL, *observed_form(), false);
941
942  PasswordForm form_longer_path(*observed_form());
943  form_longer_path.origin = GURL("https://accounts.google.com/a/LoginAuth/sec");
944  EXPECT_NE(0,
945            manager.DoesManage(form_longer_path) &
946                PasswordFormManager::RESULT_MANDATORY_ATTRIBUTES_MATCH);
947}
948
949TEST_F(PasswordFormManagerTest,
950       OriginCheck_NotMoreSecureSchemePathsMatchExactly) {
951  // If the origin URL scheme of the compared form is not more secure than that
952  // of the observed form, then the paths must match exactly.
953  PasswordFormManager manager(NULL, client(), NULL, *observed_form(), false);
954
955  PasswordForm form_longer_path(*observed_form());
956  form_longer_path.origin = GURL("http://accounts.google.com/a/LoginAuth/sec");
957  // Check that /a/LoginAuth does not match /a/LoginAuth/more.
958  EXPECT_EQ(0,
959            manager.DoesManage(form_longer_path) &
960                PasswordFormManager::RESULT_MANDATORY_ATTRIBUTES_MATCH);
961
962  PasswordForm secure_observed_form(*observed_form());
963  secure_observed_form.origin = GURL("https://accounts.google.com/a/LoginAuth");
964  PasswordFormManager secure_manager(
965      NULL, client(), NULL, secure_observed_form, true);
966  // Also for HTTPS in the observed form, and HTTP in the compared form, an
967  // exact path match is expected.
968  EXPECT_EQ(0,
969            secure_manager.DoesManage(form_longer_path) &
970                PasswordFormManager::RESULT_MANDATORY_ATTRIBUTES_MATCH);
971  // Not even upgrade to HTTPS in the compared form should help.
972  form_longer_path.origin = GURL("https://accounts.google.com/a/LoginAuth/sec");
973  EXPECT_EQ(0,
974            secure_manager.DoesManage(form_longer_path) &
975                PasswordFormManager::RESULT_MANDATORY_ATTRIBUTES_MATCH);
976}
977
978}  // namespace password_manager
979