| 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 |