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 "chrome/browser/password_manager/password_form_manager.h" | 5 #include "chrome/browser/password_manager/password_form_manager.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 | 8 |
9 #include "base/metrics/histogram.h" | 9 #include "base/metrics/histogram.h" |
10 #include "base/string_util.h" | 10 #include "base/string_util.h" |
(...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
182 | 182 |
183 // Make sure the important fields stay the same as the initially observed or | 183 // Make sure the important fields stay the same as the initially observed or |
184 // autofilled ones, as they may have changed if the user experienced a login | 184 // autofilled ones, as they may have changed if the user experienced a login |
185 // failure. | 185 // failure. |
186 // Look for these credentials in the list containing auto-fill entries. | 186 // Look for these credentials in the list containing auto-fill entries. |
187 PasswordFormMap::const_iterator it = | 187 PasswordFormMap::const_iterator it = |
188 best_matches_.find(credentials.username_value); | 188 best_matches_.find(credentials.username_value); |
189 if (it != best_matches_.end()) { | 189 if (it != best_matches_.end()) { |
190 // The user signed in with a login we autofilled. | 190 // The user signed in with a login we autofilled. |
191 pending_credentials_ = *it->second; | 191 pending_credentials_ = *it->second; |
192 is_new_login_ = false; | 192 |
193 // PSL origin matches should always be new logins, since we want to store | |
194 // them so they can automatically be filled in later. | |
195 is_new_login_ = pending_credentials_.is_psl_origin_match; | |
193 | 196 |
194 // Check to see if we're using a known username but a new password. | 197 // Check to see if we're using a known username but a new password. |
195 if (pending_credentials_.password_value != credentials.password_value) | 198 if (pending_credentials_.password_value != credentials.password_value) |
196 user_action_ = kUserActionOverride; | 199 user_action_ = kUserActionOverride; |
197 } else if (action == ALLOW_OTHER_POSSIBLE_USERNAMES && | 200 } else if (action == ALLOW_OTHER_POSSIBLE_USERNAMES && |
198 UpdatePendingCredentialsIfOtherPossibleUsername( | 201 UpdatePendingCredentialsIfOtherPossibleUsername( |
199 credentials.username_value)) { | 202 credentials.username_value)) { |
200 // |pending_credentials_| is now set. Note we don't update | 203 // |pending_credentials_| is now set. Note we don't update |
201 // |pending_credentials_.username_value| to |credentials.username_value| | 204 // |pending_credentials_.username_value| to |credentials.username_value| |
202 // yet because we need to keep the original username to modify the stored | 205 // yet because we need to keep the original username to modify the stored |
(...skipping 16 matching lines...) Expand all Loading... | |
219 if (pending_credentials_.action.is_empty()) | 222 if (pending_credentials_.action.is_empty()) |
220 pending_credentials_.action = observed_form_.action; | 223 pending_credentials_.action = observed_form_.action; |
221 | 224 |
222 pending_credentials_.password_value = credentials.password_value; | 225 pending_credentials_.password_value = credentials.password_value; |
223 pending_credentials_.preferred = credentials.preferred; | 226 pending_credentials_.preferred = credentials.preferred; |
224 | 227 |
225 if (has_generated_password_) | 228 if (has_generated_password_) |
226 pending_credentials_.type = PasswordForm::TYPE_GENERATED; | 229 pending_credentials_.type = PasswordForm::TYPE_GENERATED; |
227 } | 230 } |
228 | 231 |
232 bool PasswordFormManager::IsPSLOriginMatched() { | |
233 return pending_credentials_.is_psl_origin_match; | |
palmer
2013/06/06 21:16:42
Nit: Some people prefer to see these getter functi
nyquist
2013/06/07 22:51:10
Done.
| |
234 } | |
235 | |
229 void PasswordFormManager::Save() { | 236 void PasswordFormManager::Save() { |
230 DCHECK_EQ(state_, POST_MATCHING_PHASE); | 237 DCHECK_EQ(state_, POST_MATCHING_PHASE); |
231 DCHECK(!profile_->IsOffTheRecord()); | 238 DCHECK(!profile_->IsOffTheRecord()); |
232 | 239 |
233 if (IsNewLogin()) | 240 if (IsNewLogin()) |
234 SaveAsNewLogin(true); | 241 SaveAsNewLogin(true); |
235 else | 242 else |
236 UpdateLogin(); | 243 UpdateLogin(); |
237 } | 244 } |
238 | 245 |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
330 // Check to see if the user told us to ignore this site in the past. | 337 // Check to see if the user told us to ignore this site in the past. |
331 if (preferred_match_->blacklisted_by_user) { | 338 if (preferred_match_->blacklisted_by_user) { |
332 manager_action_ = kManagerActionBlacklisted; | 339 manager_action_ = kManagerActionBlacklisted; |
333 return; | 340 return; |
334 } | 341 } |
335 | 342 |
336 // If not blacklisted, send a message to allow password generation. | 343 // If not blacklisted, send a message to allow password generation. |
337 SendNotBlacklistedToRenderer(); | 344 SendNotBlacklistedToRenderer(); |
338 | 345 |
339 // Proceed to autofill. | 346 // Proceed to autofill. |
340 // Note that we provide the choices but don't actually prefill a value if | 347 // Note that we provide the choices but don't actually prefill a value if: |
341 // either: (1) we are in Incognito mode, or (2) the ACTION paths don't match. | 348 // (1) we are in Incognito mode, (2) the ACTION paths don't match, |
349 // or (3) if it matched using PSL domain matching. | |
342 bool wait_for_username = | 350 bool wait_for_username = |
343 profile_->IsOffTheRecord() || | 351 profile_->IsOffTheRecord() || |
344 observed_form_.action.GetWithEmptyPath() != | 352 observed_form_.action.GetWithEmptyPath() != |
345 preferred_match_->action.GetWithEmptyPath(); | 353 preferred_match_->action.GetWithEmptyPath() || |
354 preferred_match_->is_psl_origin_match; | |
346 if (wait_for_username) | 355 if (wait_for_username) |
347 manager_action_ = kManagerActionNone; | 356 manager_action_ = kManagerActionNone; |
348 else | 357 else |
349 manager_action_ = kManagerActionAutofilled; | 358 manager_action_ = kManagerActionAutofilled; |
350 password_manager_->Autofill(observed_form_, best_matches_, | 359 password_manager_->Autofill(observed_form_, best_matches_, |
351 *preferred_match_, wait_for_username); | 360 *preferred_match_, wait_for_username); |
352 } | 361 } |
353 | 362 |
354 void PasswordFormManager::OnPasswordStoreRequestDone( | 363 void PasswordFormManager::OnPasswordStoreRequestDone( |
355 CancelableRequestProvider::Handle handle, | 364 CancelableRequestProvider::Handle handle, |
(...skipping 17 matching lines...) Expand all Loading... | |
373 OnRequestDone(results); | 382 OnRequestDone(results); |
374 } | 383 } |
375 | 384 |
376 bool PasswordFormManager::IgnoreResult(const PasswordForm& form) const { | 385 bool PasswordFormManager::IgnoreResult(const PasswordForm& form) const { |
377 // Ignore change password forms until we have some change password | 386 // Ignore change password forms until we have some change password |
378 // functionality | 387 // functionality |
379 if (observed_form_.old_password_element.length() != 0) { | 388 if (observed_form_.old_password_element.length() != 0) { |
380 return true; | 389 return true; |
381 } | 390 } |
382 // Don't match an invalid SSL form with one saved under secure | 391 // Don't match an invalid SSL form with one saved under secure |
383 // circumstances. | 392 // circumstances unless it was found as a PSL origin domain match. |
384 if (form.ssl_valid && !observed_form_.ssl_valid) { | 393 if (form.ssl_valid && |
palmer
2013/06/06 21:16:42
Hmm, I am not sure I like either the old or the ne
nyquist
2013/06/07 22:51:10
I've gone back to the old way which never autofill
| |
394 !observed_form_.ssl_valid && | |
395 !form.is_psl_origin_match) { | |
385 return true; | 396 return true; |
386 } | 397 } |
387 return false; | 398 return false; |
388 } | 399 } |
389 | 400 |
390 void PasswordFormManager::SaveAsNewLogin(bool reset_preferred_login) { | 401 void PasswordFormManager::SaveAsNewLogin(bool reset_preferred_login) { |
391 DCHECK_EQ(state_, POST_MATCHING_PHASE); | 402 DCHECK_EQ(state_, POST_MATCHING_PHASE); |
392 DCHECK(IsNewLogin()); | 403 DCHECK(IsNewLogin()); |
393 // The new_form is being used to sign in, so it is preferred. | 404 // The new_form is being used to sign in, so it is preferred. |
394 DCHECK(pending_credentials_.preferred); | 405 DCHECK(pending_credentials_.preferred); |
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
521 } | 532 } |
522 return false; | 533 return false; |
523 } | 534 } |
524 | 535 |
525 int PasswordFormManager::ScoreResult(const PasswordForm& candidate) const { | 536 int PasswordFormManager::ScoreResult(const PasswordForm& candidate) const { |
526 DCHECK_EQ(state_, MATCHING_PHASE); | 537 DCHECK_EQ(state_, MATCHING_PHASE); |
527 // For scoring of candidate login data: | 538 // For scoring of candidate login data: |
528 // The most important element that should match is the origin, followed by | 539 // The most important element that should match is the origin, followed by |
529 // the action, the password name, the submit button name, and finally the | 540 // the action, the password name, the submit button name, and finally the |
530 // username input field name. | 541 // username input field name. |
531 // Exact origin match gives an addition of 32 (1 << 5) + # of matching url | 542 // Exact origin match gives an addition of 64 (1 << 6) + # of matching url |
532 // dirs. | 543 // dirs. |
533 // Partial match gives an addition of 16 (1 << 4) + # matching url dirs | 544 // Partial match gives an addition of 16 (1 << 5) + # matching url dirs |
Ilya Sherman
2013/06/06 09:25:35
16 -> 32?
nyquist
2013/06/07 22:51:10
Done.
| |
534 // That way, a partial match cannot trump an exact match even if | 545 // That way, a partial match cannot trump an exact match even if |
535 // the partial one matches all other attributes (action, elements) (and | 546 // the partial one matches all other attributes (action, elements) (and |
536 // regardless of the matching depth in the URL path). | 547 // regardless of the matching depth in the URL path). |
548 // If PSL origin match was not used, it gives an addition of 16 (1 << 4). | |
537 int score = 0; | 549 int score = 0; |
538 if (candidate.origin == observed_form_.origin) { | 550 if (candidate.origin == observed_form_.origin) { |
539 // This check is here for the most common case which | 551 // This check is here for the most common case which |
540 // is we have a single match in the db for the given host, | 552 // is we have a single match in the db for the given host, |
541 // so we don't generally need to walk the entire URL path (the else | 553 // so we don't generally need to walk the entire URL path (the else |
542 // clause). | 554 // clause). |
543 score += (1 << 5) + static_cast<int>(form_path_tokens_.size()); | 555 score += (1 << 6) + static_cast<int>(form_path_tokens_.size()); |
544 } else { | 556 } else { |
545 // Walk the origin URL paths one directory at a time to see how | 557 // Walk the origin URL paths one directory at a time to see how |
546 // deep the two match. | 558 // deep the two match. |
547 std::vector<std::string> candidate_path_tokens; | 559 std::vector<std::string> candidate_path_tokens; |
548 base::SplitString(candidate.origin.path(), '/', &candidate_path_tokens); | 560 base::SplitString(candidate.origin.path(), '/', &candidate_path_tokens); |
549 size_t depth = 0; | 561 size_t depth = 0; |
550 size_t max_dirs = std::min(form_path_tokens_.size(), | 562 size_t max_dirs = std::min(form_path_tokens_.size(), |
551 candidate_path_tokens.size()); | 563 candidate_path_tokens.size()); |
552 while ((depth < max_dirs) && (form_path_tokens_[depth] == | 564 while ((depth < max_dirs) && (form_path_tokens_[depth] == |
553 candidate_path_tokens[depth])) { | 565 candidate_path_tokens[depth])) { |
554 depth++; | 566 depth++; |
555 score++; | 567 score++; |
556 } | 568 } |
557 // do we have a partial match? | 569 // do we have a partial match? |
558 score += (depth > 0) ? 1 << 4 : 0; | 570 score += (depth > 0) ? 1 << 5 : 0; |
559 } | 571 } |
560 if (observed_form_.scheme == PasswordForm::SCHEME_HTML) { | 572 if (observed_form_.scheme == PasswordForm::SCHEME_HTML) { |
573 if (!candidate.is_psl_origin_match) | |
574 score += 1 << 4; | |
561 if (candidate.action == observed_form_.action) | 575 if (candidate.action == observed_form_.action) |
562 score += 1 << 3; | 576 score += 1 << 3; |
563 if (candidate.password_element == observed_form_.password_element) | 577 if (candidate.password_element == observed_form_.password_element) |
564 score += 1 << 2; | 578 score += 1 << 2; |
565 if (candidate.submit_element == observed_form_.submit_element) | 579 if (candidate.submit_element == observed_form_.submit_element) |
566 score += 1 << 1; | 580 score += 1 << 1; |
567 if (candidate.username_element == observed_form_.username_element) | 581 if (candidate.username_element == observed_form_.username_element) |
568 score += 1 << 0; | 582 score += 1 << 0; |
569 } | 583 } |
570 | 584 |
571 return score; | 585 return score; |
572 } | 586 } |
573 | 587 |
574 void PasswordFormManager::SubmitPassed() { | 588 void PasswordFormManager::SubmitPassed() { |
575 submit_result_ = kSubmitResultPassed; | 589 submit_result_ = kSubmitResultPassed; |
576 } | 590 } |
577 | 591 |
578 void PasswordFormManager::SubmitFailed() { | 592 void PasswordFormManager::SubmitFailed() { |
579 submit_result_ = kSubmitResultFailed; | 593 submit_result_ = kSubmitResultFailed; |
580 } | 594 } |
581 | 595 |
582 void PasswordFormManager::SendNotBlacklistedToRenderer() { | 596 void PasswordFormManager::SendNotBlacklistedToRenderer() { |
583 content::RenderViewHost* host = web_contents_->GetRenderViewHost(); | 597 content::RenderViewHost* host = web_contents_->GetRenderViewHost(); |
584 host->Send(new AutofillMsg_FormNotBlacklisted(host->GetRoutingID(), | 598 host->Send(new AutofillMsg_FormNotBlacklisted(host->GetRoutingID(), |
585 observed_form_)); | 599 observed_form_)); |
586 } | 600 } |
OLD | NEW |