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 "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 274 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 285 return state_ == POST_MATCHING_PHASE; | 285 return state_ == POST_MATCHING_PHASE; |
| 286 } | 286 } |
| 287 | 287 |
| 288 void PasswordFormManager::OnRequestDone( | 288 void PasswordFormManager::OnRequestDone( |
| 289 const std::vector<PasswordForm*>& logins_result) { | 289 const std::vector<PasswordForm*>& logins_result) { |
| 290 // Note that the result gets deleted after this call completes, but we own | 290 // Note that the result gets deleted after this call completes, but we own |
| 291 // the PasswordForm objects pointed to by the result vector, thus we keep | 291 // the PasswordForm objects pointed to by the result vector, thus we keep |
| 292 // copies to a minimum here. | 292 // copies to a minimum here. |
| 293 | 293 |
| 294 int best_score = 0; | 294 int best_score = 0; |
| 295 std::vector<PasswordForm> empties; // Empty-path matches in result set. | 295 // We will make sure these forms are in the final result regardless of score. |
|
Ilya Sherman
2013/09/19 01:02:20
nit: Please try to phrase comments without using "
Garrett Casto
2013/09/19 17:40:14
Done.
| |
| 296 std::vector<PasswordForm> credentials_to_keep; | |
| 296 for (size_t i = 0; i < logins_result.size(); i++) { | 297 for (size_t i = 0; i < logins_result.size(); i++) { |
| 297 if (IgnoreResult(*logins_result[i])) { | 298 if (IgnoreResult(*logins_result[i])) { |
| 298 delete logins_result[i]; | 299 delete logins_result[i]; |
| 299 continue; | 300 continue; |
| 300 } | 301 } |
| 301 // Score and update best matches. | 302 // Score and update best matches. |
| 302 int current_score = ScoreResult(*logins_result[i]); | 303 int current_score = ScoreResult(*logins_result[i]); |
| 303 // This check is here so we can append empty path matches in the event | 304 // This check is here so we can append empty path matches in the event |
| 304 // they don't score as high as others and aren't added to best_matches_. | 305 // they don't score as high as others and aren't added to best_matches_. |
| 305 // This is most commonly imported firefox logins. We skip blacklisted | 306 // This is most commonly imported firefox logins. We skip blacklisted |
| 306 // ones because clearly we don't want to autofill them, and secondly | 307 // ones because clearly we don't want to autofill them, and secondly |
| 307 // because they only mean something when we have no other matches already | 308 // because they only mean something when we have no other matches already |
| 308 // saved in Chrome - in which case they'll make it through the regular | 309 // saved in Chrome - in which case they'll make it through the regular |
| 309 // scoring flow below by design. Note signon_realm == origin implies empty | 310 // scoring flow below by design. Note signon_realm == origin implies empty |
| 310 // path logins_result, since signon_realm is a prefix of origin for HTML | 311 // path logins_result, since signon_realm is a prefix of origin for HTML |
| 311 // password forms. | 312 // password forms. |
| 312 // TODO(timsteele): Bug 1269400. We probably should do something more | 313 // TODO(timsteele): Bug 1269400. We probably should do something more |
| 313 // elegant for any shorter-path match instead of explicitly handling empty | 314 // elegant for any shorter-path match instead of explicitly handling empty |
| 314 // path matches. | 315 // path matches. |
| 315 if ((observed_form_.scheme == PasswordForm::SCHEME_HTML) && | 316 if ((observed_form_.scheme == PasswordForm::SCHEME_HTML) && |
| 316 (observed_form_.signon_realm == logins_result[i]->origin.spec()) && | 317 (observed_form_.signon_realm == logins_result[i]->origin.spec()) && |
| 317 (current_score > 0) && (!logins_result[i]->blacklisted_by_user)) { | 318 (current_score > 0) && (!logins_result[i]->blacklisted_by_user)) { |
| 318 empties.push_back(*logins_result[i]); | 319 credentials_to_keep.push_back(*logins_result[i]); |
| 320 } | |
| 321 | |
| 322 // Always keep generated passwords as part of the result set. We don't want | |
| 323 // users to generate a password on a signup form, and then not have it fill | |
| 324 // on the login form because they already have a previous login saved. | |
| 325 // TODO(gcasto): We don't want to cut credentials that were saved on signup | |
| 326 // forms even if they weren't generated, but currently it's hard to | |
| 327 // distinguish between those forms and two different login forms on the | |
| 328 // same domain. Filed http://crbug.com/294468 to look into this. | |
| 329 if (logins_result[i]->type == PasswordForm::TYPE_GENERATED) { | |
| 330 credentials_to_keep.push_back(*logins_result[i]); | |
| 319 } | 331 } |
|
Ilya Sherman
2013/09/19 01:02:20
nit: No need for curlies.
Garrett Casto
2013/09/19 17:40:14
Done.
| |
| 320 | 332 |
| 321 if (current_score < best_score) { | 333 if (current_score < best_score) { |
| 322 delete logins_result[i]; | 334 delete logins_result[i]; |
| 323 continue; | 335 continue; |
| 324 } | 336 } |
| 325 if (current_score == best_score) { | 337 if (current_score == best_score) { |
| 326 best_matches_[logins_result[i]->username_value] = logins_result[i]; | 338 best_matches_[logins_result[i]->username_value] = logins_result[i]; |
| 327 } else if (current_score > best_score) { | 339 } else if (current_score > best_score) { |
| 328 best_score = current_score; | 340 best_score = current_score; |
| 329 // This new login has a better score than all those up to this point | 341 // This new login has a better score than all those up to this point |
| 330 // Note 'this' owns all the PasswordForms in best_matches_. | 342 // Note 'this' owns all the PasswordForms in best_matches_. |
| 331 STLDeleteValues(&best_matches_); | 343 STLDeleteValues(&best_matches_); |
| 332 best_matches_.clear(); | 344 best_matches_.clear(); |
| 333 preferred_match_ = NULL; // Don't delete, its owned by best_matches_. | 345 preferred_match_ = NULL; // Don't delete, its owned by best_matches_. |
| 334 best_matches_[logins_result[i]->username_value] = logins_result[i]; | 346 best_matches_[logins_result[i]->username_value] = logins_result[i]; |
| 335 } | 347 } |
| 336 preferred_match_ = logins_result[i]->preferred ? logins_result[i] | 348 preferred_match_ = logins_result[i]->preferred ? logins_result[i] |
| 337 : preferred_match_; | 349 : preferred_match_; |
| 338 } | 350 } |
| 339 // We're done matching now. | 351 // We're done matching now. |
| 340 state_ = POST_MATCHING_PHASE; | 352 state_ = POST_MATCHING_PHASE; |
| 341 | 353 |
| 342 if (best_score <= 0) { | 354 if (best_score <= 0) { |
| 343 return; | 355 return; |
| 344 } | 356 } |
| 345 | 357 |
| 346 for (std::vector<PasswordForm>::const_iterator it = empties.begin(); | 358 for (std::vector<PasswordForm>::const_iterator it = |
| 347 it != empties.end(); ++it) { | 359 credentials_to_keep.begin(); |
| 360 it != credentials_to_keep.end(); ++it) { | |
| 348 // If we don't already have a result with the same username, add the | 361 // If we don't already have a result with the same username, add the |
| 349 // lower-scored empty-path match (if it had equal score it would already be | 362 // lower-scored match (if it had equal score it would already be in |
| 350 // in best_matches_). | 363 // best_matches_). |
| 351 if (best_matches_.find(it->username_value) == best_matches_.end()) | 364 if (best_matches_.find(it->username_value) == best_matches_.end()) |
| 352 best_matches_[it->username_value] = new PasswordForm(*it); | 365 best_matches_[it->username_value] = new PasswordForm(*it); |
| 353 } | 366 } |
| 354 | 367 |
| 355 // It is possible we have at least one match but have no preferred_match_, | 368 // It is possible we have at least one match but have no preferred_match_, |
| 356 // because a user may have chosen to 'Forget' the preferred match. So we | 369 // because a user may have chosen to 'Forget' the preferred match. So we |
| 357 // just pick the first one and whichever the user selects for submit will | 370 // just pick the first one and whichever the user selects for submit will |
| 358 // be saved as preferred. | 371 // be saved as preferred. |
| 359 DCHECK(!best_matches_.empty()); | 372 DCHECK(!best_matches_.empty()); |
| 360 if (!preferred_match_) | 373 if (!preferred_match_) |
| (...skipping 255 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 616 | 629 |
| 617 void PasswordFormManager::SubmitFailed() { | 630 void PasswordFormManager::SubmitFailed() { |
| 618 submit_result_ = kSubmitResultFailed; | 631 submit_result_ = kSubmitResultFailed; |
| 619 } | 632 } |
| 620 | 633 |
| 621 void PasswordFormManager::SendNotBlacklistedToRenderer() { | 634 void PasswordFormManager::SendNotBlacklistedToRenderer() { |
| 622 content::RenderViewHost* host = web_contents_->GetRenderViewHost(); | 635 content::RenderViewHost* host = web_contents_->GetRenderViewHost(); |
| 623 host->Send(new AutofillMsg_FormNotBlacklisted(host->GetRoutingID(), | 636 host->Send(new AutofillMsg_FormNotBlacklisted(host->GetRoutingID(), |
| 624 observed_form_)); | 637 observed_form_)); |
| 625 } | 638 } |
| OLD | NEW |