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