Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(411)

Side by Side Diff: chrome/browser/password_manager/password_form_manager.cc

Issue 15660018: [autofill] Add support for PSL domain matching for password autofill. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fixed android label with Created 7 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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/strings/string_split.h" 10 #include "base/strings/string_split.h"
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after
146 146
147 // Save the pending_credentials_ entry marked as blacklisted. 147 // Save the pending_credentials_ entry marked as blacklisted.
148 SaveAsNewLogin(false); 148 SaveAsNewLogin(false);
149 } 149 }
150 150
151 bool PasswordFormManager::IsNewLogin() { 151 bool PasswordFormManager::IsNewLogin() {
152 DCHECK_EQ(state_, POST_MATCHING_PHASE); 152 DCHECK_EQ(state_, POST_MATCHING_PHASE);
153 return is_new_login_; 153 return is_new_login_;
154 } 154 }
155 155
156 bool PasswordFormManager::IsPendingCredentialsPublicSuffixMatch() {
157 return !pending_credentials_.original_signon_realm.empty();
158 }
159
156 void PasswordFormManager::SetHasGeneratedPassword() { 160 void PasswordFormManager::SetHasGeneratedPassword() {
157 has_generated_password_ = true; 161 has_generated_password_ = true;
158 } 162 }
159 163
160 bool PasswordFormManager::HasGeneratedPassword() { 164 bool PasswordFormManager::HasGeneratedPassword() {
161 // This check is permissive, as the user may have generated a password and 165 // This check is permissive, as the user may have generated a password and
162 // then edited it in the form itself. However, even in this case the user 166 // then edited it in the form itself. However, even in this case the user
163 // has already given consent, so we treat these cases the same. 167 // has already given consent, so we treat these cases the same.
164 return has_generated_password_; 168 return has_generated_password_;
165 } 169 }
(...skipping 16 matching lines...) Expand all
182 186
183 // Make sure the important fields stay the same as the initially observed or 187 // 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 188 // autofilled ones, as they may have changed if the user experienced a login
185 // failure. 189 // failure.
186 // Look for these credentials in the list containing auto-fill entries. 190 // Look for these credentials in the list containing auto-fill entries.
187 PasswordFormMap::const_iterator it = 191 PasswordFormMap::const_iterator it =
188 best_matches_.find(credentials.username_value); 192 best_matches_.find(credentials.username_value);
189 if (it != best_matches_.end()) { 193 if (it != best_matches_.end()) {
190 // The user signed in with a login we autofilled. 194 // The user signed in with a login we autofilled.
191 pending_credentials_ = *it->second; 195 pending_credentials_ = *it->second;
192 is_new_login_ = false; 196
197 // Public suffix matches should always be new logins, since we want to store
198 // them so they can automatically be filled in later.
199 is_new_login_ = !pending_credentials_.original_signon_realm.empty();
193 200
194 // Check to see if we're using a known username but a new password. 201 // Check to see if we're using a known username but a new password.
195 if (pending_credentials_.password_value != credentials.password_value) 202 if (pending_credentials_.password_value != credentials.password_value)
196 user_action_ = kUserActionOverride; 203 user_action_ = kUserActionOverride;
197 } else if (action == ALLOW_OTHER_POSSIBLE_USERNAMES && 204 } else if (action == ALLOW_OTHER_POSSIBLE_USERNAMES &&
198 UpdatePendingCredentialsIfOtherPossibleUsername( 205 UpdatePendingCredentialsIfOtherPossibleUsername(
199 credentials.username_value)) { 206 credentials.username_value)) {
200 // |pending_credentials_| is now set. Note we don't update 207 // |pending_credentials_| is now set. Note we don't update
201 // |pending_credentials_.username_value| to |credentials.username_value| 208 // |pending_credentials_.username_value| to |credentials.username_value|
202 // yet because we need to keep the original username to modify the stored 209 // yet because we need to keep the original username to modify the stored
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after
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 public suffix 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_->original_signon_realm.empty();
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 165 matching lines...) Expand 10 before | Expand all | Expand 10 after
521 } 530 }
522 return false; 531 return false;
523 } 532 }
524 533
525 int PasswordFormManager::ScoreResult(const PasswordForm& candidate) const { 534 int PasswordFormManager::ScoreResult(const PasswordForm& candidate) const {
526 DCHECK_EQ(state_, MATCHING_PHASE); 535 DCHECK_EQ(state_, MATCHING_PHASE);
527 // For scoring of candidate login data: 536 // For scoring of candidate login data:
528 // The most important element that should match is the origin, followed by 537 // 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 538 // the action, the password name, the submit button name, and finally the
530 // username input field name. 539 // username input field name.
531 // Exact origin match gives an addition of 32 (1 << 5) + # of matching url 540 // Exact origin match gives an addition of 64 (1 << 6) + # of matching url
532 // dirs. 541 // dirs.
533 // Partial match gives an addition of 16 (1 << 4) + # matching url dirs 542 // Partial match gives an addition of 32 (1 << 5) + # matching url dirs
534 // That way, a partial match cannot trump an exact match even if 543 // That way, a partial match cannot trump an exact match even if
535 // the partial one matches all other attributes (action, elements) (and 544 // the partial one matches all other attributes (action, elements) (and
536 // regardless of the matching depth in the URL path). 545 // regardless of the matching depth in the URL path).
546 // If public suffix origin match was not used, it gives an addition of
547 // 16 (1 << 4).
537 int score = 0; 548 int score = 0;
538 if (candidate.origin == observed_form_.origin) { 549 if (candidate.origin == observed_form_.origin) {
539 // This check is here for the most common case which 550 // This check is here for the most common case which
540 // is we have a single match in the db for the given host, 551 // 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 552 // so we don't generally need to walk the entire URL path (the else
542 // clause). 553 // clause).
543 score += (1 << 5) + static_cast<int>(form_path_tokens_.size()); 554 score += (1 << 6) + static_cast<int>(form_path_tokens_.size());
544 } else { 555 } else {
545 // Walk the origin URL paths one directory at a time to see how 556 // Walk the origin URL paths one directory at a time to see how
546 // deep the two match. 557 // deep the two match.
547 std::vector<std::string> candidate_path_tokens; 558 std::vector<std::string> candidate_path_tokens;
548 base::SplitString(candidate.origin.path(), '/', &candidate_path_tokens); 559 base::SplitString(candidate.origin.path(), '/', &candidate_path_tokens);
549 size_t depth = 0; 560 size_t depth = 0;
550 size_t max_dirs = std::min(form_path_tokens_.size(), 561 size_t max_dirs = std::min(form_path_tokens_.size(),
551 candidate_path_tokens.size()); 562 candidate_path_tokens.size());
552 while ((depth < max_dirs) && (form_path_tokens_[depth] == 563 while ((depth < max_dirs) && (form_path_tokens_[depth] ==
553 candidate_path_tokens[depth])) { 564 candidate_path_tokens[depth])) {
554 depth++; 565 depth++;
555 score++; 566 score++;
556 } 567 }
557 // do we have a partial match? 568 // do we have a partial match?
558 score += (depth > 0) ? 1 << 4 : 0; 569 score += (depth > 0) ? 1 << 5 : 0;
559 } 570 }
560 if (observed_form_.scheme == PasswordForm::SCHEME_HTML) { 571 if (observed_form_.scheme == PasswordForm::SCHEME_HTML) {
572 if (candidate.original_signon_realm.empty())
573 score += 1 << 4;
561 if (candidate.action == observed_form_.action) 574 if (candidate.action == observed_form_.action)
562 score += 1 << 3; 575 score += 1 << 3;
563 if (candidate.password_element == observed_form_.password_element) 576 if (candidate.password_element == observed_form_.password_element)
564 score += 1 << 2; 577 score += 1 << 2;
565 if (candidate.submit_element == observed_form_.submit_element) 578 if (candidate.submit_element == observed_form_.submit_element)
566 score += 1 << 1; 579 score += 1 << 1;
567 if (candidate.username_element == observed_form_.username_element) 580 if (candidate.username_element == observed_form_.username_element)
568 score += 1 << 0; 581 score += 1 << 0;
569 } 582 }
570 583
571 return score; 584 return score;
572 } 585 }
573 586
574 void PasswordFormManager::SubmitPassed() { 587 void PasswordFormManager::SubmitPassed() {
575 submit_result_ = kSubmitResultPassed; 588 submit_result_ = kSubmitResultPassed;
576 } 589 }
577 590
578 void PasswordFormManager::SubmitFailed() { 591 void PasswordFormManager::SubmitFailed() {
579 submit_result_ = kSubmitResultFailed; 592 submit_result_ = kSubmitResultFailed;
580 } 593 }
581 594
582 void PasswordFormManager::SendNotBlacklistedToRenderer() { 595 void PasswordFormManager::SendNotBlacklistedToRenderer() {
583 content::RenderViewHost* host = web_contents_->GetRenderViewHost(); 596 content::RenderViewHost* host = web_contents_->GetRenderViewHost();
584 host->Send(new AutofillMsg_FormNotBlacklisted(host->GetRoutingID(), 597 host->Send(new AutofillMsg_FormNotBlacklisted(host->GetRoutingID(),
585 observed_form_)); 598 observed_form_));
586 } 599 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698