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