15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/password_manager/password_form_manager.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <algorithm>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/metrics/histogram.h"
102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/strings/string_split.h"
11868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string_util.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/password_manager/password_manager.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/password_manager/password_store.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/password_manager/password_store_factory.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/profiles/profile.h"
16d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "components/autofill/content/browser/autofill_driver_impl.h"
17d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)#include "components/autofill/content/common/autofill_messages.h"
18d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "components/autofill/core/browser/form_structure.h"
19eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "components/autofill/core/browser/validation.h"
2058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "components/autofill/core/common/password_form.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/render_view_host.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/web_contents.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
24d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)using autofill::FormStructure;
2558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)using autofill::PasswordForm;
2658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)using autofill::PasswordFormMap;
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::Time;
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PasswordFormManager::PasswordFormManager(Profile* profile,
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         PasswordManager* password_manager,
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         content::WebContents* web_contents,
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         const PasswordForm& observed_form,
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         bool ssl_valid)
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : best_matches_deleter_(&best_matches_),
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      observed_form_(observed_form),
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      is_new_login_(true),
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      has_generated_password_(false),
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      password_manager_(password_manager),
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      preferred_match_(NULL),
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      state_(PRE_MATCHING_PHASE),
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      profile_(profile),
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      web_contents_(web_contents),
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      manager_action_(kManagerActionNone),
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      user_action_(kUserActionNone),
45f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      submit_result_(kSubmitResultNotSubmitted) {
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(profile_);
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (observed_form_.origin.is_valid())
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::SplitString(observed_form_.origin.path(), '/', &form_path_tokens_);
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  observed_form_.ssl_valid = ssl_valid;
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PasswordFormManager::~PasswordFormManager() {
534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  UMA_HISTOGRAM_ENUMERATION("PasswordManager.ActionsTakenWithPsl",
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            GetActionsTaken(),
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            kMaxNumActionsTaken);
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int PasswordFormManager::GetActionsTaken() {
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return user_action_ + kUserActionMax * (manager_action_ +
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         kManagerActionMax * submit_result_);
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(timsteele): use a hash of some sort in the future?
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool PasswordFormManager::DoesManage(const PasswordForm& form,
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     ActionMatch action_match) const {
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (form.scheme != PasswordForm::SCHEME_HTML)
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return observed_form_.signon_realm == form.signon_realm;
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // HTML form case.
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // At a minimum, username and password element must match.
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!((form.username_element == observed_form_.username_element) &&
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        (form.password_element == observed_form_.password_element))) {
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // When action match is required, the action URL must match, but
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the form is allowed to have an empty action URL (See bug 1107719).
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Otherwise ignore action URL, this is to allow saving password form with
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // dynamically changed action URL (See bug 27246).
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (form.action.is_valid() && (form.action != observed_form_.action)) {
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (action_match == ACTION_MATCH_REQUIRED)
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If this is a replay of the same form in the case a user entered an invalid
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // password, the origin of the new form may equal the action of the "first"
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // form.
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!((form.origin == observed_form_.origin) ||
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        (form.origin == observed_form_.action))) {
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (form.origin.SchemeIsSecure() &&
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        !observed_form_.origin.SchemeIsSecure()) {
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Compare origins, ignoring scheme. There is no easy way to do this
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // with GURL because clearing the scheme would result in an invalid url.
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // This is for some sites (such as Hotmail) that begin on an http page and
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // head to https for the retry when password was invalid.
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      std::string::const_iterator after_scheme1 = form.origin.spec().begin() +
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                  form.origin.scheme().length();
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      std::string::const_iterator after_scheme2 =
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          observed_form_.origin.spec().begin() +
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          observed_form_.origin.scheme().length();
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return std::search(after_scheme1,
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         form.origin.spec().end(),
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         after_scheme2,
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         observed_form_.origin.spec().end())
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         != form.origin.spec().end();
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool PasswordFormManager::IsBlacklisted() {
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(state_, POST_MATCHING_PHASE);
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (preferred_match_ && preferred_match_->blacklisted_by_user)
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PasswordFormManager::PermanentlyBlacklist() {
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(state_, POST_MATCHING_PHASE);
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Configure the form about to be saved for blacklist status.
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pending_credentials_.preferred = true;
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pending_credentials_.blacklisted_by_user = true;
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pending_credentials_.username_value.clear();
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pending_credentials_.password_value.clear();
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Retroactively forget existing matches for this form, so we NEVER prompt or
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // autofill it again.
1304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  int num_passwords_deleted = 0;
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!best_matches_.empty()) {
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PasswordFormMap::const_iterator iter;
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PasswordStore* password_store = PasswordStoreFactory::GetForProfile(
1347d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        profile_, Profile::EXPLICIT_ACCESS).get();
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!password_store) {
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NOTREACHED();
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (iter = best_matches_.begin(); iter != best_matches_.end(); ++iter) {
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // We want to remove existing matches for this form so that the exact
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // origin match with |blackisted_by_user == true| is the only result that
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // shows up in the future for this origin URL. However, we don't want to
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // delete logins that were actually saved on a different page (hence with
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // different origin URL) and just happened to match this form because of
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // the scoring algorithm. See bug 1204493.
1464e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      if (iter->second->origin == observed_form_.origin) {
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        password_store->RemoveLogin(*iter->second);
1484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        ++num_passwords_deleted;
1494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      }
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  UMA_HISTOGRAM_COUNTS("PasswordManager.NumPasswordsDeletedWhenBlacklisting",
1544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                       num_passwords_deleted);
1554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Save the pending_credentials_ entry marked as blacklisted.
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SaveAsNewLogin(false);
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool PasswordFormManager::IsNewLogin() {
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(state_, POST_MATCHING_PHASE);
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return is_new_login_;
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
165eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochbool PasswordFormManager::IsPendingCredentialsPublicSuffixMatch() {
166eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return pending_credentials_.IsPublicSuffixMatch();
167eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
168eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PasswordFormManager::SetHasGeneratedPassword() {
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  has_generated_password_ = true;
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool PasswordFormManager::HasGeneratedPassword() {
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This check is permissive, as the user may have generated a password and
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // then edited it in the form itself. However, even in this case the user
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // has already given consent, so we treat these cases the same.
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return has_generated_password_;
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool PasswordFormManager::HasValidPasswordForm() {
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(state_, POST_MATCHING_PHASE);
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Non-HTML password forms (primarily HTTP and FTP autentication)
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // do not contain username_element and password_element values.
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (observed_form_.scheme != PasswordForm::SCHEME_HTML)
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return !observed_form_.username_element.empty() &&
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      !observed_form_.password_element.empty();
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
190868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void PasswordFormManager::ProvisionallySave(
191868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    const PasswordForm& credentials,
192868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    OtherPossibleUsernamesAction action) {
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(state_, POST_MATCHING_PHASE);
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(DoesManage(credentials, ACTION_MATCH_NOT_REQUIRED));
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Make sure the important fields stay the same as the initially observed or
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // autofilled ones, as they may have changed if the user experienced a login
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // failure.
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Look for these credentials in the list containing auto-fill entries.
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PasswordFormMap::const_iterator it =
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      best_matches_.find(credentials.username_value);
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (it != best_matches_.end()) {
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // The user signed in with a login we autofilled.
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pending_credentials_ = *it->second;
205eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
206eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // Public suffix matches should always be new logins, since we want to store
207eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // them so they can automatically be filled in later.
208eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    is_new_login_ = IsPendingCredentialsPublicSuffixMatch();
2094e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    if (is_new_login_)
2104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      user_action_ = kUserActionChoosePslMatch;
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Check to see if we're using a known username but a new password.
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (pending_credentials_.password_value != credentials.password_value)
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      user_action_ = kUserActionOverride;
215868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  } else if (action == ALLOW_OTHER_POSSIBLE_USERNAMES &&
216868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)             UpdatePendingCredentialsIfOtherPossibleUsername(
217868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                 credentials.username_value)) {
218868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // |pending_credentials_| is now set. Note we don't update
219868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // |pending_credentials_.username_value| to |credentials.username_value|
220868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // yet because we need to keep the original username to modify the stored
221868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // credential.
222868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    selected_username_ = credentials.username_value;
223868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    is_new_login_ = false;
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // User typed in a new, unknown username.
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    user_action_ = kUserActionOverride;
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pending_credentials_ = observed_form_;
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pending_credentials_.username_value = credentials.username_value;
229868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    pending_credentials_.other_possible_usernames =
230868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        credentials.other_possible_usernames;
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pending_credentials_.action = credentials.action;
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If the user selected credentials we autofilled from a PasswordForm
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // that contained no action URL (IE6/7 imported passwords, for example),
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // bless it with the action URL from the observed form. See bug 1107719.
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (pending_credentials_.action.is_empty())
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pending_credentials_.action = observed_form_.action;
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pending_credentials_.password_value = credentials.password_value;
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pending_credentials_.preferred = credentials.preferred;
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (has_generated_password_)
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pending_credentials_.type = PasswordForm::TYPE_GENERATED;
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PasswordFormManager::Save() {
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(state_, POST_MATCHING_PHASE);
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!profile_->IsOffTheRecord());
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (IsNewLogin())
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SaveAsNewLogin(true);
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UpdateLogin();
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
257f60fc993c7b081abf77ce2ffc7fcca1142c8cb01Torne (Richard Coles)void PasswordFormManager::FetchMatchingLoginsFromPasswordStore(
258f60fc993c7b081abf77ce2ffc7fcca1142c8cb01Torne (Richard Coles)    PasswordStore::AuthorizationPromptPolicy prompt_policy) {
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(state_, PRE_MATCHING_PHASE);
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  state_ = MATCHING_PHASE;
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PasswordStore* password_store = PasswordStoreFactory::GetForProfile(
2627d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      profile_, Profile::EXPLICIT_ACCESS).get();
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!password_store) {
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NOTREACHED();
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
267f60fc993c7b081abf77ce2ffc7fcca1142c8cb01Torne (Richard Coles)  password_store->GetLogins(observed_form_, prompt_policy, this);
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool PasswordFormManager::HasCompletedMatching() {
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return state_ == POST_MATCHING_PHASE;
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void PasswordFormManager::OnRequestDone(
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::vector<PasswordForm*>& logins_result) {
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Note that the result gets deleted after this call completes, but we own
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the PasswordForm objects pointed to by the result vector, thus we keep
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // copies to a minimum here.
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int best_score = 0;
28168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // These credentials will be in the final result regardless of score.
28268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  std::vector<PasswordForm> credentials_to_keep;
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < logins_result.size(); i++) {
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (IgnoreResult(*logins_result[i])) {
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      delete logins_result[i];
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Score and update best matches.
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int current_score = ScoreResult(*logins_result[i]);
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // This check is here so we can append empty path matches in the event
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // they don't score as high as others and aren't added to best_matches_.
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // This is most commonly imported firefox logins. We skip blacklisted
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // ones because clearly we don't want to autofill them, and secondly
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // because they only mean something when we have no other matches already
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // saved in Chrome - in which case they'll make it through the regular
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // scoring flow below by design. Note signon_realm == origin implies empty
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // path logins_result, since signon_realm is a prefix of origin for HTML
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // password forms.
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // TODO(timsteele): Bug 1269400. We probably should do something more
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // elegant for any shorter-path match instead of explicitly handling empty
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // path matches.
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ((observed_form_.scheme == PasswordForm::SCHEME_HTML) &&
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        (observed_form_.signon_realm == logins_result[i]->origin.spec()) &&
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        (current_score > 0) && (!logins_result[i]->blacklisted_by_user)) {
30568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      credentials_to_keep.push_back(*logins_result[i]);
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    // Always keep generated passwords as part of the result set. If a user
30968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    // generates a password on a signup form, it should show on a login form
31068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    // even if they have a previous login saved.
31168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    // TODO(gcasto): We don't want to cut credentials that were saved on signup
31268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    // forms even if they weren't generated, but currently it's hard to
31368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    // distinguish between those forms and two different login forms on the
31468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    // same domain. Filed http://crbug.com/294468 to look into this.
31568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    if (logins_result[i]->type == PasswordForm::TYPE_GENERATED)
31668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      credentials_to_keep.push_back(*logins_result[i]);
31768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (current_score < best_score) {
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      delete logins_result[i];
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (current_score == best_score) {
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      best_matches_[logins_result[i]->username_value] = logins_result[i];
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else if (current_score > best_score) {
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      best_score = current_score;
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // This new login has a better score than all those up to this point
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Note 'this' owns all the PasswordForms in best_matches_.
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      STLDeleteValues(&best_matches_);
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      best_matches_.clear();
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      preferred_match_ = NULL;  // Don't delete, its owned by best_matches_.
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      best_matches_[logins_result[i]->username_value] = logins_result[i];
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    preferred_match_ = logins_result[i]->preferred ? logins_result[i]
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                   : preferred_match_;
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We're done matching now.
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  state_ = POST_MATCHING_PHASE;
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (best_score <= 0) {
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
34368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  for (std::vector<PasswordForm>::const_iterator it =
34468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)           credentials_to_keep.begin();
34568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)       it != credentials_to_keep.end(); ++it) {
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // If we don't already have a result with the same username, add the
34768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    // lower-scored match (if it had equal score it would already be in
34868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    // best_matches_).
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (best_matches_.find(it->username_value) == best_matches_.end())
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      best_matches_[it->username_value] = new PasswordForm(*it);
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  UMA_HISTOGRAM_COUNTS("PasswordManager.NumPasswordsNotShown",
3544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                       logins_result.size() - best_matches_.size());
3554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // It is possible we have at least one match but have no preferred_match_,
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // because a user may have chosen to 'Forget' the preferred match. So we
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // just pick the first one and whichever the user selects for submit will
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // be saved as preferred.
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!best_matches_.empty());
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!preferred_match_)
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    preferred_match_ = best_matches_.begin()->second;
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Check to see if the user told us to ignore this site in the past.
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (preferred_match_->blacklisted_by_user) {
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    manager_action_ = kManagerActionBlacklisted;
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If not blacklisted, send a message to allow password generation.
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SendNotBlacklistedToRenderer();
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Proceed to autofill.
374eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Note that we provide the choices but don't actually prefill a value if:
375eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // (1) we are in Incognito mode, (2) the ACTION paths don't match,
376eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // or (3) if it matched using public suffix domain matching.
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool wait_for_username =
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      profile_->IsOffTheRecord() ||
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      observed_form_.action.GetWithEmptyPath() !=
380eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          preferred_match_->action.GetWithEmptyPath() ||
381eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          preferred_match_->IsPublicSuffixMatch();
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (wait_for_username)
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    manager_action_ = kManagerActionNone;
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    manager_action_ = kManagerActionAutofilled;
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  password_manager_->Autofill(observed_form_, best_matches_,
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              *preferred_match_, wait_for_username);
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PasswordFormManager::OnPasswordStoreRequestDone(
3912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CancelableRequestProvider::Handle handle,
39258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      const std::vector<autofill::PasswordForm*>& result) {
3932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // TODO(kaiwang): Remove this function.
3942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  NOTREACHED();
3952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void PasswordFormManager::OnGetPasswordStoreResults(
39858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      const std::vector<autofill::PasswordForm*>& results) {
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(state_, MATCHING_PHASE);
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (results.empty()) {
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    state_ = POST_MATCHING_PHASE;
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // No result means that we visit this site the first time so we don't need
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // to check whether this site is blacklisted or not. Just send a message
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // to allow password generation.
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SendNotBlacklistedToRenderer();
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  OnRequestDone(results);
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool PasswordFormManager::IgnoreResult(const PasswordForm& form) const {
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Ignore change password forms until we have some change password
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // functionality
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (observed_form_.old_password_element.length() != 0) {
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Don't match an invalid SSL form with one saved under secure
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // circumstances.
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (form.ssl_valid && !observed_form_.ssl_valid) {
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PasswordFormManager::SaveAsNewLogin(bool reset_preferred_login) {
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(state_, POST_MATCHING_PHASE);
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(IsNewLogin());
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The new_form is being used to sign in, so it is preferred.
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(pending_credentials_.preferred);
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // new_form contains the same basic data as observed_form_ (because its the
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // same form), but with the newly added credentials.
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!profile_->IsOffTheRecord());
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PasswordStore* password_store = PasswordStoreFactory::GetForProfile(
4377d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      profile_, Profile::IMPLICIT_ACCESS).get();
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!password_store) {
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NOTREACHED();
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pending_credentials_.date_created = Time::Now();
444c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  SanitizePossibleUsernames(&pending_credentials_);
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  password_store->AddLogin(pending_credentials_);
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (reset_preferred_login) {
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UpdatePreferredLoginState(password_store);
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
452c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void PasswordFormManager::SanitizePossibleUsernames(PasswordForm* form) {
453c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Remove any possible usernames that could be credit cards or SSN for privacy
454868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // reasons. Also remove duplicates, both in other_possible_usernames and
455868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // between other_possible_usernames and username_value.
456d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  std::set<base::string16> set;
457d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  for (std::vector<base::string16>::iterator it =
458868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)           form->other_possible_usernames.begin();
459868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)       it != form->other_possible_usernames.end(); ++it) {
460c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (!autofill::IsValidCreditCardNumber(*it) && !autofill::IsSSN(*it))
461c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      set.insert(*it);
462c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
463c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  set.erase(form->username_value);
464d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  std::vector<base::string16> temp(set.begin(), set.end());
465868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  form->other_possible_usernames.swap(temp);
466c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
467c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PasswordFormManager::UpdatePreferredLoginState(
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PasswordStore* password_store) {
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(password_store);
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PasswordFormMap::iterator iter;
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (iter = best_matches_.begin(); iter != best_matches_.end(); iter++) {
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (iter->second->username_value != pending_credentials_.username_value &&
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        iter->second->preferred) {
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // This wasn't the selected login but it used to be preferred.
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      iter->second->preferred = false;
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (user_action_ == kUserActionNone)
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        user_action_ = kUserActionChoose;
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      password_store->UpdateLogin(*iter->second);
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PasswordFormManager::UpdateLogin() {
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(state_, POST_MATCHING_PHASE);
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(preferred_match_);
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If we're doing an Update, we either autofilled correctly and need to
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // update the stats, or the user typed in a new password for autofilled
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // username, or the user selected one of the non-preferred matches,
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // thus requiring a swap of preferred bits.
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!IsNewLogin() && pending_credentials_.preferred);
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!profile_->IsOffTheRecord());
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PasswordStore* password_store = PasswordStoreFactory::GetForProfile(
4957d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      profile_, Profile::IMPLICIT_ACCESS).get();
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!password_store) {
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NOTREACHED();
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
50190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Update metadata.
50290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  ++pending_credentials_.times_used;
50390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
504d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // Check to see if this form is a candidate for password generation.
505d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  CheckForAccountCreationForm(pending_credentials_, observed_form_);
506d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UpdatePreferredLoginState(password_store);
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
509868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Remove alternate usernames. At this point we assume that we have found
510868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // the right username.
511868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  pending_credentials_.other_possible_usernames.clear();
512868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Update the new preferred login.
514868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!selected_username_.empty()) {
515868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // An other possible username is selected. We set this selected username
516868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // as the real username. The PasswordStore API isn't designed to update
517868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // username, so we delete the old credentials and add a new one instead.
518868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    password_store->RemoveLogin(pending_credentials_);
519868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    pending_credentials_.username_value = selected_username_;
520868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    password_store->AddLogin(pending_credentials_);
521868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  } else if ((observed_form_.scheme == PasswordForm::SCHEME_HTML) &&
522868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)             (observed_form_.origin.spec().length() >
523868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)              observed_form_.signon_realm.length()) &&
524868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)             (observed_form_.signon_realm ==
525868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)              pending_credentials_.origin.spec())) {
526868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // Note origin.spec().length > signon_realm.length implies the origin has a
527868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // path, since signon_realm is a prefix of origin for HTML password forms.
528868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    //
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // The user logged in successfully with one of our autofilled logins on a
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // page with non-empty path, but the autofilled entry was initially saved/
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // imported with an empty path. Rather than just mark this entry preferred,
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // we create a more specific copy for this exact page and leave the "master"
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // unchanged. This is to prevent the case where that master login is used
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // on several sites (e.g site.com/a and site.com/b) but the user actually
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // has a different preference on each site. For example, on /a, he wants the
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // general empty-path login so it is flagged as preferred, but on /b he logs
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // in with a different saved entry - we don't want to remove the preferred
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // status of the former because upon return to /a it won't be the default-
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // fill match.
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // TODO(timsteele): Bug 1188626 - expire the master copies.
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PasswordForm copy(pending_credentials_);
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    copy.origin = observed_form_.origin;
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    copy.action = observed_form_.action;
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    password_store->AddLogin(copy);
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    password_store->UpdateLogin(pending_credentials_);
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
550868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)bool PasswordFormManager::UpdatePendingCredentialsIfOtherPossibleUsername(
551a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    const base::string16& username) {
552868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  for (PasswordFormMap::const_iterator it = best_matches_.begin();
553868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)       it != best_matches_.end(); ++it) {
554868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    for (size_t i = 0; i < it->second->other_possible_usernames.size(); ++i) {
555868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      if (it->second->other_possible_usernames[i] == username) {
556868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        pending_credentials_ = *it->second;
557868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        return true;
558868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      }
559868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
560868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
561868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return false;
562868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
563868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
564d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)void PasswordFormManager::CheckForAccountCreationForm(
565d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    const PasswordForm& pending, const PasswordForm& observed) {
566d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // We check to see if the saved form_data is the same as the observed
567d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // form_data, which should never be true for passwords saved on account
568d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // creation forms. This check is only made the first time a password is used
569d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // to cut down on false positives. Specifically a site may have multiple login
570d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // forms with different markup, which might look similar to a signup form.
571d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  if (pending.times_used == 1) {
572d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    FormStructure pending_structure(pending.form_data);
573d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    FormStructure observed_structure(observed.form_data);
5744e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    // Ignore |pending_structure| if its FormData has no fields. This is to
5754e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    // weed out those credentials that were saved before FormData was added
5764e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    // to PasswordForm. Even without this check, these FormStructure's won't
5774e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    // be uploaded, but it makes it hard to see if we are encountering
5784e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    // unexpected errors.
5794e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    if (!pending.form_data.fields.empty() &&
5804e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        pending_structure.FormSignature() !=
581d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)            observed_structure.FormSignature()) {
582d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      autofill::AutofillDriverImpl* driver =
583d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)          autofill::AutofillDriverImpl::FromWebContents(web_contents_);
584d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      if (driver && driver->autofill_manager()) {
585d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        // Note that this doesn't guarantee that the upload succeeded, only that
586d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        // |pending.form_data| is considered uploadable.
587d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        bool success = driver->autofill_manager()->UploadPasswordGenerationForm(
588d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)            pending.form_data);
589d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        UMA_HISTOGRAM_BOOLEAN("PasswordGeneration.UploadStarted", success);
590d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      }
591d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    }
592d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  }
593d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}
594d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int PasswordFormManager::ScoreResult(const PasswordForm& candidate) const {
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(state_, MATCHING_PHASE);
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // For scoring of candidate login data:
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The most important element that should match is the origin, followed by
5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the action, the password name, the submit button name, and finally the
6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // username input field name.
601eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Exact origin match gives an addition of 64 (1 << 6) + # of matching url
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // dirs.
603eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Partial match gives an addition of 32 (1 << 5) + # matching url dirs
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // That way, a partial match cannot trump an exact match even if
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the partial one matches all other attributes (action, elements) (and
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // regardless of the matching depth in the URL path).
607eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // If public suffix origin match was not used, it gives an addition of
608eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // 16 (1 << 4).
6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int score = 0;
6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (candidate.origin == observed_form_.origin) {
6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // This check is here for the most common case which
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // is we have a single match in the db for the given host,
6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // so we don't generally need to walk the entire URL path (the else
6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // clause).
615eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    score += (1 << 6) + static_cast<int>(form_path_tokens_.size());
6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Walk the origin URL paths one directory at a time to see how
6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // deep the two match.
6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::vector<std::string> candidate_path_tokens;
6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::SplitString(candidate.origin.path(), '/', &candidate_path_tokens);
6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size_t depth = 0;
6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size_t max_dirs = std::min(form_path_tokens_.size(),
6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               candidate_path_tokens.size());
6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    while ((depth < max_dirs) && (form_path_tokens_[depth] ==
6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  candidate_path_tokens[depth])) {
6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      depth++;
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      score++;
6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // do we have a partial match?
630eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    score += (depth > 0) ? 1 << 5 : 0;
6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (observed_form_.scheme == PasswordForm::SCHEME_HTML) {
633eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    if (!candidate.IsPublicSuffixMatch())
634eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      score += 1 << 4;
6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (candidate.action == observed_form_.action)
6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      score += 1 << 3;
6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (candidate.password_element == observed_form_.password_element)
6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      score += 1 << 2;
6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (candidate.submit_element == observed_form_.submit_element)
6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      score += 1 << 1;
6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (candidate.username_element == observed_form_.username_element)
6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      score += 1 << 0;
6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return score;
6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PasswordFormManager::SubmitPassed() {
6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  submit_result_ = kSubmitResultPassed;
6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PasswordFormManager::SubmitFailed() {
6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  submit_result_ = kSubmitResultFailed;
6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PasswordFormManager::SendNotBlacklistedToRenderer() {
6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  content::RenderViewHost* host = web_contents_->GetRenderViewHost();
6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  host->Send(new AutofillMsg_FormNotBlacklisted(host->GetRoutingID(),
6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                 observed_form_));
6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
661