password_form_manager_unittest.cc revision 010d83a9304c5a91596085d917d248abff47903a
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
384  password_store->AddLogin(*saved_match());
385  manager->FetchMatchingLoginsFromPasswordStore(PasswordStore::ALLOW_PROMPT);
386  RunAllPendingTasks();
387
388  // The saved match has the right username already.
389  PasswordForm login(*observed_form());
390  login.username_value = saved_match()->username_value;
391  login.password_value = saved_match()->password_value;
392  login.preferred = true;
393  manager->ProvisionallySave(
394      login, PasswordFormManager::ALLOW_OTHER_POSSIBLE_USERNAMES);
395
396  EXPECT_FALSE(manager->IsNewLogin());
397  manager->Save();
398  RunAllPendingTasks();
399
400  // Should be only one password stored, and should not have
401  // |other_possible_usernames| set anymore.
402  TestPasswordStore::PasswordMap passwords = password_store->stored_passwords();
403  EXPECT_EQ(1U, passwords.size());
404  ASSERT_EQ(1U, passwords[saved_match()->signon_realm].size());
405  EXPECT_EQ(saved_match()->username_value,
406            passwords[saved_match()->signon_realm][0].username_value);
407  EXPECT_EQ(0U,
408            passwords[saved_match()->signon_realm][0]
409                .other_possible_usernames.size());
410
411  // This time use an alternate username
412  manager.reset(new PasswordFormManager(
413      &password_manager, &client, client.GetDriver(), *observed_form(), false));
414  password_store->Clear();
415  password_store->AddLogin(*saved_match());
416  manager->FetchMatchingLoginsFromPasswordStore(PasswordStore::ALLOW_PROMPT);
417  RunAllPendingTasks();
418
419  base::string16 new_username = saved_match()->other_possible_usernames[0];
420  login.username_value = new_username;
421  manager->ProvisionallySave(
422      login, PasswordFormManager::ALLOW_OTHER_POSSIBLE_USERNAMES);
423
424  EXPECT_FALSE(manager->IsNewLogin());
425  manager->Save();
426  RunAllPendingTasks();
427
428  // |other_possible_usernames| should also be empty, but username_value should
429  // be changed to match |new_username|
430  passwords = password_store->stored_passwords();
431  EXPECT_EQ(1U, passwords.size());
432  ASSERT_EQ(1U, passwords[saved_match()->signon_realm].size());
433  EXPECT_EQ(new_username,
434            passwords[saved_match()->signon_realm][0].username_value);
435  EXPECT_EQ(0U,
436            passwords[saved_match()->signon_realm][0]
437                .other_possible_usernames.size());
438  password_store->Shutdown();
439}
440
441TEST_F(PasswordFormManagerTest, TestValidForms) {
442  // User submits credentials for the observed form.
443  PasswordForm credentials = *observed_form();
444  credentials.scheme = PasswordForm::SCHEME_HTML;
445  credentials.username_value = saved_match()->username_value;
446  credentials.password_value = saved_match()->password_value;
447
448  // Form with both username_element and password_element.
449  PasswordFormManager manager1(NULL, NULL, NULL, credentials, false);
450  SimulateMatchingPhase(&manager1, false);
451  EXPECT_TRUE(manager1.HasValidPasswordForm());
452
453  // Form without a username_element but with a password_element.
454  credentials.username_element.clear();
455  PasswordFormManager manager2(NULL, NULL, NULL, credentials, false);
456  SimulateMatchingPhase(&manager2, false);
457  EXPECT_FALSE(manager2.HasValidPasswordForm());
458
459  // Form without a password_element but with a username_element.
460  credentials.username_element = saved_match()->username_element;
461  credentials.password_element.clear();
462  PasswordFormManager manager3(NULL, NULL, NULL, credentials, false);
463  SimulateMatchingPhase(&manager3, false);
464  EXPECT_FALSE(manager3.HasValidPasswordForm());
465
466  // Form with neither a password_element nor a username_element.
467  credentials.username_element.clear();
468  credentials.password_element.clear();
469  PasswordFormManager manager4(NULL, NULL, NULL, credentials, false);
470  SimulateMatchingPhase(&manager4, false);
471  EXPECT_FALSE(manager4.HasValidPasswordForm());
472}
473
474TEST_F(PasswordFormManagerTest, TestValidFormsBasic) {
475  // User submits credentials for the observed form.
476  PasswordForm credentials = *observed_form();
477  credentials.scheme = PasswordForm::SCHEME_BASIC;
478  credentials.username_value = saved_match()->username_value;
479  credentials.password_value = saved_match()->password_value;
480
481  // Form with both username_element and password_element.
482  PasswordFormManager manager1(NULL, NULL, NULL, credentials, false);
483  SimulateMatchingPhase(&manager1, false);
484  EXPECT_TRUE(manager1.HasValidPasswordForm());
485
486  // Form without a username_element but with a password_element.
487  credentials.username_element.clear();
488  PasswordFormManager manager2(NULL, NULL, NULL, credentials, false);
489  SimulateMatchingPhase(&manager2, false);
490  EXPECT_TRUE(manager2.HasValidPasswordForm());
491
492  // Form without a password_element but with a username_element.
493  credentials.username_element = saved_match()->username_element;
494  credentials.password_element.clear();
495  PasswordFormManager manager3(NULL, NULL, NULL, credentials, false);
496  SimulateMatchingPhase(&manager3, false);
497  EXPECT_TRUE(manager3.HasValidPasswordForm());
498
499  // Form with neither a password_element nor a username_element.
500  credentials.username_element.clear();
501  credentials.password_element.clear();
502  PasswordFormManager manager4(NULL, NULL, NULL, credentials, false);
503  SimulateMatchingPhase(&manager4, false);
504  EXPECT_TRUE(manager4.HasValidPasswordForm());
505}
506
507TEST_F(PasswordFormManagerTest, TestSendNotBlacklistedMessage) {
508  base::MessageLoop message_loop;
509
510  // A dumb password manager.
511  TestPasswordManagerClient client(NULL);
512  TestPasswordManager password_manager(&client);
513  scoped_ptr<PasswordFormManager> manager(new PasswordFormManager(
514      &password_manager, &client, client.GetDriver(), *observed_form(), false));
515
516  // First time sign up attempt; No login result is found from password store;
517  // We should send the not blacklisted message.
518  EXPECT_CALL(*client.GetMockDriver(), AllowPasswordGenerationForForm(_))
519      .Times(1);
520  SimulateFetchMatchingLoginsFromPasswordStore(manager.get());
521  std::vector<PasswordForm*> result;
522  SimulateResponseFromPasswordStore(manager.get(), result);
523  Mock::VerifyAndClearExpectations(client.GetMockDriver());
524
525  // Sign up attempt to previously visited sites; Login result is found from
526  // password store, and is not blacklisted; We should send the not blacklisted
527  // message.
528  manager.reset(new PasswordFormManager(
529      &password_manager, &client, client.GetDriver(), *observed_form(), false));
530  EXPECT_CALL(*client.GetMockDriver(), AllowPasswordGenerationForForm(_))
531      .Times(1);
532  SimulateFetchMatchingLoginsFromPasswordStore(manager.get());
533  // We need add heap allocated objects to result.
534  result.push_back(CreateSavedMatch(false));
535  SimulateResponseFromPasswordStore(manager.get(), result);
536  Mock::VerifyAndClearExpectations(client.GetMockDriver());
537
538  // Sign up attempt to previously visited sites; Login result is found from
539  // password store, but is blacklisted; We should not send the not blacklisted
540  // message.
541  manager.reset(new PasswordFormManager(
542      &password_manager, &client, client.GetDriver(), *observed_form(), false));
543  EXPECT_CALL(*client.GetMockDriver(), AllowPasswordGenerationForForm(_))
544      .Times(0);
545  SimulateFetchMatchingLoginsFromPasswordStore(manager.get());
546  result.clear();
547  result.push_back(CreateSavedMatch(true));
548  SimulateResponseFromPasswordStore(manager.get(), result);
549  Mock::VerifyAndClearExpectations(client.GetMockDriver());
550}
551
552TEST_F(PasswordFormManagerTest, TestForceInclusionOfGeneratedPasswords) {
553  base::MessageLoop message_loop;
554
555  TestPasswordManagerClient client(NULL);
556  TestPasswordManager password_manager(&client);
557  scoped_ptr<PasswordFormManager> manager(new PasswordFormManager(
558      &password_manager, &client, client.GetDriver(), *observed_form(), false));
559
560  // Simulate having two matches for this origin, one of which was from a form
561  // with different HTML tags for elements. Because of scoring differences,
562  // only the first form will be sent to Autofill().
563  std::vector<PasswordForm*> results;
564  results.push_back(CreateSavedMatch(false));
565  results.push_back(CreateSavedMatch(false));
566  results[1]->username_value = ASCIIToUTF16("other@gmail.com");
567  results[1]->password_element = ASCIIToUTF16("signup_password");
568  results[1]->username_element = ASCIIToUTF16("signup_username");
569  SimulateFetchMatchingLoginsFromPasswordStore(manager.get());
570  SimulateResponseFromPasswordStore(manager.get(), results);
571  EXPECT_EQ(1u, password_manager.GetLatestBestMatches().size());
572  results.clear();
573
574  // Same thing, except this time the credentials that don't match quite as
575  // well are generated. They should now be sent to Autofill().
576  manager.reset(new PasswordFormManager(
577      &password_manager, &client, client.GetDriver(), *observed_form(), false));
578  results.push_back(CreateSavedMatch(false));
579  results.push_back(CreateSavedMatch(false));
580  results[1]->username_value = ASCIIToUTF16("other@gmail.com");
581  results[1]->password_element = ASCIIToUTF16("signup_password");
582  results[1]->username_element = ASCIIToUTF16("signup_username");
583  results[1]->type = PasswordForm::TYPE_GENERATED;
584  SimulateFetchMatchingLoginsFromPasswordStore(manager.get());
585  SimulateResponseFromPasswordStore(manager.get(), results);
586  EXPECT_EQ(2u, password_manager.GetLatestBestMatches().size());
587}
588
589TEST_F(PasswordFormManagerTest, TestSanitizePossibleUsernames) {
590  scoped_ptr<TestPasswordManagerClient> client(
591      new TestPasswordManagerClient(NULL));
592  scoped_ptr<MockPasswordManagerDriver> driver;
593  scoped_ptr<PasswordFormManager> manager(new PasswordFormManager(
594      NULL, client.get(), driver.get(), *observed_form(), false));
595  PasswordForm credentials(*observed_form());
596  credentials.other_possible_usernames.push_back(ASCIIToUTF16("543-43-1234"));
597  credentials.other_possible_usernames.push_back(
598      ASCIIToUTF16("378282246310005"));
599  credentials.other_possible_usernames.push_back(
600      ASCIIToUTF16("other username"));
601  credentials.username_value = ASCIIToUTF16("test@gmail.com");
602
603  SanitizePossibleUsernames(manager.get(), &credentials);
604
605  // Possible credit card number and SSN are stripped.
606  std::vector<base::string16> expected;
607  expected.push_back(ASCIIToUTF16("other username"));
608  EXPECT_THAT(credentials.other_possible_usernames, Eq(expected));
609
610  credentials.other_possible_usernames.clear();
611  credentials.other_possible_usernames.push_back(ASCIIToUTF16("511-32-9830"));
612  credentials.other_possible_usernames.push_back(ASCIIToUTF16("duplicate"));
613  credentials.other_possible_usernames.push_back(ASCIIToUTF16("duplicate"));
614  credentials.other_possible_usernames.push_back(ASCIIToUTF16("random"));
615  credentials.other_possible_usernames.push_back(
616      ASCIIToUTF16("test@gmail.com"));
617
618  SanitizePossibleUsernames(manager.get(), &credentials);
619
620  // SSN, duplicate in |other_possible_usernames| and duplicate of
621  // |username_value| all removed.
622  expected.clear();
623  expected.push_back(ASCIIToUTF16("duplicate"));
624  expected.push_back(ASCIIToUTF16("random"));
625  EXPECT_THAT(credentials.other_possible_usernames, Eq(expected));
626}
627
628TEST_F(PasswordFormManagerTest, TestUpdateIncompleteCredentials) {
629  InitializeMockStore();
630
631  // We've found this form on a website:
632  PasswordForm encountered_form;
633  encountered_form.origin = GURL("http://accounts.google.com/LoginAuth");
634  encountered_form.signon_realm = "http://accounts.google.com/";
635  encountered_form.action = GURL("http://accounts.google.com/Login");
636  encountered_form.username_element = ASCIIToUTF16("Email");
637  encountered_form.password_element = ASCIIToUTF16("Passwd");
638  encountered_form.submit_element = ASCIIToUTF16("signIn");
639
640  TestPasswordManagerClient client(mock_store());
641  MockPasswordManagerDriver driver;
642  EXPECT_CALL(driver, IsOffTheRecord()).WillRepeatedly(Return(false));
643  EXPECT_CALL(driver, AllowPasswordGenerationForForm(_));
644
645  TestPasswordManager manager(&client);
646  PasswordFormManager form_manager(
647      &manager, &client, &driver, encountered_form, false);
648
649  const PasswordStore::AuthorizationPromptPolicy auth_policy =
650      PasswordStore::DISALLOW_PROMPT;
651  EXPECT_CALL(*mock_store(),
652              GetLogins(encountered_form, auth_policy, &form_manager));
653  form_manager.FetchMatchingLoginsFromPasswordStore(auth_policy);
654
655  // Password store only has these incomplete credentials.
656  PasswordForm* incomplete_form = new PasswordForm();
657  incomplete_form->origin = GURL("http://accounts.google.com/LoginAuth");
658  incomplete_form->signon_realm = "http://accounts.google.com/";
659  incomplete_form->password_value = ASCIIToUTF16("my_password");
660  incomplete_form->username_value = ASCIIToUTF16("my_username");
661  incomplete_form->preferred = true;
662  incomplete_form->ssl_valid = false;
663  incomplete_form->scheme = PasswordForm::SCHEME_HTML;
664
665  // We expect to see this form eventually sent to the Password store. It
666  // has password/username values from the store and 'username_element',
667  // 'password_element', 'submit_element' and 'action' fields copied from
668  // the encountered form.
669  PasswordForm complete_form(*incomplete_form);
670  complete_form.action = encountered_form.action;
671  complete_form.password_element = encountered_form.password_element;
672  complete_form.username_element = encountered_form.username_element;
673  complete_form.submit_element = encountered_form.submit_element;
674
675  // Feed the incomplete credentials to the manager.
676  std::vector<PasswordForm*> results;
677  results.push_back(incomplete_form);  // Takes ownership.
678  form_manager.OnRequestDone(results);
679
680  form_manager.ProvisionallySave(
681      complete_form, PasswordFormManager::IGNORE_OTHER_POSSIBLE_USERNAMES);
682  // By now that form has been used once.
683  complete_form.times_used = 1;
684
685  // Check that PasswordStore receives an update request with the complete form.
686  EXPECT_CALL(*mock_store(), UpdateLogin(complete_form));
687  form_manager.Save();
688}
689
690TEST_F(PasswordFormManagerTest, TestScoringPublicSuffixMatch) {
691  base::MessageLoop message_loop;
692
693  TestPasswordManagerClient client(NULL);
694  MockPasswordManagerDriver driver;
695  EXPECT_CALL(driver, IsOffTheRecord()).WillRepeatedly(Return(false));
696  EXPECT_CALL(driver, AllowPasswordGenerationForForm(_));
697
698  TestPasswordManager password_manager(&client);
699  scoped_ptr<PasswordFormManager> manager(new PasswordFormManager(
700    &password_manager, &client, &driver, *observed_form(), false));
701
702  // Simulate having two matches for this form, first comes from different
703  // signon realm, but reports the same origin and action as matched form.
704  // Second candidate has the same signon realm as the form, but has a different
705  // origin and action. Public suffix match is the most important criterion so
706  // the second candidate should be selected.
707  std::vector<PasswordForm*> results;
708  results.push_back(CreateSavedMatch(false));
709  results.push_back(CreateSavedMatch(false));
710  results[0]->original_signon_realm = "http://accounts2.google.com";
711  results[1]->origin = GURL("http://accounts.google.com/a/ServiceLoginAuth2");
712  results[1]->action = GURL("http://accounts.google.com/a/ServiceLogin2");
713  SimulateFetchMatchingLoginsFromPasswordStore(manager.get());
714  SimulateResponseFromPasswordStore(manager.get(), results);
715  EXPECT_EQ(1u, password_manager.GetLatestBestMatches().size());
716  EXPECT_EQ("", password_manager.GetLatestBestMatches().begin()
717      ->second->original_signon_realm);
718}
719
720}  // namespace password_manager
721