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 |