password_form_manager_unittest.cc revision cedac228d2dd51db4b79ea1e72c7f249408ee061
1// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "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_manager_driver.h"
15#include "components/password_manager/core/browser/mock_password_store.h"
16#include "components/password_manager/core/browser/password_form_manager.h"
17#include "components/password_manager/core/browser/password_manager.h"
18#include "components/password_manager/core/browser/password_manager_driver.h"
19#include "components/password_manager/core/browser/password_store.h"
20#include "components/password_manager/core/browser/stub_password_manager_client.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 TestPasswordManagerClient : public StubPasswordManagerClient {
49 public:
50  explicit TestPasswordManagerClient(PasswordStore* password_store)
51      : password_store_(password_store) {
52    prefs_.registry()->RegisterBooleanPref(prefs::kPasswordManagerEnabled,
53                                           true);
54  }
55
56  virtual void PromptUserToSavePassword(PasswordFormManager* form_to_save)
57      OVERRIDE {}
58  virtual PrefService* GetPrefs() OVERRIDE { return &prefs_; }
59  virtual PasswordStore* GetPasswordStore() OVERRIDE { return password_store_; }
60  virtual PasswordManagerDriver* GetDriver() OVERRIDE { return &driver_; }
61  virtual void AuthenticateAutofillAndFillForm(
62      scoped_ptr<autofill::PasswordFormFillData> fill_data) OVERRIDE {
63    driver_.FillPasswordForm(*fill_data.get());
64  }
65
66  MockPasswordManagerDriver* GetMockDriver() { return &driver_; }
67
68 private:
69  TestingPrefServiceSimple prefs_;
70  PasswordStore* password_store_;
71  MockPasswordManagerDriver driver_;
72};
73
74class TestPasswordManager : public PasswordManager {
75 public:
76  explicit TestPasswordManager(PasswordManagerClient* client)
77      : PasswordManager(client) {}
78
79  virtual void Autofill(const autofill::PasswordForm& form_for_autofill,
80                        const autofill::PasswordFormMap& best_matches,
81                        const autofill::PasswordForm& preferred_match,
82                        bool wait_for_username) const OVERRIDE {
83    best_matches_ = best_matches;
84  }
85
86  const autofill::PasswordFormMap& GetLatestBestMatches() {
87    return best_matches_;
88  }
89
90 private:
91  // Marked mutable to get around constness of Autofill().
92  mutable autofill::PasswordFormMap best_matches_;
93};
94
95}  // namespace
96
97class PasswordFormManagerTest : public testing::Test {
98 public:
99  PasswordFormManagerTest() {}
100
101  virtual void SetUp() {
102    observed_form_.origin = GURL("http://accounts.google.com/a/LoginAuth");
103    observed_form_.action = GURL("http://accounts.google.com/a/Login");
104    observed_form_.username_element = ASCIIToUTF16("Email");
105    observed_form_.password_element = ASCIIToUTF16("Passwd");
106    observed_form_.submit_element = ASCIIToUTF16("signIn");
107    observed_form_.signon_realm = "http://accounts.google.com";
108
109    saved_match_ = observed_form_;
110    saved_match_.origin = GURL("http://accounts.google.com/a/ServiceLoginAuth");
111    saved_match_.action = GURL("http://accounts.google.com/a/ServiceLogin");
112    saved_match_.preferred = true;
113    saved_match_.username_value = ASCIIToUTF16("test@gmail.com");
114    saved_match_.password_value = ASCIIToUTF16("test1");
115    saved_match_.other_possible_usernames.push_back(
116        ASCIIToUTF16("test2@gmail.com"));
117  }
118
119  virtual void TearDown() {
120    if (mock_store_)
121      mock_store_->Shutdown();
122  }
123
124  void InitializeMockStore() {
125    if (!mock_store_) {
126      mock_store_ = new MockPasswordStore();
127      ASSERT_TRUE(mock_store_);
128    }
129  }
130
131  MockPasswordStore* mock_store() const { return mock_store_.get(); }
132
133  PasswordForm* GetPendingCredentials(PasswordFormManager* p) {
134    return &p->pending_credentials_;
135  }
136
137  void SimulateMatchingPhase(PasswordFormManager* p, bool find_match) {
138    // Roll up the state to mock out the matching phase.
139    p->state_ = PasswordFormManager::POST_MATCHING_PHASE;
140    if (!find_match)
141      return;
142
143    PasswordForm* match = new PasswordForm(saved_match_);
144    // Heap-allocated form is owned by p.
145    p->best_matches_[match->username_value] = match;
146    p->preferred_match_ = match;
147  }
148
149  void SimulateFetchMatchingLoginsFromPasswordStore(
150      PasswordFormManager* manager) {
151    // Just need to update the internal states.
152    manager->state_ = PasswordFormManager::MATCHING_PHASE;
153  }
154
155  void SimulateResponseFromPasswordStore(
156      PasswordFormManager* manager,
157      const std::vector<PasswordForm*>& result) {
158    // Simply call the callback method when request done. This will transfer
159    // the ownership of the objects in |result| to the |manager|.
160    manager->OnGetPasswordStoreResults(result);
161  }
162
163  void SanitizePossibleUsernames(PasswordFormManager* p, PasswordForm* form) {
164    p->SanitizePossibleUsernames(form);
165  }
166
167  bool IgnoredResult(PasswordFormManager* p, PasswordForm* form) {
168    return p->IgnoreResult(*form);
169  }
170
171  PasswordForm* observed_form() { return &observed_form_; }
172  PasswordForm* saved_match() { return &saved_match_; }
173  PasswordForm* CreateSavedMatch(bool blacklisted) {
174    // Owned by the caller of this method.
175    PasswordForm* match = new PasswordForm(saved_match_);
176    match->blacklisted_by_user = blacklisted;
177    return match;
178  }
179
180 private:
181  PasswordForm observed_form_;
182  PasswordForm saved_match_;
183  scoped_refptr<MockPasswordStore> mock_store_;
184};
185
186TEST_F(PasswordFormManagerTest, TestNewLogin) {
187  scoped_ptr<TestPasswordManagerClient> client(
188      new TestPasswordManagerClient(NULL));
189  scoped_ptr<MockPasswordManagerDriver> driver;
190  PasswordFormManager* manager = new PasswordFormManager(
191      NULL, client.get(), driver.get(), *observed_form(), false);
192
193  SimulateMatchingPhase(manager, false);
194  // User submits credentials for the observed form.
195  PasswordForm credentials = *observed_form();
196  credentials.username_value = saved_match()->username_value;
197  credentials.password_value = saved_match()->password_value;
198  credentials.preferred = true;
199  manager->ProvisionallySave(
200      credentials, PasswordFormManager::IGNORE_OTHER_POSSIBLE_USERNAMES);
201
202  // Successful login. The PasswordManager would instruct PasswordFormManager
203  // to save, which should know this is a new login.
204  EXPECT_TRUE(manager->IsNewLogin());
205  // Make sure the credentials that would be submitted on successful login
206  // are going to match the stored entry in the db.
207  EXPECT_EQ(observed_form()->origin.spec(),
208            GetPendingCredentials(manager)->origin.spec());
209  EXPECT_EQ(observed_form()->signon_realm,
210            GetPendingCredentials(manager)->signon_realm);
211  EXPECT_EQ(observed_form()->action, GetPendingCredentials(manager)->action);
212  EXPECT_TRUE(GetPendingCredentials(manager)->preferred);
213  EXPECT_EQ(saved_match()->password_value,
214            GetPendingCredentials(manager)->password_value);
215  EXPECT_EQ(saved_match()->username_value,
216            GetPendingCredentials(manager)->username_value);
217
218  // Now, suppose the user re-visits the site and wants to save an additional
219  // login for the site with a new username. In this case, the matching phase
220  // will yield the previously saved login.
221  SimulateMatchingPhase(manager, true);
222  // Set up the new login.
223  base::string16 new_user = ASCIIToUTF16("newuser");
224  base::string16 new_pass = ASCIIToUTF16("newpass");
225  credentials.username_value = new_user;
226  credentials.password_value = new_pass;
227  manager->ProvisionallySave(
228      credentials, PasswordFormManager::IGNORE_OTHER_POSSIBLE_USERNAMES);
229
230  // Again, the PasswordFormManager should know this is still a new login.
231  EXPECT_TRUE(manager->IsNewLogin());
232  // And make sure everything squares up again.
233  EXPECT_EQ(observed_form()->origin.spec(),
234            GetPendingCredentials(manager)->origin.spec());
235  EXPECT_EQ(observed_form()->signon_realm,
236            GetPendingCredentials(manager)->signon_realm);
237  EXPECT_TRUE(GetPendingCredentials(manager)->preferred);
238  EXPECT_EQ(new_pass, GetPendingCredentials(manager)->password_value);
239  EXPECT_EQ(new_user, GetPendingCredentials(manager)->username_value);
240  delete manager;
241}
242
243TEST_F(PasswordFormManagerTest, TestUpdatePassword) {
244  // Create a PasswordFormManager with observed_form, as if we just
245  // saw this form and need to find matching logins.
246  scoped_ptr<TestPasswordManagerClient> client(
247      new TestPasswordManagerClient(NULL));
248  scoped_ptr<MockPasswordManagerDriver> driver;
249  PasswordFormManager* manager = new PasswordFormManager(
250      NULL, client.get(), driver.get(), *observed_form(), false);
251
252  SimulateMatchingPhase(manager, true);
253
254  // User submits credentials for the observed form using a username previously
255  // stored, but a new password. Note that the observed form may have different
256  // origin URL (as it does in this case) than the saved_match, but we want to
257  // make sure the updated password is reflected in saved_match, because that is
258  // what we autofilled.
259  base::string16 new_pass = ASCIIToUTF16("newpassword");
260  PasswordForm credentials = *observed_form();
261  credentials.username_value = saved_match()->username_value;
262  credentials.password_value = new_pass;
263  credentials.preferred = true;
264  manager->ProvisionallySave(
265      credentials, PasswordFormManager::IGNORE_OTHER_POSSIBLE_USERNAMES);
266
267  // Successful login. The PasswordManager would instruct PasswordFormManager
268  // to save, and since this is an update, it should know not to save as a new
269  // login.
270  EXPECT_FALSE(manager->IsNewLogin());
271
272  // Make sure the credentials that would be submitted on successful login
273  // are going to match the stored entry in the db. (This verifies correct
274  // behaviour for bug 1074420).
275  EXPECT_EQ(GetPendingCredentials(manager)->origin.spec(),
276            saved_match()->origin.spec());
277  EXPECT_EQ(GetPendingCredentials(manager)->signon_realm,
278            saved_match()->signon_realm);
279  EXPECT_TRUE(GetPendingCredentials(manager)->preferred);
280  EXPECT_EQ(new_pass, GetPendingCredentials(manager)->password_value);
281  // Done.
282  delete manager;
283}
284
285TEST_F(PasswordFormManagerTest, TestIgnoreResult) {
286  scoped_ptr<TestPasswordManagerClient> client(
287      new TestPasswordManagerClient(NULL));
288  scoped_ptr<MockPasswordManagerDriver> driver;
289  PasswordFormManager* manager = new PasswordFormManager(
290      NULL, client.get(), driver.get(), *observed_form(), false);
291
292  // Make sure we don't match a PasswordForm if it was originally saved on
293  // an SSL-valid page and we are now on a page with invalid certificate.
294  saved_match()->ssl_valid = true;
295  EXPECT_TRUE(IgnoredResult(manager, saved_match()));
296
297  saved_match()->ssl_valid = false;
298  // Different paths for action / origin are okay.
299  saved_match()->action = GURL("http://www.google.com/b/Login");
300  saved_match()->origin = GURL("http://www.google.com/foo");
301  EXPECT_FALSE(IgnoredResult(manager, saved_match()));
302
303  // Done.
304  delete manager;
305}
306
307TEST_F(PasswordFormManagerTest, TestEmptyAction) {
308  scoped_ptr<TestPasswordManagerClient> client(
309      new TestPasswordManagerClient(NULL));
310  scoped_ptr<MockPasswordManagerDriver> driver;
311  scoped_ptr<PasswordFormManager> manager(new PasswordFormManager(
312      NULL, client.get(), driver.get(), *observed_form(), false));
313
314  saved_match()->action = GURL();
315  SimulateMatchingPhase(manager.get(), true);
316  // User logs in with the autofilled username / password from saved_match.
317  PasswordForm login = *observed_form();
318  login.username_value = saved_match()->username_value;
319  login.password_value = saved_match()->password_value;
320  manager->ProvisionallySave(
321      login, PasswordFormManager::IGNORE_OTHER_POSSIBLE_USERNAMES);
322  EXPECT_FALSE(manager->IsNewLogin());
323  // We bless our saved PasswordForm entry with the action URL of the
324  // observed form.
325  EXPECT_EQ(observed_form()->action,
326            GetPendingCredentials(manager.get())->action);
327}
328
329TEST_F(PasswordFormManagerTest, TestUpdateAction) {
330  scoped_ptr<TestPasswordManagerClient> client(
331      new TestPasswordManagerClient(NULL));
332  scoped_ptr<MockPasswordManagerDriver> driver;
333  scoped_ptr<PasswordFormManager> manager(new PasswordFormManager(
334      NULL, client.get(), driver.get(), *observed_form(), false));
335
336  SimulateMatchingPhase(manager.get(), true);
337  // User logs in with the autofilled username / password from saved_match.
338  PasswordForm login = *observed_form();
339  login.username_value = saved_match()->username_value;
340  login.password_value = saved_match()->password_value;
341
342  manager->ProvisionallySave(
343      login, PasswordFormManager::IGNORE_OTHER_POSSIBLE_USERNAMES);
344  EXPECT_FALSE(manager->IsNewLogin());
345  // The observed action URL is different from the previously saved one, and
346  // is the same as the one that would be submitted on successful login.
347  EXPECT_NE(observed_form()->action, saved_match()->action);
348  EXPECT_EQ(observed_form()->action,
349            GetPendingCredentials(manager.get())->action);
350}
351
352TEST_F(PasswordFormManagerTest, TestDynamicAction) {
353  scoped_ptr<TestPasswordManagerClient> client(
354      new TestPasswordManagerClient(NULL));
355  scoped_ptr<MockPasswordManagerDriver> driver;
356  scoped_ptr<PasswordFormManager> manager(new PasswordFormManager(
357      NULL, client.get(), driver.get(), *observed_form(), false));
358
359  SimulateMatchingPhase(manager.get(), false);
360  PasswordForm login(*observed_form());
361  // The submitted action URL is different from the one observed on page load.
362  GURL new_action = GURL("http://www.google.com/new_action");
363  login.action = new_action;
364
365  manager->ProvisionallySave(
366      login, PasswordFormManager::IGNORE_OTHER_POSSIBLE_USERNAMES);
367  EXPECT_TRUE(manager->IsNewLogin());
368  // Check that the provisionally saved action URL is the same as the submitted
369  // action URL, not the one observed on page load.
370  EXPECT_EQ(new_action, GetPendingCredentials(manager.get())->action);
371}
372
373TEST_F(PasswordFormManagerTest, TestAlternateUsername) {
374  // Need a MessageLoop for callbacks.
375  base::MessageLoop message_loop;
376  scoped_refptr<TestPasswordStore> password_store = new TestPasswordStore;
377  CHECK(password_store->Init(syncer::SyncableService::StartSyncFlare()));
378
379  TestPasswordManagerClient client(password_store.get());
380  TestPasswordManager password_manager(&client);
381  scoped_ptr<PasswordFormManager> manager(new PasswordFormManager(
382      &password_manager, &client, client.GetDriver(), *observed_form(), false));
383  EXPECT_CALL(*client.GetMockDriver(), AllowPasswordGenerationForForm(_))
384      .Times(1);
385  EXPECT_CALL(*client.GetMockDriver(), IsOffTheRecord())
386      .WillRepeatedly(Return(false));
387
388  password_store->AddLogin(*saved_match());
389  manager->FetchMatchingLoginsFromPasswordStore(PasswordStore::ALLOW_PROMPT);
390  RunAllPendingTasks();
391
392  // The saved match has the right username already.
393  PasswordForm login(*observed_form());
394  login.username_value = saved_match()->username_value;
395  login.password_value = saved_match()->password_value;
396  login.preferred = true;
397  manager->ProvisionallySave(
398      login, PasswordFormManager::ALLOW_OTHER_POSSIBLE_USERNAMES);
399
400  EXPECT_FALSE(manager->IsNewLogin());
401  manager->Save();
402  RunAllPendingTasks();
403
404  // Should be only one password stored, and should not have
405  // |other_possible_usernames| set anymore.
406  TestPasswordStore::PasswordMap passwords = password_store->stored_passwords();
407  EXPECT_EQ(1U, passwords.size());
408  ASSERT_EQ(1U, passwords[saved_match()->signon_realm].size());
409  EXPECT_EQ(saved_match()->username_value,
410            passwords[saved_match()->signon_realm][0].username_value);
411  EXPECT_EQ(0U,
412            passwords[saved_match()->signon_realm][0]
413                .other_possible_usernames.size());
414
415  // This time use an alternate username
416  manager.reset(new PasswordFormManager(
417      &password_manager, &client, client.GetDriver(), *observed_form(), false));
418  EXPECT_CALL(*client.GetMockDriver(), AllowPasswordGenerationForForm(_))
419      .Times(1);
420  password_store->Clear();
421  password_store->AddLogin(*saved_match());
422  manager->FetchMatchingLoginsFromPasswordStore(PasswordStore::ALLOW_PROMPT);
423  RunAllPendingTasks();
424
425  base::string16 new_username = saved_match()->other_possible_usernames[0];
426  login.username_value = new_username;
427  manager->ProvisionallySave(
428      login, PasswordFormManager::ALLOW_OTHER_POSSIBLE_USERNAMES);
429
430  EXPECT_FALSE(manager->IsNewLogin());
431  manager->Save();
432  RunAllPendingTasks();
433
434  // |other_possible_usernames| should also be empty, but username_value should
435  // be changed to match |new_username|
436  passwords = password_store->stored_passwords();
437  EXPECT_EQ(1U, passwords.size());
438  ASSERT_EQ(1U, passwords[saved_match()->signon_realm].size());
439  EXPECT_EQ(new_username,
440            passwords[saved_match()->signon_realm][0].username_value);
441  EXPECT_EQ(0U,
442            passwords[saved_match()->signon_realm][0]
443                .other_possible_usernames.size());
444  password_store->Shutdown();
445}
446
447TEST_F(PasswordFormManagerTest, TestValidForms) {
448  // User submits credentials for the observed form.
449  PasswordForm credentials = *observed_form();
450  credentials.scheme = PasswordForm::SCHEME_HTML;
451  credentials.username_value = saved_match()->username_value;
452  credentials.password_value = saved_match()->password_value;
453
454  // Form with both username_element and password_element.
455  PasswordFormManager manager1(NULL, NULL, NULL, credentials, false);
456  SimulateMatchingPhase(&manager1, false);
457  EXPECT_TRUE(manager1.HasValidPasswordForm());
458
459  // Form without a username_element but with a password_element.
460  credentials.username_element.clear();
461  PasswordFormManager manager2(NULL, NULL, NULL, credentials, false);
462  SimulateMatchingPhase(&manager2, false);
463  EXPECT_FALSE(manager2.HasValidPasswordForm());
464
465  // Form without a password_element but with a username_element.
466  credentials.username_element = saved_match()->username_element;
467  credentials.password_element.clear();
468  PasswordFormManager manager3(NULL, NULL, NULL, credentials, false);
469  SimulateMatchingPhase(&manager3, false);
470  EXPECT_FALSE(manager3.HasValidPasswordForm());
471
472  // Form with neither a password_element nor a username_element.
473  credentials.username_element.clear();
474  credentials.password_element.clear();
475  PasswordFormManager manager4(NULL, NULL, NULL, credentials, false);
476  SimulateMatchingPhase(&manager4, false);
477  EXPECT_FALSE(manager4.HasValidPasswordForm());
478}
479
480TEST_F(PasswordFormManagerTest, TestValidFormsBasic) {
481  // User submits credentials for the observed form.
482  PasswordForm credentials = *observed_form();
483  credentials.scheme = PasswordForm::SCHEME_BASIC;
484  credentials.username_value = saved_match()->username_value;
485  credentials.password_value = saved_match()->password_value;
486
487  // Form with both username_element and password_element.
488  PasswordFormManager manager1(NULL, NULL, NULL, credentials, false);
489  SimulateMatchingPhase(&manager1, false);
490  EXPECT_TRUE(manager1.HasValidPasswordForm());
491
492  // Form without a username_element but with a password_element.
493  credentials.username_element.clear();
494  PasswordFormManager manager2(NULL, NULL, NULL, credentials, false);
495  SimulateMatchingPhase(&manager2, false);
496  EXPECT_TRUE(manager2.HasValidPasswordForm());
497
498  // Form without a password_element but with a username_element.
499  credentials.username_element = saved_match()->username_element;
500  credentials.password_element.clear();
501  PasswordFormManager manager3(NULL, NULL, NULL, credentials, false);
502  SimulateMatchingPhase(&manager3, false);
503  EXPECT_TRUE(manager3.HasValidPasswordForm());
504
505  // Form with neither a password_element nor a username_element.
506  credentials.username_element.clear();
507  credentials.password_element.clear();
508  PasswordFormManager manager4(NULL, NULL, NULL, credentials, false);
509  SimulateMatchingPhase(&manager4, false);
510  EXPECT_TRUE(manager4.HasValidPasswordForm());
511}
512
513TEST_F(PasswordFormManagerTest, TestSendNotBlacklistedMessage) {
514  base::MessageLoop message_loop;
515
516  // A dumb password manager.
517  TestPasswordManagerClient client(NULL);
518  TestPasswordManager password_manager(&client);
519  scoped_ptr<PasswordFormManager> manager(new PasswordFormManager(
520      &password_manager, &client, client.GetDriver(), *observed_form(), false));
521
522  // First time sign up attempt; No login result is found from password store;
523  // We should send the not blacklisted message.
524  EXPECT_CALL(*client.GetMockDriver(), AllowPasswordGenerationForForm(_))
525      .Times(1);
526  SimulateFetchMatchingLoginsFromPasswordStore(manager.get());
527  std::vector<PasswordForm*> result;
528  SimulateResponseFromPasswordStore(manager.get(), result);
529  Mock::VerifyAndClearExpectations(client.GetMockDriver());
530
531  // Sign up attempt to previously visited sites; Login result is found from
532  // password store, and is not blacklisted; We should send the not blacklisted
533  // message.
534  manager.reset(new PasswordFormManager(
535      &password_manager, &client, client.GetDriver(), *observed_form(), false));
536  EXPECT_CALL(*client.GetMockDriver(), AllowPasswordGenerationForForm(_))
537      .Times(1);
538  EXPECT_CALL(*client.GetMockDriver(), IsOffTheRecord())
539      .WillRepeatedly(Return(false));
540  SimulateFetchMatchingLoginsFromPasswordStore(manager.get());
541  // We need add heap allocated objects to result.
542  result.push_back(CreateSavedMatch(false));
543  SimulateResponseFromPasswordStore(manager.get(), result);
544  Mock::VerifyAndClearExpectations(client.GetMockDriver());
545
546  // Sign up attempt to previously visited sites; Login result is found from
547  // password store, but is blacklisted; We should not send the not blacklisted
548  // message.
549  manager.reset(new PasswordFormManager(
550      &password_manager, &client, client.GetDriver(), *observed_form(), false));
551  EXPECT_CALL(*client.GetMockDriver(), AllowPasswordGenerationForForm(_))
552      .Times(0);
553  SimulateFetchMatchingLoginsFromPasswordStore(manager.get());
554  result.clear();
555  result.push_back(CreateSavedMatch(true));
556  SimulateResponseFromPasswordStore(manager.get(), result);
557  Mock::VerifyAndClearExpectations(client.GetMockDriver());
558}
559
560TEST_F(PasswordFormManagerTest, TestForceInclusionOfGeneratedPasswords) {
561  base::MessageLoop message_loop;
562
563  TestPasswordManagerClient client(NULL);
564  TestPasswordManager password_manager(&client);
565  scoped_ptr<PasswordFormManager> manager(new PasswordFormManager(
566      &password_manager, &client, client.GetDriver(), *observed_form(), false));
567  EXPECT_CALL(*client.GetMockDriver(), AllowPasswordGenerationForForm(_))
568      .Times(1);
569  EXPECT_CALL(*client.GetMockDriver(), IsOffTheRecord())
570      .WillRepeatedly(Return(false));
571
572  // Simulate having two matches for this origin, one of which was from a form
573  // with different HTML tags for elements. Because of scoring differences,
574  // only the first form will be sent to Autofill().
575  std::vector<PasswordForm*> results;
576  results.push_back(CreateSavedMatch(false));
577  results.push_back(CreateSavedMatch(false));
578  results[1]->username_value = ASCIIToUTF16("other@gmail.com");
579  results[1]->password_element = ASCIIToUTF16("signup_password");
580  results[1]->username_element = ASCIIToUTF16("signup_username");
581  SimulateFetchMatchingLoginsFromPasswordStore(manager.get());
582  SimulateResponseFromPasswordStore(manager.get(), results);
583  EXPECT_EQ(1u, password_manager.GetLatestBestMatches().size());
584  results.clear();
585
586  // Same thing, except this time the credentials that don't match quite as
587  // well are generated. They should now be sent to Autofill().
588  manager.reset(new PasswordFormManager(
589      &password_manager, &client, client.GetDriver(), *observed_form(), false));
590  EXPECT_CALL(*client.GetMockDriver(), AllowPasswordGenerationForForm(_))
591      .Times(1);
592
593  results.push_back(CreateSavedMatch(false));
594  results.push_back(CreateSavedMatch(false));
595  results[1]->username_value = ASCIIToUTF16("other@gmail.com");
596  results[1]->password_element = ASCIIToUTF16("signup_password");
597  results[1]->username_element = ASCIIToUTF16("signup_username");
598  results[1]->type = PasswordForm::TYPE_GENERATED;
599  SimulateFetchMatchingLoginsFromPasswordStore(manager.get());
600  SimulateResponseFromPasswordStore(manager.get(), results);
601  EXPECT_EQ(2u, password_manager.GetLatestBestMatches().size());
602}
603
604TEST_F(PasswordFormManagerTest, TestSanitizePossibleUsernames) {
605  scoped_ptr<TestPasswordManagerClient> client(
606      new TestPasswordManagerClient(NULL));
607  scoped_ptr<MockPasswordManagerDriver> driver;
608  scoped_ptr<PasswordFormManager> manager(new PasswordFormManager(
609      NULL, client.get(), driver.get(), *observed_form(), false));
610  PasswordForm credentials(*observed_form());
611  credentials.other_possible_usernames.push_back(ASCIIToUTF16("543-43-1234"));
612  credentials.other_possible_usernames.push_back(
613      ASCIIToUTF16("378282246310005"));
614  credentials.other_possible_usernames.push_back(
615      ASCIIToUTF16("other username"));
616  credentials.username_value = ASCIIToUTF16("test@gmail.com");
617
618  SanitizePossibleUsernames(manager.get(), &credentials);
619
620  // Possible credit card number and SSN are stripped.
621  std::vector<base::string16> expected;
622  expected.push_back(ASCIIToUTF16("other username"));
623  EXPECT_THAT(credentials.other_possible_usernames, Eq(expected));
624
625  credentials.other_possible_usernames.clear();
626  credentials.other_possible_usernames.push_back(ASCIIToUTF16("511-32-9830"));
627  credentials.other_possible_usernames.push_back(ASCIIToUTF16("duplicate"));
628  credentials.other_possible_usernames.push_back(ASCIIToUTF16("duplicate"));
629  credentials.other_possible_usernames.push_back(ASCIIToUTF16("random"));
630  credentials.other_possible_usernames.push_back(
631      ASCIIToUTF16("test@gmail.com"));
632
633  SanitizePossibleUsernames(manager.get(), &credentials);
634
635  // SSN, duplicate in |other_possible_usernames| and duplicate of
636  // |username_value| all removed.
637  expected.clear();
638  expected.push_back(ASCIIToUTF16("duplicate"));
639  expected.push_back(ASCIIToUTF16("random"));
640  EXPECT_THAT(credentials.other_possible_usernames, Eq(expected));
641}
642
643TEST_F(PasswordFormManagerTest, TestUpdateIncompleteCredentials) {
644  InitializeMockStore();
645
646  // We've found this form on a website:
647  PasswordForm encountered_form;
648  encountered_form.origin = GURL("http://accounts.google.com/LoginAuth");
649  encountered_form.signon_realm = "http://accounts.google.com/";
650  encountered_form.action = GURL("http://accounts.google.com/Login");
651  encountered_form.username_element = ASCIIToUTF16("Email");
652  encountered_form.password_element = ASCIIToUTF16("Passwd");
653  encountered_form.submit_element = ASCIIToUTF16("signIn");
654
655  TestPasswordManagerClient client(mock_store());
656  MockPasswordManagerDriver driver;
657  EXPECT_CALL(driver, IsOffTheRecord()).WillRepeatedly(Return(false));
658  EXPECT_CALL(driver, AllowPasswordGenerationForForm(_));
659
660  TestPasswordManager manager(&client);
661  PasswordFormManager form_manager(
662      &manager, &client, &driver, encountered_form, false);
663
664  const PasswordStore::AuthorizationPromptPolicy auth_policy =
665      PasswordStore::DISALLOW_PROMPT;
666  EXPECT_CALL(*mock_store(),
667              GetLogins(encountered_form, auth_policy, &form_manager));
668  form_manager.FetchMatchingLoginsFromPasswordStore(auth_policy);
669
670  // Password store only has these incomplete credentials.
671  PasswordForm* incomplete_form = new PasswordForm();
672  incomplete_form->origin = GURL("http://accounts.google.com/LoginAuth");
673  incomplete_form->signon_realm = "http://accounts.google.com/";
674  incomplete_form->password_value = ASCIIToUTF16("my_password");
675  incomplete_form->username_value = ASCIIToUTF16("my_username");
676  incomplete_form->preferred = true;
677  incomplete_form->ssl_valid = false;
678  incomplete_form->scheme = PasswordForm::SCHEME_HTML;
679
680  // We expect to see this form eventually sent to the Password store. It
681  // has password/username values from the store and 'username_element',
682  // 'password_element', 'submit_element' and 'action' fields copied from
683  // the encountered form.
684  PasswordForm complete_form(*incomplete_form);
685  complete_form.action = encountered_form.action;
686  complete_form.password_element = encountered_form.password_element;
687  complete_form.username_element = encountered_form.username_element;
688  complete_form.submit_element = encountered_form.submit_element;
689
690  PasswordForm obsolete_form(*incomplete_form);
691  obsolete_form.action = encountered_form.action;
692
693  // Feed the incomplete credentials to the manager.
694  std::vector<PasswordForm*> results;
695  results.push_back(incomplete_form);  // Takes ownership.
696  form_manager.OnRequestDone(results);
697
698  form_manager.ProvisionallySave(
699      complete_form, PasswordFormManager::IGNORE_OTHER_POSSIBLE_USERNAMES);
700  // By now that form has been used once.
701  complete_form.times_used = 1;
702  obsolete_form.times_used = 1;
703
704  // Check that PasswordStore receives an update request with the complete form.
705  EXPECT_CALL(*mock_store(), RemoveLogin(obsolete_form));
706  EXPECT_CALL(*mock_store(), AddLogin(complete_form));
707  form_manager.Save();
708}
709
710TEST_F(PasswordFormManagerTest, TestScoringPublicSuffixMatch) {
711  base::MessageLoop message_loop;
712
713  TestPasswordManagerClient client(NULL);
714  MockPasswordManagerDriver driver;
715  EXPECT_CALL(driver, IsOffTheRecord()).WillRepeatedly(Return(false));
716  EXPECT_CALL(driver, AllowPasswordGenerationForForm(_));
717
718  TestPasswordManager password_manager(&client);
719  scoped_ptr<PasswordFormManager> manager(new PasswordFormManager(
720    &password_manager, &client, &driver, *observed_form(), false));
721
722  // Simulate having two matches for this form, first comes from different
723  // signon realm, but reports the same origin and action as matched form.
724  // Second candidate has the same signon realm as the form, but has a different
725  // origin and action. Public suffix match is the most important criterion so
726  // the second candidate should be selected.
727  std::vector<PasswordForm*> results;
728  results.push_back(CreateSavedMatch(false));
729  results.push_back(CreateSavedMatch(false));
730  results[0]->original_signon_realm = "http://accounts2.google.com";
731  results[1]->origin = GURL("http://accounts.google.com/a/ServiceLoginAuth2");
732  results[1]->action = GURL("http://accounts.google.com/a/ServiceLogin2");
733  SimulateFetchMatchingLoginsFromPasswordStore(manager.get());
734  SimulateResponseFromPasswordStore(manager.get(), results);
735  EXPECT_EQ(1u, password_manager.GetLatestBestMatches().size());
736  EXPECT_EQ("", password_manager.GetLatestBestMatches().begin()
737      ->second->original_signon_realm);
738}
739
740}  // namespace password_manager
741