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