Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "components/password_manager/core/browser/password_form_manager.h" | 5 #include "components/password_manager/core/browser/password_form_manager.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <set> | 8 #include <set> |
| 9 | 9 |
| 10 #include "base/metrics/histogram.h" | 10 #include "base/metrics/histogram.h" |
| (...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 225 bool PasswordFormManager::HasValidPasswordForm() const { | 225 bool PasswordFormManager::HasValidPasswordForm() const { |
| 226 DCHECK_EQ(state_, POST_MATCHING_PHASE); | 226 DCHECK_EQ(state_, POST_MATCHING_PHASE); |
| 227 // Non-HTML password forms (primarily HTTP and FTP autentication) | 227 // Non-HTML password forms (primarily HTTP and FTP autentication) |
| 228 // do not contain username_element and password_element values. | 228 // do not contain username_element and password_element values. |
| 229 if (observed_form_.scheme != PasswordForm::SCHEME_HTML) | 229 if (observed_form_.scheme != PasswordForm::SCHEME_HTML) |
| 230 return true; | 230 return true; |
| 231 return !observed_form_.password_element.empty() || | 231 return !observed_form_.password_element.empty() || |
| 232 !observed_form_.new_password_element.empty(); | 232 !observed_form_.new_password_element.empty(); |
| 233 } | 233 } |
| 234 | 234 |
| 235 void PasswordFormManager::ProvisionallySave( | 235 bool PasswordFormManager::ProvisionallySave( |
| 236 const PasswordForm& credentials, | 236 const PasswordForm& credentials, |
| 237 OtherPossibleUsernamesAction action) { | 237 OtherPossibleUsernamesAction action) { |
| 238 DCHECK_EQ(state_, POST_MATCHING_PHASE); | 238 DCHECK_EQ(state_, POST_MATCHING_PHASE); |
| 239 DCHECK_NE(RESULT_NO_MATCH, DoesManage(credentials)); | 239 DCHECK_NE(RESULT_NO_MATCH, DoesManage(credentials)); |
| 240 | 240 |
| 241 // If this was a sign-up or change password form, we want to persist the new | 241 // If this was a sign-up or change password form, we want to persist the new |
| 242 // password; if this was a login form, then the current password (which might | 242 // password; if this was a login form, then the current password (which might |
| 243 // still be "new" in the sense that we see these credentials for the first | 243 // still be "new" in the sense that we see these credentials for the first |
| 244 // time, or that the user manually entered his actual password to overwrite an | 244 // time, or that the user manually entered his actual password to overwrite an |
| 245 // obsolete password we had in the store). | 245 // obsolete password we had in the store). |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 296 // infrequently, and the inconvenience put on the user by asking them is | 296 // infrequently, and the inconvenience put on the user by asking them is |
| 297 // not significant, so we are fine with asking here again. | 297 // not significant, so we are fine with asking here again. |
| 298 if (password_changed) { | 298 if (password_changed) { |
| 299 pending_credentials_.original_signon_realm.clear(); | 299 pending_credentials_.original_signon_realm.clear(); |
| 300 DCHECK(!IsPendingCredentialsPublicSuffixMatch()); | 300 DCHECK(!IsPendingCredentialsPublicSuffixMatch()); |
| 301 } | 301 } |
| 302 } else { // Not a PSL match. | 302 } else { // Not a PSL match. |
| 303 is_new_login_ = false; | 303 is_new_login_ = false; |
| 304 if (password_changed) | 304 if (password_changed) |
| 305 user_action_ = kUserActionOverridePassword; | 305 user_action_ = kUserActionOverridePassword; |
| 306 | |
| 307 // For ignorable change-password form, bail out early if usernames are | |
|
vabr (Chromium)
2015/02/06 16:27:07
Why should change password forms not be ignored in
Pritam Nikam
2015/02/09 15:48:17
Done.
| |
| 308 // matching but passwords are not matching. | |
| 309 if (IsIgnorableChangePasswordForm() && | |
| 310 pending_credentials_.password_value != credentials.password_value) { | |
| 311 return false; | |
| 312 } | |
| 306 } | 313 } |
| 307 } else if (action == ALLOW_OTHER_POSSIBLE_USERNAMES && | 314 } else if (action == ALLOW_OTHER_POSSIBLE_USERNAMES && |
| 308 UpdatePendingCredentialsIfOtherPossibleUsername( | 315 UpdatePendingCredentialsIfOtherPossibleUsername( |
| 309 credentials.username_value)) { | 316 credentials.username_value)) { |
| 310 // |pending_credentials_| is now set. Note we don't update | 317 // |pending_credentials_| is now set. Note we don't update |
| 311 // |pending_credentials_.username_value| to |credentials.username_value| | 318 // |pending_credentials_.username_value| to |credentials.username_value| |
| 312 // yet because we need to keep the original username to modify the stored | 319 // yet because we need to keep the original username to modify the stored |
| 313 // credential. | 320 // credential. |
| 314 selected_username_ = credentials.username_value; | 321 selected_username_ = credentials.username_value; |
| 315 is_new_login_ = false; | 322 is_new_login_ = false; |
| 316 } else { | 323 } else { |
| 317 // User typed in a new, unknown username. | 324 // User typed in a new, unknown username. |
| 325 // For ignorable change-password form, bail out early if usernames are not | |
| 326 // matching. | |
| 327 if (IsIgnorableChangePasswordForm()) | |
| 328 return false; | |
| 329 | |
| 318 user_action_ = kUserActionOverrideUsernameAndPassword; | 330 user_action_ = kUserActionOverrideUsernameAndPassword; |
| 319 pending_credentials_ = observed_form_; | 331 pending_credentials_ = observed_form_; |
| 320 pending_credentials_.username_value = credentials.username_value; | 332 pending_credentials_.username_value = credentials.username_value; |
| 321 pending_credentials_.other_possible_usernames = | 333 pending_credentials_.other_possible_usernames = |
| 322 credentials.other_possible_usernames; | 334 credentials.other_possible_usernames; |
| 323 | 335 |
| 324 // The password value will be filled in later, remove any garbage for now. | 336 // The password value will be filled in later, remove any garbage for now. |
| 325 pending_credentials_.password_value.clear(); | 337 pending_credentials_.password_value.clear(); |
| 326 pending_credentials_.new_password_value.clear(); | 338 pending_credentials_.new_password_value.clear(); |
| 327 | 339 |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 346 pending_credentials_.preferred = credentials.preferred; | 358 pending_credentials_.preferred = credentials.preferred; |
| 347 | 359 |
| 348 if (user_action_ == kUserActionOverridePassword && | 360 if (user_action_ == kUserActionOverridePassword && |
| 349 pending_credentials_.type == PasswordForm::TYPE_GENERATED && | 361 pending_credentials_.type == PasswordForm::TYPE_GENERATED && |
| 350 !has_generated_password_) { | 362 !has_generated_password_) { |
| 351 LogPasswordGenerationSubmissionEvent(PASSWORD_OVERRIDDEN); | 363 LogPasswordGenerationSubmissionEvent(PASSWORD_OVERRIDDEN); |
| 352 } | 364 } |
| 353 | 365 |
| 354 if (has_generated_password_) | 366 if (has_generated_password_) |
| 355 pending_credentials_.type = PasswordForm::TYPE_GENERATED; | 367 pending_credentials_.type = PasswordForm::TYPE_GENERATED; |
| 368 | |
| 369 return true; | |
| 356 } | 370 } |
| 357 | 371 |
| 358 void PasswordFormManager::Save() { | 372 void PasswordFormManager::Save() { |
| 359 DCHECK_EQ(state_, POST_MATCHING_PHASE); | 373 DCHECK_EQ(state_, POST_MATCHING_PHASE); |
| 360 DCHECK(!client_->IsOffTheRecord()); | 374 DCHECK(!client_->IsOffTheRecord()); |
| 361 | 375 |
| 362 if (IsNewLogin()) | 376 if (IsNewLogin()) |
| 363 SaveAsNewLogin(true); | 377 SaveAsNewLogin(true); |
| 364 else | 378 else |
| 365 UpdateLogin(); | 379 UpdateLogin(); |
| 366 } | 380 } |
| 367 | 381 |
| 368 void PasswordFormManager::FetchMatchingLoginsFromPasswordStore( | 382 void PasswordFormManager::FetchMatchingLoginsFromPasswordStore( |
| 369 PasswordStore::AuthorizationPromptPolicy prompt_policy) { | 383 PasswordStore::AuthorizationPromptPolicy prompt_policy) { |
| 370 DCHECK_EQ(state_, PRE_MATCHING_PHASE); | 384 DCHECK_EQ(state_, PRE_MATCHING_PHASE); |
| 371 state_ = MATCHING_PHASE; | 385 state_ = MATCHING_PHASE; |
| 372 | 386 |
| 373 scoped_ptr<BrowserSavePasswordProgressLogger> logger; | 387 scoped_ptr<BrowserSavePasswordProgressLogger> logger; |
| 374 if (client_->IsLoggingActive()) { | 388 if (client_->IsLoggingActive()) { |
| 375 logger.reset(new BrowserSavePasswordProgressLogger(client_)); | 389 logger.reset(new BrowserSavePasswordProgressLogger(client_)); |
| 376 logger->LogMessage(Logger::STRING_FETCH_LOGINS_METHOD); | 390 logger->LogMessage(Logger::STRING_FETCH_LOGINS_METHOD); |
| 377 } | 391 } |
| 378 | 392 |
| 379 // Do not autofill on sign-up or change password forms (until we have some | |
|
vabr (Chromium)
2015/02/06 16:27:07
The goal of http://crbug.com/448351 is not at all
Pritam Nikam
2015/02/09 15:48:17
In my opinion, this is needed to fetch stored form
| |
| 380 // working change password functionality). | |
| 381 if (!observed_form_.new_password_element.empty()) { | |
| 382 if (logger) | |
| 383 logger->LogMessage(Logger::STRING_FORM_NOT_AUTOFILLED); | |
| 384 client_->AutofillResultsComputed(); | |
| 385 // There is no point in looking for the credentials in the store when they | |
| 386 // won't be autofilled, so pretend there were none. | |
| 387 std::vector<autofill::PasswordForm*> dummy_results; | |
| 388 OnGetPasswordStoreResults(dummy_results); | |
| 389 return; | |
| 390 } | |
| 391 | |
| 392 PasswordStore* password_store = client_->GetPasswordStore(); | 393 PasswordStore* password_store = client_->GetPasswordStore(); |
| 393 if (!password_store) { | 394 if (!password_store) { |
| 394 if (logger) | 395 if (logger) |
| 395 logger->LogMessage(Logger::STRING_NO_STORE); | 396 logger->LogMessage(Logger::STRING_NO_STORE); |
| 396 NOTREACHED(); | 397 NOTREACHED(); |
| 397 return; | 398 return; |
| 398 } | 399 } |
| 399 password_store->GetLogins(observed_form_, prompt_policy, this); | 400 password_store->GetLogins(observed_form_, prompt_policy, this); |
| 400 } | 401 } |
| 401 | 402 |
| 402 bool PasswordFormManager::HasCompletedMatching() const { | 403 bool PasswordFormManager::HasCompletedMatching() const { |
| 403 return state_ == POST_MATCHING_PHASE; | 404 return state_ == POST_MATCHING_PHASE; |
| 404 } | 405 } |
| 405 | 406 |
| 406 bool PasswordFormManager::IsIgnorableChangePasswordForm() const { | |
| 407 bool is_change_password_form = !observed_form_.new_password_element.empty() && | |
| 408 !observed_form_.password_element.empty(); | |
| 409 bool is_username_certainly_correct = observed_form_.username_marked_by_site; | |
| 410 return is_change_password_form && !is_username_certainly_correct; | |
| 411 } | |
| 412 | |
| 413 void PasswordFormManager::OnRequestDone( | 407 void PasswordFormManager::OnRequestDone( |
| 414 const std::vector<PasswordForm*>& logins_result) { | 408 const std::vector<PasswordForm*>& logins_result) { |
| 415 // Note that the result gets deleted after this call completes, but we own | 409 // Note that the result gets deleted after this call completes, but we own |
| 416 // the PasswordForm objects pointed to by the result vector, thus we keep | 410 // the PasswordForm objects pointed to by the result vector, thus we keep |
| 417 // copies to a minimum here. | 411 // copies to a minimum here. |
| 418 | 412 |
| 419 scoped_ptr<BrowserSavePasswordProgressLogger> logger; | 413 scoped_ptr<BrowserSavePasswordProgressLogger> logger; |
| 420 if (client_->IsLoggingActive()) { | 414 if (client_->IsLoggingActive()) { |
| 421 logger.reset(new BrowserSavePasswordProgressLogger(client_)); | 415 logger.reset(new BrowserSavePasswordProgressLogger(client_)); |
| 422 logger->LogMessage(Logger::STRING_ON_REQUEST_DONE_METHOD); | 416 logger->LogMessage(Logger::STRING_ON_REQUEST_DONE_METHOD); |
| (...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 544 // (1) we are in Incognito mode, (2) the ACTION paths don't match, | 538 // (1) we are in Incognito mode, (2) the ACTION paths don't match, |
| 545 // or (3) if it matched using public suffix domain matching. | 539 // or (3) if it matched using public suffix domain matching. |
| 546 bool wait_for_username = client_->IsOffTheRecord() || | 540 bool wait_for_username = client_->IsOffTheRecord() || |
| 547 observed_form_.action.GetWithEmptyPath() != | 541 observed_form_.action.GetWithEmptyPath() != |
| 548 preferred_match_->action.GetWithEmptyPath() || | 542 preferred_match_->action.GetWithEmptyPath() || |
| 549 preferred_match_->IsPublicSuffixMatch(); | 543 preferred_match_->IsPublicSuffixMatch(); |
| 550 if (wait_for_username) | 544 if (wait_for_username) |
| 551 manager_action_ = kManagerActionNone; | 545 manager_action_ = kManagerActionNone; |
| 552 else | 546 else |
| 553 manager_action_ = kManagerActionAutofilled; | 547 manager_action_ = kManagerActionAutofilled; |
| 554 password_manager_->Autofill(driver.get(), observed_form_, best_matches_, | 548 |
| 555 *preferred_match_, wait_for_username); | 549 // Do not autofill on sign-up or change password forms (until we have some |
| 550 // working change password functionality). | |
| 551 if (observed_form_.new_password_element.empty()) { | |
|
vabr (Chromium)
2015/02/06 16:27:07
What's the advantage of moving the check to so lat
Pritam Nikam
2015/02/09 15:48:17
We can skip autofilling for all change-password fo
| |
| 552 password_manager_->Autofill(driver.get(), observed_form_, best_matches_, | |
| 553 *preferred_match_, wait_for_username); | |
| 554 } | |
| 556 } | 555 } |
| 557 | 556 |
| 558 void PasswordFormManager::OnGetPasswordStoreResults( | 557 void PasswordFormManager::OnGetPasswordStoreResults( |
| 559 const std::vector<autofill::PasswordForm*>& results) { | 558 const std::vector<autofill::PasswordForm*>& results) { |
| 560 DCHECK_EQ(state_, MATCHING_PHASE); | 559 DCHECK_EQ(state_, MATCHING_PHASE); |
| 561 | 560 |
| 562 scoped_ptr<BrowserSavePasswordProgressLogger> logger; | 561 scoped_ptr<BrowserSavePasswordProgressLogger> logger; |
| 563 if (client_->IsLoggingActive()) { | 562 if (client_->IsLoggingActive()) { |
| 564 logger.reset(new BrowserSavePasswordProgressLogger(client_)); | 563 logger.reset(new BrowserSavePasswordProgressLogger(client_)); |
| 565 logger->LogMessage(Logger::STRING_ON_GET_STORE_RESULTS_METHOD); | 564 logger->LogMessage(Logger::STRING_ON_GET_STORE_RESULTS_METHOD); |
| (...skipping 295 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 861 if (has_generated_password_) | 860 if (has_generated_password_) |
| 862 LogPasswordGenerationSubmissionEvent(PASSWORD_SUBMITTED); | 861 LogPasswordGenerationSubmissionEvent(PASSWORD_SUBMITTED); |
| 863 } | 862 } |
| 864 | 863 |
| 865 void PasswordFormManager::SubmitFailed() { | 864 void PasswordFormManager::SubmitFailed() { |
| 866 submit_result_ = kSubmitResultFailed; | 865 submit_result_ = kSubmitResultFailed; |
| 867 if (has_generated_password_) | 866 if (has_generated_password_) |
| 868 LogPasswordGenerationSubmissionEvent(PASSWORD_SUBMISSION_FAILED); | 867 LogPasswordGenerationSubmissionEvent(PASSWORD_SUBMISSION_FAILED); |
| 869 } | 868 } |
| 870 | 869 |
| 870 bool PasswordFormManager::IsIgnorableChangePasswordForm() const { | |
| 871 bool is_change_password_form = !observed_form_.new_password_element.empty() && | |
| 872 !observed_form_.password_element.empty(); | |
| 873 bool is_username_certainly_correct = observed_form_.username_marked_by_site; | |
| 874 return is_change_password_form && !is_username_certainly_correct; | |
| 875 } | |
| 876 | |
| 871 } // namespace password_manager | 877 } // namespace password_manager |
| OLD | NEW |