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
26 using autofill::PasswordForm;
27 using base::ASCIIToUTF16;
28 using ::testing::_;
29 using ::testing::Eq;
30 using ::testing::Mock;
31 using ::testing::Return;
32
33 namespace autofill {
34 class AutofillManager;
35 }
36
37 namespace password_manager {
38
39 namespace {
40
RunAllPendingTasks()41 void RunAllPendingTasks() {
42 base::RunLoop run_loop;
43 base::MessageLoop::current()->PostTask(
44 FROM_HERE, base::MessageLoop::QuitWhenIdleClosure());
45 run_loop.Run();
46 }
47
48 class MockPasswordManagerDriver : public StubPasswordManagerDriver {
49 public:
50 MOCK_METHOD0(IsOffTheRecord, bool());
51 MOCK_METHOD1(AllowPasswordGenerationForForm, void(autofill::PasswordForm*));
52 };
53
54 class TestPasswordManagerClient : public StubPasswordManagerClient {
55 public:
TestPasswordManagerClient(PasswordStore * password_store)56 explicit TestPasswordManagerClient(PasswordStore* password_store)
57 : password_store_(password_store) {
58 prefs_.registry()->RegisterBooleanPref(prefs::kPasswordManagerEnabled,
59 true);
60 }
61
PromptUserToSavePassword(PasswordFormManager * form_to_save)62 virtual void PromptUserToSavePassword(PasswordFormManager* form_to_save)
63 OVERRIDE {}
GetPrefs()64 virtual PrefService* GetPrefs() OVERRIDE { return &prefs_; }
GetPasswordStore()65 virtual PasswordStore* GetPasswordStore() OVERRIDE { return password_store_; }
GetDriver()66 virtual PasswordManagerDriver* GetDriver() OVERRIDE { return &driver_; }
AuthenticateAutofillAndFillForm(scoped_ptr<autofill::PasswordFormFillData> fill_data)67 virtual void AuthenticateAutofillAndFillForm(
68 scoped_ptr<autofill::PasswordFormFillData> fill_data) OVERRIDE {
69 driver_.FillPasswordForm(*fill_data.get());
70 }
71
GetMockDriver()72 MockPasswordManagerDriver* GetMockDriver() { return &driver_; }
73
74 private:
75 TestingPrefServiceSimple prefs_;
76 PasswordStore* password_store_;
77 MockPasswordManagerDriver driver_;
78 };
79
80 class TestPasswordManager : public PasswordManager {
81 public:
TestPasswordManager(PasswordManagerClient * client)82 explicit TestPasswordManager(PasswordManagerClient* client)
83 : PasswordManager(client) {}
84
Autofill(const autofill::PasswordForm & form_for_autofill,const autofill::PasswordFormMap & best_matches,const autofill::PasswordForm & preferred_match,bool wait_for_username) const85 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
GetLatestBestMatches()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
103 class PasswordFormManagerTest : public testing::Test {
104 public:
PasswordFormManagerTest()105 PasswordFormManagerTest() {}
106
SetUp()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
TearDown()125 virtual void TearDown() {
126 if (mock_store_)
127 mock_store_->Shutdown();
128 }
129
InitializeMockStore()130 void InitializeMockStore() {
131 if (!mock_store_) {
132 mock_store_ = new MockPasswordStore();
133 ASSERT_TRUE(mock_store_);
134 }
135 }
136
mock_store() const137 MockPasswordStore* mock_store() const { return mock_store_.get(); }
138
GetPendingCredentials(PasswordFormManager * p)139 PasswordForm* GetPendingCredentials(PasswordFormManager* p) {
140 return &p->pending_credentials_;
141 }
142
SimulateMatchingPhase(PasswordFormManager * p,bool find_match)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
SimulateFetchMatchingLoginsFromPasswordStore(PasswordFormManager * manager)155 void SimulateFetchMatchingLoginsFromPasswordStore(
156 PasswordFormManager* manager) {
157 // Just need to update the internal states.
158 manager->state_ = PasswordFormManager::MATCHING_PHASE;
159 }
160
SimulateResponseFromPasswordStore(PasswordFormManager * manager,const std::vector<PasswordForm * > & result)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
SanitizePossibleUsernames(PasswordFormManager * p,PasswordForm * form)169 void SanitizePossibleUsernames(PasswordFormManager* p, PasswordForm* form) {
170 p->SanitizePossibleUsernames(form);
171 }
172
IgnoredResult(PasswordFormManager * p,PasswordForm * form)173 bool IgnoredResult(PasswordFormManager* p, PasswordForm* form) {
174 return p->IgnoreResult(*form);
175 }
176
observed_form()177 PasswordForm* observed_form() { return &observed_form_; }
saved_match()178 PasswordForm* saved_match() { return &saved_match_; }
CreateSavedMatch(bool blacklisted)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
TEST_F(PasswordFormManagerTest,TestNewLogin)192 TEST_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
TEST_F(PasswordFormManagerTest,TestUpdatePassword)249 TEST_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
TEST_F(PasswordFormManagerTest,TestIgnoreResult)291 TEST_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
TEST_F(PasswordFormManagerTest,TestEmptyAction)313 TEST_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
TEST_F(PasswordFormManagerTest,TestUpdateAction)335 TEST_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
TEST_F(PasswordFormManagerTest,TestDynamicAction)358 TEST_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
TEST_F(PasswordFormManagerTest,TestAlternateUsername)379 TEST_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
TEST_F(PasswordFormManagerTest,TestValidForms)453 TEST_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
TEST_F(PasswordFormManagerTest,TestValidFormsBasic)486 TEST_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
TEST_F(PasswordFormManagerTest,TestSendNotBlacklistedMessage)519 TEST_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
TEST_F(PasswordFormManagerTest,TestForceInclusionOfGeneratedPasswords)566 TEST_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
TEST_F(PasswordFormManagerTest,TestSanitizePossibleUsernames)610 TEST_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
TEST_F(PasswordFormManagerTest,TestUpdateIncompleteCredentials)649 TEST_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
TEST_F(PasswordFormManagerTest,TestScoringPublicSuffixMatch)716 TEST_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