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/command_line.h" | |
| 10 #include "base/metrics/histogram.h" | 11 #include "base/metrics/histogram.h" |
| 11 #include "base/metrics/user_metrics.h" | 12 #include "base/metrics/user_metrics.h" |
| 12 #include "base/strings/string_split.h" | 13 #include "base/strings/string_split.h" |
| 13 #include "base/strings/string_util.h" | 14 #include "base/strings/string_util.h" |
| 14 #include "base/strings/utf_string_conversions.h" | 15 #include "base/strings/utf_string_conversions.h" |
| 15 #include "components/autofill/core/browser/autofill_manager.h" | 16 #include "components/autofill/core/browser/autofill_manager.h" |
| 16 #include "components/autofill/core/browser/form_structure.h" | 17 #include "components/autofill/core/browser/form_structure.h" |
| 17 #include "components/autofill/core/browser/validation.h" | 18 #include "components/autofill/core/browser/validation.h" |
| 19 #include "components/autofill/core/common/autofill_switches.h" | |
| 18 #include "components/autofill/core/common/password_form.h" | 20 #include "components/autofill/core/common/password_form.h" |
| 19 #include "components/password_manager/core/browser/browser_save_password_progres s_logger.h" | 21 #include "components/password_manager/core/browser/browser_save_password_progres s_logger.h" |
| 20 #include "components/password_manager/core/browser/password_manager.h" | 22 #include "components/password_manager/core/browser/password_manager.h" |
| 21 #include "components/password_manager/core/browser/password_manager_client.h" | 23 #include "components/password_manager/core/browser/password_manager_client.h" |
| 22 #include "components/password_manager/core/browser/password_manager_driver.h" | 24 #include "components/password_manager/core/browser/password_manager_driver.h" |
| 23 #include "components/password_manager/core/browser/password_store.h" | 25 #include "components/password_manager/core/browser/password_store.h" |
| 26 #include "net/base/registry_controlled_domains/registry_controlled_domain.h" | |
| 24 | 27 |
| 25 using autofill::FormStructure; | 28 using autofill::FormStructure; |
| 26 using autofill::PasswordForm; | 29 using autofill::PasswordForm; |
| 27 using autofill::PasswordFormMap; | 30 using autofill::PasswordFormMap; |
| 28 using base::Time; | 31 using base::Time; |
| 29 | 32 |
| 30 // Shorten the name to spare line breaks. The code provides enough context | 33 // Shorten the name to spare line breaks. The code provides enough context |
| 31 // already. | 34 // already. |
| 32 typedef autofill::SavePasswordProgressLogger Logger; | 35 typedef autofill::SavePasswordProgressLogger Logger; |
| 33 | 36 |
| (...skipping 27 matching lines...) Expand all Loading... | |
| 61 event, SUBMISSION_EVENT_ENUM_COUNT); | 64 event, SUBMISSION_EVENT_ENUM_COUNT); |
| 62 } | 65 } |
| 63 | 66 |
| 64 PasswordForm CopyAndModifySSLValidity(const PasswordForm& orig, | 67 PasswordForm CopyAndModifySSLValidity(const PasswordForm& orig, |
| 65 bool ssl_valid) { | 68 bool ssl_valid) { |
| 66 PasswordForm result(orig); | 69 PasswordForm result(orig); |
| 67 result.ssl_valid = ssl_valid; | 70 result.ssl_valid = ssl_valid; |
| 68 return result; | 71 return result; |
| 69 } | 72 } |
| 70 | 73 |
| 74 bool IsChangePasswordForm(const PasswordForm& candidate) { | |
| 75 return !candidate.new_password_element.empty() && | |
| 76 !candidate.password_element.empty(); | |
| 77 } | |
| 78 | |
| 71 } // namespace | 79 } // namespace |
| 72 | 80 |
| 73 PasswordFormManager::PasswordFormManager( | 81 PasswordFormManager::PasswordFormManager( |
| 74 PasswordManager* password_manager, | 82 PasswordManager* password_manager, |
| 75 PasswordManagerClient* client, | 83 PasswordManagerClient* client, |
| 76 const base::WeakPtr<PasswordManagerDriver>& driver, | 84 const base::WeakPtr<PasswordManagerDriver>& driver, |
| 77 const PasswordForm& observed_form, | 85 const PasswordForm& observed_form, |
| 78 bool ssl_valid) | 86 bool ssl_valid) |
| 79 : best_matches_deleter_(&best_matches_), | 87 : best_matches_deleter_(&best_matches_), |
| 80 observed_form_(CopyAndModifySSLValidity(observed_form, ssl_valid)), | 88 observed_form_(CopyAndModifySSLValidity(observed_form, ssl_valid)), |
| (...skipping 226 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 307 } else if (action == ALLOW_OTHER_POSSIBLE_USERNAMES && | 315 } else if (action == ALLOW_OTHER_POSSIBLE_USERNAMES && |
| 308 UpdatePendingCredentialsIfOtherPossibleUsername( | 316 UpdatePendingCredentialsIfOtherPossibleUsername( |
| 309 credentials.username_value)) { | 317 credentials.username_value)) { |
| 310 // |pending_credentials_| is now set. Note we don't update | 318 // |pending_credentials_| is now set. Note we don't update |
| 311 // |pending_credentials_.username_value| to |credentials.username_value| | 319 // |pending_credentials_.username_value| to |credentials.username_value| |
| 312 // yet because we need to keep the original username to modify the stored | 320 // yet because we need to keep the original username to modify the stored |
| 313 // credential. | 321 // credential. |
| 314 selected_username_ = credentials.username_value; | 322 selected_username_ = credentials.username_value; |
| 315 is_new_login_ = false; | 323 is_new_login_ = false; |
| 316 } else { | 324 } else { |
| 317 // User typed in a new, unknown username. | 325 // Check whether its a change-password form with missing username or its |
| 318 user_action_ = kUserActionOverrideUsernameAndPassword; | 326 // obscured. E.g. numeric indicator of the password strength please refer |
| 319 pending_credentials_ = observed_form_; | 327 // http://crbug.com/448351. |
| 320 pending_credentials_.username_value = credentials.username_value; | 328 PasswordForm matching_form; |
| 321 pending_credentials_.other_possible_usernames = | 329 if (IsChangePasswordForm(credentials) && |
| 322 credentials.other_possible_usernames; | 330 HasMatchingCredentialsInStore(credentials, &matching_form)) { |
| 331 is_new_login_ = false; | |
| 332 pending_credentials_ = matching_form; | |
| 333 selected_username_ = matching_form.username_value; | |
| 334 user_action_ = kUserActionOverridePassword; | |
| 335 } else { | |
| 336 // User typed in a new, unknown username. | |
| 337 user_action_ = kUserActionOverrideUsernameAndPassword; | |
| 338 pending_credentials_ = observed_form_; | |
| 339 pending_credentials_.username_value = credentials.username_value; | |
| 340 pending_credentials_.other_possible_usernames = | |
| 341 credentials.other_possible_usernames; | |
| 323 | 342 |
| 324 // The password value will be filled in later, remove any garbage for now. | 343 // The password value will be filled in later, remove any garbage for now. |
| 325 pending_credentials_.password_value.clear(); | 344 pending_credentials_.password_value.clear(); |
| 326 pending_credentials_.new_password_value.clear(); | 345 pending_credentials_.new_password_value.clear(); |
| 327 | 346 |
| 328 // If this was a sign-up or change password form, the names of the elements | 347 // If this was a sign-up or change password form, the names of the |
| 329 // are likely different than those on a login form, so do not bother saving | 348 // elements are likely different than those on a login form, so do not |
| 330 // them. We will fill them with meaningful values in UpdateLogin() when the | 349 // bother saving them. We will fill them with meaningful values in |
| 331 // user goes onto a real login form for the first time. | 350 // UpdateLogin() when the user goes onto a real login form for the first |
| 332 if (!credentials.new_password_element.empty()) { | 351 // time. |
| 333 pending_credentials_.password_element.clear(); | 352 if (!credentials.new_password_element.empty()) { |
| 334 pending_credentials_.new_password_element.clear(); | 353 pending_credentials_.password_element.clear(); |
| 354 pending_credentials_.new_password_element.clear(); | |
| 355 } | |
| 335 } | 356 } |
| 336 } | 357 } |
| 337 | 358 |
| 338 pending_credentials_.action = credentials.action; | 359 pending_credentials_.action = credentials.action; |
| 339 // If the user selected credentials we autofilled from a PasswordForm | 360 // If the user selected credentials we autofilled from a PasswordForm |
| 340 // that contained no action URL (IE6/7 imported passwords, for example), | 361 // that contained no action URL (IE6/7 imported passwords, for example), |
| 341 // bless it with the action URL from the observed form. See bug 1107719. | 362 // bless it with the action URL from the observed form. See bug 1107719. |
| 342 if (pending_credentials_.action.is_empty()) | 363 if (pending_credentials_.action.is_empty()) |
| 343 pending_credentials_.action = observed_form_.action; | 364 pending_credentials_.action = observed_form_.action; |
| 344 | 365 |
| (...skipping 26 matching lines...) Expand all Loading... | |
| 371 state_ = MATCHING_PHASE; | 392 state_ = MATCHING_PHASE; |
| 372 | 393 |
| 373 scoped_ptr<BrowserSavePasswordProgressLogger> logger; | 394 scoped_ptr<BrowserSavePasswordProgressLogger> logger; |
| 374 if (client_->IsLoggingActive()) { | 395 if (client_->IsLoggingActive()) { |
| 375 logger.reset(new BrowserSavePasswordProgressLogger(client_)); | 396 logger.reset(new BrowserSavePasswordProgressLogger(client_)); |
| 376 logger->LogMessage(Logger::STRING_FETCH_LOGINS_METHOD); | 397 logger->LogMessage(Logger::STRING_FETCH_LOGINS_METHOD); |
| 377 } | 398 } |
| 378 | 399 |
| 379 // Do not autofill on sign-up or change password forms (until we have some | 400 // Do not autofill on sign-up or change password forms (until we have some |
| 380 // working change password functionality). | 401 // working change password functionality). |
| 381 if (!observed_form_.new_password_element.empty()) { | 402 if (!observed_form_.new_password_element.empty() && |
| 403 !base::CommandLine::ForCurrentProcess()->HasSwitch( | |
| 404 autofill::switches::kEnablePasswordSaveOnInPageNavigation)) { | |
| 382 if (logger) | 405 if (logger) |
| 383 logger->LogMessage(Logger::STRING_FORM_NOT_AUTOFILLED); | 406 logger->LogMessage(Logger::STRING_FORM_NOT_AUTOFILLED); |
| 384 client_->AutofillResultsComputed(); | 407 client_->AutofillResultsComputed(); |
| 385 // There is no point in looking for the credentials in the store when they | 408 // There is no point in looking for the credentials in the store when they |
| 386 // won't be autofilled, so pretend there were none. | 409 // won't be autofilled, so pretend there were none. |
| 387 std::vector<autofill::PasswordForm*> dummy_results; | 410 std::vector<autofill::PasswordForm*> dummy_results; |
| 388 OnGetPasswordStoreResults(dummy_results); | 411 OnGetPasswordStoreResults(dummy_results); |
| 389 return; | 412 return; |
| 390 } | 413 } |
| 391 | 414 |
| 392 PasswordStore* password_store = client_->GetPasswordStore(); | 415 PasswordStore* password_store = client_->GetPasswordStore(); |
| 393 if (!password_store) { | 416 if (!password_store) { |
| 394 if (logger) | 417 if (logger) |
| 395 logger->LogMessage(Logger::STRING_NO_STORE); | 418 logger->LogMessage(Logger::STRING_NO_STORE); |
| 396 NOTREACHED(); | 419 NOTREACHED(); |
| 397 return; | 420 return; |
| 398 } | 421 } |
| 399 password_store->GetLogins(observed_form_, prompt_policy, this); | 422 password_store->GetLogins(observed_form_, prompt_policy, this); |
| 400 } | 423 } |
| 401 | 424 |
| 402 bool PasswordFormManager::HasCompletedMatching() const { | 425 bool PasswordFormManager::HasCompletedMatching() const { |
| 403 return state_ == POST_MATCHING_PHASE; | 426 return state_ == POST_MATCHING_PHASE; |
| 404 } | 427 } |
| 405 | 428 |
| 406 bool PasswordFormManager::IsIgnorableChangePasswordForm() const { | 429 bool PasswordFormManager::IsIgnorableChangePasswordForm() const { |
| 407 bool is_change_password_form = !observed_form_.new_password_element.empty() && | 430 bool is_username_certainly_correct = |
| 408 !observed_form_.password_element.empty(); | 431 observed_form_.username_marked_by_site || |
| 409 bool is_username_certainly_correct = observed_form_.username_marked_by_site; | 432 HasMatchingCredentialsInStore(observed_form_, nullptr); |
| 410 return is_change_password_form && !is_username_certainly_correct; | 433 return IsChangePasswordForm(observed_form_) && !is_username_certainly_correct; |
| 411 } | 434 } |
| 412 | 435 |
| 413 void PasswordFormManager::OnRequestDone( | 436 void PasswordFormManager::OnRequestDone( |
| 414 const std::vector<PasswordForm*>& logins_result) { | 437 const std::vector<PasswordForm*>& logins_result) { |
| 415 // Note that the result gets deleted after this call completes, but we own | 438 // 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 | 439 // the PasswordForm objects pointed to by the result vector, thus we keep |
| 417 // copies to a minimum here. | 440 // copies to a minimum here. |
| 418 | 441 |
| 419 scoped_ptr<BrowserSavePasswordProgressLogger> logger; | 442 scoped_ptr<BrowserSavePasswordProgressLogger> logger; |
| 420 if (client_->IsLoggingActive()) { | 443 if (client_->IsLoggingActive()) { |
| (...skipping 440 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 861 if (has_generated_password_) | 884 if (has_generated_password_) |
| 862 LogPasswordGenerationSubmissionEvent(PASSWORD_SUBMITTED); | 885 LogPasswordGenerationSubmissionEvent(PASSWORD_SUBMITTED); |
| 863 } | 886 } |
| 864 | 887 |
| 865 void PasswordFormManager::SubmitFailed() { | 888 void PasswordFormManager::SubmitFailed() { |
| 866 submit_result_ = kSubmitResultFailed; | 889 submit_result_ = kSubmitResultFailed; |
| 867 if (has_generated_password_) | 890 if (has_generated_password_) |
| 868 LogPasswordGenerationSubmissionEvent(PASSWORD_SUBMISSION_FAILED); | 891 LogPasswordGenerationSubmissionEvent(PASSWORD_SUBMISSION_FAILED); |
| 869 } | 892 } |
| 870 | 893 |
| 894 bool PasswordFormManager::HasMatchingCredentialsInStore( | |
| 895 const autofill::PasswordForm& candidate, | |
| 896 autofill::PasswordForm* matching_form) const { | |
| 897 bool match_found = false; | |
| 898 for (PasswordFormMap::const_iterator iter = best_matches_.begin(); | |
|
vabr (Chromium)
2015/01/28 13:25:32
nit: You can use
for (const auto& match : best_mat
Pritam Nikam
2015/01/29 14:14:35
Done.
| |
| 899 iter != best_matches_.end(); ++iter) { | |
| 900 if (net::registry_controlled_domains::SameDomainOrHost( | |
|
vabr (Chromium)
2015/01/28 13:25:32
This is too permissive, we cannot just update pass
Pritam Nikam
2015/01/29 14:14:35
Done.
| |
| 901 iter->second->origin, candidate.origin, | |
| 902 net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES) && | |
| 903 (iter->second->password_value == candidate.password_value)) { | |
| 904 if (matching_form != nullptr) | |
|
vabr (Chromium)
2015/01/28 13:25:32
nit: Just write:
if (matching_form)
Pritam Nikam
2015/01/29 14:14:35
Done.
| |
| 905 *matching_form = *(iter->second); | |
| 906 match_found = true; | |
| 907 break; | |
| 908 } | |
| 909 } | |
| 910 | |
| 911 return match_found; | |
| 912 } | |
| 913 | |
| 871 } // namespace password_manager | 914 } // namespace password_manager |
| OLD | NEW |