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

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: Updated regexp, sanitized result, escaped form domain and added comments. 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/string_util.h" 10 #include "base/string_util.h"
(...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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
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
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
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 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698