// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "components/password_manager/core/browser/password_form_manager.h"

#include <stddef.h>

#include <algorithm>
#include <map>
#include <set>
#include <utility>

#include "base/metrics/histogram_macros.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
#include "build/build_config.h"
#include "components/autofill/core/browser/autofill_manager.h"
#include "components/autofill/core/browser/form_structure.h"
#include "components/autofill/core/browser/proto/server.pb.h"
#include "components/autofill/core/browser/validation.h"
#include "components/autofill/core/common/password_form.h"
#include "components/password_manager/core/browser/affiliation_utils.h"
#include "components/password_manager/core/browser/browser_save_password_progress_logger.h"
#include "components/password_manager/core/browser/credentials_filter.h"
#include "components/password_manager/core/browser/log_manager.h"
#include "components/password_manager/core/browser/password_manager.h"
#include "components/password_manager/core/browser/password_manager_client.h"
#include "components/password_manager/core/browser/password_manager_driver.h"
#include "components/password_manager/core/browser/password_manager_metrics_util.h"
#include "components/password_manager/core/browser/password_manager_util.h"
#include "components/password_manager/core/browser/password_store.h"
#include "components/password_manager/core/browser/statistics_table.h"
#include "google_apis/gaia/gaia_auth_util.h"

using autofill::FormStructure;
using autofill::PasswordForm;
using autofill::PasswordFormMap;
using base::Time;

// Shorten the name to spare line breaks. The code provides enough context
// already.
typedef autofill::SavePasswordProgressLogger Logger;

namespace password_manager {

namespace {

PasswordForm CopyAndModifySSLValidity(const PasswordForm& orig,
                                      bool ssl_valid) {
  PasswordForm result(orig);
  result.ssl_valid = ssl_valid;
  return result;
}

// Returns true if user-typed username and password field values match with one
// of the password form within |credentials| map; otherwise false.
bool DoesUsenameAndPasswordMatchCredentials(
    const base::string16& typed_username,
    const base::string16& typed_password,
    const autofill::PasswordFormMap& credentials) {
  for (const auto& match : credentials) {
    if (match.second->username_value == typed_username &&
        match.second->password_value == typed_password)
      return true;
  }
  return false;
}

std::vector<std::string> SplitPathToSegments(const std::string& path) {
  return base::SplitString(path, "/", base::TRIM_WHITESPACE,
                           base::SPLIT_WANT_ALL);
}

// Return false iff the strings are neither empty nor equal.
bool AreStringsEqualOrEmpty(const base::string16& s1,
                            const base::string16& s2) {
  return s1.empty() || s2.empty() || s1 == s2;
}

bool DoesStringContainOnlyDigits(const base::string16& s) {
  for (auto c : s) {
    if (!base::IsAsciiDigit(c))
      return false;
  }
  return true;
}

// Heuristics to determine that a string is very unlikely to be a username.
bool IsProbablyNotUsername(const base::string16& s) {
  return !s.empty() && DoesStringContainOnlyDigits(s) && s.size() < 3;
}

}  // namespace

PasswordFormManager::PasswordFormManager(
    PasswordManager* password_manager,
    PasswordManagerClient* client,
    const base::WeakPtr<PasswordManagerDriver>& driver,
    const PasswordForm& observed_form,
    bool ssl_valid)
    : observed_form_(CopyAndModifySSLValidity(observed_form, ssl_valid)),
      provisionally_saved_form_(nullptr),
      other_possible_username_action_(
          PasswordFormManager::IGNORE_OTHER_POSSIBLE_USERNAMES),
      form_path_segments_(
          observed_form_.origin.is_valid()
              ? SplitPathToSegments(observed_form_.origin.path())
              : std::vector<std::string>()),
      is_new_login_(true),
      has_generated_password_(false),
      is_manual_generation_(false),
      password_overridden_(false),
      retry_password_form_password_update_(false),
      generation_available_(false),
      password_manager_(password_manager),
      preferred_match_(nullptr),
      is_ignorable_change_password_form_(false),
      is_possible_change_password_form_without_username_(
          observed_form.IsPossibleChangePasswordFormWithoutUsername()),
      state_(PRE_MATCHING_PHASE),
      client_(client),
      manager_action_(kManagerActionNone),
      user_action_(kUserActionNone),
      submit_result_(kSubmitResultNotSubmitted),
      form_type_(kFormTypeUnspecified),
      need_to_refetch_(false) {
  DCHECK_EQ(observed_form.scheme == PasswordForm::SCHEME_HTML,
            driver != nullptr);
  if (driver)
    drivers_.push_back(driver);
}

PasswordFormManager::~PasswordFormManager() {
  UMA_HISTOGRAM_ENUMERATION(
      "PasswordManager.ActionsTakenV3", GetActionsTaken(), kMaxNumActionsTaken);
  if (submit_result_ == kSubmitResultNotSubmitted) {
    if (has_generated_password_)
      metrics_util::LogPasswordGenerationSubmissionEvent(
          metrics_util::PASSWORD_NOT_SUBMITTED);
    else if (generation_available_)
      metrics_util::LogPasswordGenerationAvailableSubmissionEvent(
          metrics_util::PASSWORD_NOT_SUBMITTED);
  }
  if (form_type_ != kFormTypeUnspecified) {
    UMA_HISTOGRAM_ENUMERATION("PasswordManager.SubmittedFormType", form_type_,
                              kFormTypeMax);
  }
}

int PasswordFormManager::GetActionsTaken() const {
  return user_action_ +
         kUserActionMax *
             (manager_action_ + kManagerActionMax * submit_result_);
}

// static
base::string16 PasswordFormManager::PasswordToSave(const PasswordForm& form) {
  if (form.new_password_element.empty() || form.new_password_value.empty())
    return form.password_value;
  return form.new_password_value;
}

// TODO(timsteele): use a hash of some sort in the future?
PasswordFormManager::MatchResultMask PasswordFormManager::DoesManage(
    const PasswordForm& form) const {
  // Non-HTML form case.
  if (observed_form_.scheme != PasswordForm::SCHEME_HTML ||
      form.scheme != PasswordForm::SCHEME_HTML) {
    const bool forms_match = observed_form_.signon_realm == form.signon_realm &&
                             observed_form_.scheme == form.scheme;
    return forms_match ? RESULT_COMPLETE_MATCH : RESULT_NO_MATCH;
  }

  // HTML form case.
  MatchResultMask result = RESULT_NO_MATCH;

  // Easiest case of matching origins.
  bool origins_match = form.origin == observed_form_.origin;
  // If this is a replay of the same form in the case a user entered an invalid
  // password, the origin of the new form may equal the action of the "first"
  // form instead.
  origins_match = origins_match || (form.origin == observed_form_.action);
  // Otherwise, if action hosts are the same, the old URL scheme is HTTP while
  // the new one is HTTPS, and the new path equals to or extends the old path,
  // we also consider the actions a match. This is to accommodate cases where
  // the original login form is on an HTTP page, but a failed login attempt
  // redirects to HTTPS (as in http://example.org -> https://example.org/auth).
  if (!origins_match && !observed_form_.origin.SchemeIsCryptographic() &&
      form.origin.SchemeIsCryptographic()) {
    const std::string& old_path = observed_form_.origin.path();
    const std::string& new_path = form.origin.path();
    origins_match =
        observed_form_.origin.host() == form.origin.host() &&
        observed_form_.origin.port() == form.origin.port() &&
        base::StartsWith(new_path, old_path, base::CompareCase::SENSITIVE);
  }

  if (!origins_match)
    return result;

  result |= RESULT_ORIGINS_MATCH;

  // Autofill predictions can overwrite our default username selection so
  // if this form was parsed with autofill predictions then allow the username
  // element to be different.
  if ((form.was_parsed_using_autofill_predictions ||
       form.username_element == observed_form_.username_element) &&
      form.password_element == observed_form_.password_element) {
    result |= RESULT_HTML_ATTRIBUTES_MATCH;
  }

  // Note: although saved password forms might actually have an empty action
  // URL if they were imported (see bug 1107719), the |form| we see here comes
  // never from the password store, and should have an exactly matching action.
  if (form.action == observed_form_.action)
    result |= RESULT_ACTION_MATCH;

  return result;
}

bool PasswordFormManager::IsBlacklisted() const {
  DCHECK_EQ(state_, POST_MATCHING_PHASE);
  return !blacklisted_matches_.empty();
}

void PasswordFormManager::PermanentlyBlacklist() {
  DCHECK_EQ(state_, POST_MATCHING_PHASE);
  DCHECK(!client_->IsOffTheRecord());

  // Configure the form about to be saved for blacklist status.
  blacklisted_matches_.push_back(
      new autofill::PasswordForm(pending_credentials_));
  blacklisted_matches_.back()->preferred = false;
  blacklisted_matches_.back()->blacklisted_by_user = true;
  blacklisted_matches_.back()->username_value.clear();
  blacklisted_matches_.back()->password_value.clear();
  blacklisted_matches_.back()->other_possible_usernames.clear();
  blacklisted_matches_.back()->date_created = Time::Now();

  PasswordStore* password_store = client_->GetPasswordStore();
  DCHECK(password_store);
  password_store->AddLogin(*blacklisted_matches_.back());
}

bool PasswordFormManager::IsNewLogin() const {
  DCHECK_EQ(state_, POST_MATCHING_PHASE);
  return is_new_login_;
}

bool PasswordFormManager::IsPendingCredentialsPublicSuffixMatch() const {
  return pending_credentials_.is_public_suffix_match;
}

void PasswordFormManager::ProvisionallySave(
    const PasswordForm& credentials,
    OtherPossibleUsernamesAction action) {
  DCHECK(state_ == MATCHING_PHASE || state_ == POST_MATCHING_PHASE) << state_;
  DCHECK_NE(RESULT_NO_MATCH, DoesManage(credentials));

  scoped_ptr<autofill::PasswordForm> mutable_provisionally_saved_form(
      new PasswordForm(credentials));
  if (credentials.IsPossibleChangePasswordForm() &&
      !credentials.username_value.empty() &&
      IsProbablyNotUsername(credentials.username_value)) {
    mutable_provisionally_saved_form->username_value.clear();
    mutable_provisionally_saved_form->username_element.clear();
    is_possible_change_password_form_without_username_ = true;
  }
  provisionally_saved_form_ = std::move(mutable_provisionally_saved_form);
  other_possible_username_action_ = action;

  if (HasCompletedMatching())
    CreatePendingCredentials();
}

void PasswordFormManager::Save() {
  DCHECK_EQ(state_, POST_MATCHING_PHASE);
  DCHECK(!client_->IsOffTheRecord());

  if (IsNewLogin()) {
    SaveAsNewLogin();
    DeleteEmptyUsernameCredentials();
  } else {
    UpdateLogin();
  }

  // This is not in UpdateLogin() to catch PSL matched credentials.
  if (pending_credentials_.times_used != 0 &&
      pending_credentials_.type == PasswordForm::TYPE_GENERATED) {
    metrics_util::LogPasswordGenerationSubmissionEvent(
        metrics_util::PASSWORD_USED);
  }

  password_manager_->UpdateFormManagers();
}

void PasswordFormManager::Update(
    const autofill::PasswordForm& credentials_to_update) {
  if (observed_form_.IsPossibleChangePasswordForm()) {
    FormStructure form_structure(credentials_to_update.form_data);
    UploadChangePasswordForm(autofill::NEW_PASSWORD,
                             form_structure.FormSignature());
  }
  base::string16 password_to_save = pending_credentials_.password_value;
  pending_credentials_ = credentials_to_update;
  pending_credentials_.password_value = password_to_save;
  pending_credentials_.preferred = true;
  is_new_login_ = false;
  UpdateLogin();
}

void PasswordFormManager::FetchDataFromPasswordStore() {
  if (state_ == MATCHING_PHASE) {
    // There is currently a password store query in progress, need to re-fetch
    // store results later.
    need_to_refetch_ = true;
    return;
  }

  scoped_ptr<BrowserSavePasswordProgressLogger> logger;
  if (password_manager_util::IsLoggingActive(client_)) {
    logger.reset(
        new BrowserSavePasswordProgressLogger(client_->GetLogManager()));
    logger->LogMessage(Logger::STRING_FETCH_LOGINS_METHOD);
    logger->LogNumber(Logger::STRING_FORM_MANAGER_STATE, state_);
  }

  provisionally_saved_form_.reset();
  state_ = MATCHING_PHASE;

  PasswordStore* password_store = client_->GetPasswordStore();
  if (!password_store) {
    if (logger)
      logger->LogMessage(Logger::STRING_NO_STORE);
    NOTREACHED();
    return;
  }
  password_store->GetLogins(observed_form_, this);

// The statistics isn't needed on mobile, only on desktop. Let's save some
// processor cycles.
#if !defined(OS_IOS) && !defined(OS_ANDROID)
  // The statistics is needed for the "Save password?" bubble.
  password_store->GetSiteStats(observed_form_.origin.GetOrigin(), this);
#endif
}

bool PasswordFormManager::HasCompletedMatching() const {
  return state_ == POST_MATCHING_PHASE;
}

void PasswordFormManager::SetSubmittedForm(const autofill::PasswordForm& form) {
  bool is_change_password_form =
      !form.new_password_value.empty() && !form.password_value.empty();
  is_ignorable_change_password_form_ =
      is_change_password_form && !form.username_marked_by_site &&
      !DoesUsenameAndPasswordMatchCredentials(
          form.username_value, form.password_value, best_matches_) &&
      !client_->IsUpdatePasswordUIEnabled();
  bool is_signup_form =
      !form.new_password_value.empty() && form.password_value.empty();
  bool no_username = form.username_element.empty();

  if (form.layout == PasswordForm::Layout::LAYOUT_LOGIN_AND_SIGNUP) {
    form_type_ = kFormTypeLoginAndSignup;
  } else if (is_ignorable_change_password_form_) {
    if (no_username)
      form_type_ = kFormTypeChangePasswordNoUsername;
    else
      form_type_ = kFormTypeChangePasswordDisabled;
  } else if (is_change_password_form) {
    form_type_ = kFormTypeChangePasswordEnabled;
  } else if (is_signup_form) {
    if (no_username)
      form_type_ = kFormTypeSignupNoUsername;
    else
      form_type_ = kFormTypeSignup;
  } else if (no_username) {
    form_type_ = kFormTypeLoginNoUsername;
  } else {
    form_type_ = kFormTypeLogin;
  }
}

void PasswordFormManager::OnRequestDone(
    ScopedVector<PasswordForm> logins_result) {
  preferred_match_ = nullptr;
  best_matches_.clear();
  blacklisted_matches_.clear();
  const size_t logins_result_size = logins_result.size();

  scoped_ptr<BrowserSavePasswordProgressLogger> logger;
  if (password_manager_util::IsLoggingActive(client_)) {
    logger.reset(
        new BrowserSavePasswordProgressLogger(client_->GetLogManager()));
    logger->LogMessage(Logger::STRING_ON_REQUEST_DONE_METHOD);
  }

  // Remove credentials which need to be ignored from |logins_result|.
  if (!observed_form_.ssl_valid) {
    logins_result.erase(
        std::partition(logins_result.begin(), logins_result.end(),
                       [](PasswordForm* form) { return !form->ssl_valid; }),
        logins_result.end());
  }
  logins_result =
      client_->GetStoreResultFilter()->FilterResults(std::move(logins_result));

  // Deal with blacklisted forms.
  auto begin_blacklisted = std::partition(
      logins_result.begin(), logins_result.end(),
      [](PasswordForm* form) { return !form->blacklisted_by_user; });
  for (auto it = begin_blacklisted; it != logins_result.end(); ++it) {
    if (IsBlacklistMatch(**it)) {
      blacklisted_matches_.push_back(*it);
      *it = nullptr;
    }
  }
  logins_result.erase(begin_blacklisted, logins_result.end());
  if (logins_result.empty())
    return;

  // Now compute scores for the remaining credentials in |login_result|.
  std::vector<uint32_t> credential_scores;
  credential_scores.reserve(logins_result.size());
  uint32_t best_score = 0;
  std::map<base::string16, uint32_t> best_scores;
  for (const PasswordForm* login : logins_result) {
    uint32_t current_score = ScoreResult(*login);
    best_score = std::max(best_score, current_score);
    best_scores[login->username_value] =
        std::max(best_scores[login->username_value], current_score);
    credential_scores.push_back(current_score);
  }

  // Fill |best_matches_| with the best-scoring credentials for each username.
  for (size_t i = 0; i < logins_result.size(); ++i) {
    // Take ownership of the PasswordForm from the ScopedVector.
    scoped_ptr<PasswordForm> login(logins_result[i]);
    logins_result[i] = nullptr;
    DCHECK(!login->blacklisted_by_user);
    const base::string16& username = login->username_value;

    if (credential_scores[i] < best_scores[username]) {
      not_best_matches_.push_back(std::move(login));
      continue;
    }

    if (!preferred_match_ && credential_scores[i] == best_score)
      preferred_match_ = login.get();

    // If there is another best-score match for the same username then leave it
    // and add the current form to |not_best_matches_|.
    auto best_match_username = best_matches_.find(username);
    if (best_match_username == best_matches_.end()) {
      best_matches_.insert(std::make_pair(username, std::move(login)));
    } else {
      not_best_matches_.push_back(std::move(login));
    }
  }

  UMA_HISTOGRAM_COUNTS("PasswordManager.NumPasswordsNotShown",
                       logins_result_size - best_matches_.size());
}

void PasswordFormManager::ProcessFrame(
    const base::WeakPtr<PasswordManagerDriver>& driver) {
  DCHECK_EQ(PasswordForm::SCHEME_HTML, observed_form_.scheme);
  if (state_ == POST_MATCHING_PHASE)
    ProcessFrameInternal(driver);

  for (auto const& old_driver : drivers_) {
    // |drivers_| is not a set because WeakPtr has no good candidate for a key
    // (the address may change to null). So let's weed out duplicates in O(N).
    if (old_driver.get() == driver.get())
      return;
  }

  drivers_.push_back(driver);
}

void PasswordFormManager::ProcessFrameInternal(
    const base::WeakPtr<PasswordManagerDriver>& driver) {
  DCHECK_EQ(PasswordForm::SCHEME_HTML, observed_form_.scheme);
  if (!driver || manager_action_ == kManagerActionBlacklisted)
    return;

  // Allow generation for any non-blacklisted form.
  driver->AllowPasswordGenerationForForm(observed_form_);

  if (best_matches_.empty())
    return;

  // Proceed to autofill.
  // Note that we provide the choices but don't actually prefill a value if:
  // (1) we are in Incognito mode, (2) the ACTION paths don't match,
  // (3) if it matched using public suffix domain matching, or
  // (4) the form is change password form.
  // However, 2 and 3 should not apply to Android-based credentials found
  // via affiliation-based matching (we want to autofill them).
  // TODO(engedy): Clean this up. See: https://crbug.com/476519.
  bool wait_for_username =
      client_->IsOffTheRecord() ||
      (!IsValidAndroidFacetURI(preferred_match_->signon_realm) &&
       (observed_form_.action.GetWithEmptyPath() !=
            preferred_match_->action.GetWithEmptyPath() ||
        preferred_match_->is_public_suffix_match ||
        observed_form_.IsPossibleChangePasswordForm()));
  if (wait_for_username)
    manager_action_ = kManagerActionNone;
  else
    manager_action_ = kManagerActionAutofilled;
  password_manager_->Autofill(driver.get(), observed_form_, best_matches_,
                              *preferred_match_, wait_for_username);
}

void PasswordFormManager::ProcessLoginPrompt() {
  DCHECK_NE(PasswordForm::SCHEME_HTML, observed_form_.scheme);
  if (!preferred_match_)
    return;

  manager_action_ = kManagerActionAutofilled;
  password_manager_->AutofillHttpAuth(best_matches_, *preferred_match_);
}

void PasswordFormManager::OnGetPasswordStoreResults(
    ScopedVector<PasswordForm> results) {
  DCHECK_EQ(state_, MATCHING_PHASE);

  if (need_to_refetch_) {
    // The received results are no longer up-to-date, need to re-request.
    state_ = PRE_MATCHING_PHASE;
    FetchDataFromPasswordStore();
    need_to_refetch_ = false;
    return;
  }

  scoped_ptr<BrowserSavePasswordProgressLogger> logger;
  if (password_manager_util::IsLoggingActive(client_)) {
    logger.reset(
        new BrowserSavePasswordProgressLogger(client_->GetLogManager()));
    logger->LogMessage(Logger::STRING_ON_GET_STORE_RESULTS_METHOD);
    logger->LogNumber(Logger::STRING_NUMBER_RESULTS, results.size());
  }

  if (!results.empty())
    OnRequestDone(std::move(results));
  state_ = POST_MATCHING_PHASE;

  // If password store was slow and provisionally saved form is already here
  // then create pending credentials (see http://crbug.com/470322).
  if (provisionally_saved_form_)
    CreatePendingCredentials();

  if (manager_action_ != kManagerActionBlacklisted) {
    for (auto const& driver : drivers_)
      ProcessFrameInternal(driver);
    if (observed_form_.scheme != PasswordForm::SCHEME_HTML)
      ProcessLoginPrompt();
  }
}

void PasswordFormManager::OnGetSiteStatistics(
    scoped_ptr<std::vector<scoped_ptr<InteractionsStats>>> stats) {
  // On Windows the password request may be resolved after the statistics due to
  // importing from IE.
  DCHECK(state_ == MATCHING_PHASE || state_ == POST_MATCHING_PHASE) << state_;
  interactions_stats_.swap(*stats);
}

void PasswordFormManager::SaveAsNewLogin() {
  DCHECK_EQ(state_, POST_MATCHING_PHASE);
  DCHECK(IsNewLogin());
  // The new_form is being used to sign in, so it is preferred.
  DCHECK(pending_credentials_.preferred);
  DCHECK(!pending_credentials_.blacklisted_by_user);
  // new_form contains the same basic data as observed_form_ (because its the
  // same form), but with the newly added credentials.

  DCHECK(!client_->IsOffTheRecord());

  PasswordStore* password_store = client_->GetPasswordStore();
  if (!password_store) {
    NOTREACHED();
    return;
  }

  // Upload credentials the first time they are saved. This data is used
  // by password generation to help determine account creation sites.
  // Credentials that have been previously used (e.g. PSL matches) are checked
  // to see if they are valid account creation forms.
  if (has_generated_password_) {
    UploadGeneratedVote();
  } else if (pending_credentials_.times_used == 0) {
    if (!observed_form_.IsPossibleChangePasswordFormWithoutUsername())
      UploadPasswordForm(pending_credentials_.form_data, base::string16(),
                         autofill::PASSWORD, std::string());
    } else {
      if (!observed_form_.IsPossibleChangePasswordFormWithoutUsername())
        SendAutofillVotes(observed_form_, &pending_credentials_);
    }

  pending_credentials_.date_created = Time::Now();
  SanitizePossibleUsernames(&pending_credentials_);
  password_store->AddLogin(pending_credentials_);

  UpdatePreferredLoginState(password_store);
}

void PasswordFormManager::SanitizePossibleUsernames(PasswordForm* form) {
  // Remove any possible usernames that could be credit cards or SSN for privacy
  // reasons. Also remove duplicates, both in other_possible_usernames and
  // between other_possible_usernames and username_value.
  std::set<base::string16> set;
  for (std::vector<base::string16>::const_iterator it =
           form->other_possible_usernames.begin();
       it != form->other_possible_usernames.end(); ++it) {
    if (!autofill::IsValidCreditCardNumber(*it) && !autofill::IsSSN(*it))
      set.insert(*it);
  }
  set.erase(form->username_value);
  std::vector<base::string16> temp(set.begin(), set.end());
  form->other_possible_usernames.swap(temp);
}

void PasswordFormManager::UpdatePreferredLoginState(
    PasswordStore* password_store) {
  DCHECK(password_store);
  PasswordFormMap::const_iterator iter;
  for (iter = best_matches_.begin(); iter != best_matches_.end(); iter++) {
    if (iter->second->username_value != pending_credentials_.username_value &&
        iter->second->preferred && !iter->second->is_public_suffix_match) {
      // This wasn't the selected login but it used to be preferred.
      iter->second->preferred = false;
      if (user_action_ == kUserActionNone)
        user_action_ = kUserActionChoose;
      password_store->UpdateLogin(*iter->second);
    }
  }
}

void PasswordFormManager::UpdateLogin() {
  DCHECK_EQ(state_, POST_MATCHING_PHASE);
  DCHECK(preferred_match_);
  // If we're doing an Update, we either autofilled correctly and need to
  // update the stats, or the user typed in a new password for autofilled
  // username, or the user selected one of the non-preferred matches,
  // thus requiring a swap of preferred bits.
  DCHECK(!IsNewLogin() && pending_credentials_.preferred);
  DCHECK(!client_->IsOffTheRecord());

  PasswordStore* password_store = client_->GetPasswordStore();
  if (!password_store) {
    NOTREACHED();
    return;
  }

  UpdateMetadataForUsage(pending_credentials_);

  client_->GetStoreResultFilter()->ReportFormUsed(pending_credentials_);

  // Check to see if this form is a candidate for password generation.
  // Do not send votes on change password forms, since they were already sent in
  // Update() method.
  if (has_generated_password_) {
    UploadGeneratedVote();
  } else if (!observed_form_.IsPossibleChangePasswordForm()) {
    SendAutofillVotes(observed_form_, &pending_credentials_);
  }

  UpdatePreferredLoginState(password_store);

  bool password_was_updated = false;
  // Update the new preferred login.
  if (!selected_username_.empty()) {
    // Username has changed. We set this selected username as the real
    // username. Given that |username_value| is part of the Sync and
    // PasswordStore primary key, the old primary key must be supplied.
    PasswordForm old_primary_key(pending_credentials_);
    pending_credentials_.username_value = selected_username_;
    password_store->UpdateLoginWithPrimaryKey(pending_credentials_,
                                              old_primary_key);
  } else if (observed_form_.new_password_element.empty() &&
             !IsValidAndroidFacetURI(pending_credentials_.signon_realm) &&
             (pending_credentials_.password_element.empty() ||
              pending_credentials_.username_element.empty() ||
              pending_credentials_.submit_element.empty())) {
    // If |observed_form_| was a sign-up or change password form, there is no
    // point in trying to update element names: they are likely going to be
    // different than those on a login form.
    // Otherwise, given that |password_element| and |username_element| are part
    // of Sync and PasswordStore primary key, the old primary key must be
    // supplied to UpdateLogin().
    PasswordForm old_primary_key(pending_credentials_);
    pending_credentials_.password_element = observed_form_.password_element;
    pending_credentials_.username_element = observed_form_.username_element;
    pending_credentials_.submit_element = observed_form_.submit_element;
    password_store->UpdateLoginWithPrimaryKey(pending_credentials_,
                                              old_primary_key);
    password_was_updated = true;
  } else {
    password_store->UpdateLogin(pending_credentials_);
    password_was_updated = true;
  }
  // If this was password update then update all non-best matches entries with
  // the same username and the same old password.
  if (password_was_updated) {
    PasswordFormMap::const_iterator updated_password_it =
        best_matches_.find(pending_credentials_.username_value);
    DCHECK(best_matches_.end() != updated_password_it);
    const base::string16& old_password =
        updated_password_it->second->password_value;
    for (size_t i = 0; i < not_best_matches_.size(); ++i) {
      if (not_best_matches_[i]->username_value ==
              pending_credentials_.username_value &&
          not_best_matches_[i]->password_value == old_password) {
        not_best_matches_[i]->password_value =
            pending_credentials_.password_value;
        password_store->UpdateLogin(*not_best_matches_[i]);
      }
    }
  }
}

void PasswordFormManager::UpdateMetadataForUsage(
    const PasswordForm& credential) {
  ++pending_credentials_.times_used;

  // Remove alternate usernames. At this point we assume that we have found
  // the right username.
  pending_credentials_.other_possible_usernames.clear();
}

bool PasswordFormManager::UpdatePendingCredentialsIfOtherPossibleUsername(
    const base::string16& username) {
  for (PasswordFormMap::const_iterator it = best_matches_.begin();
       it != best_matches_.end(); ++it) {
    for (size_t i = 0; i < it->second->other_possible_usernames.size(); ++i) {
      if (it->second->other_possible_usernames[i] == username) {
        pending_credentials_ = *it->second;
        return true;
      }
    }
  }
  return false;
}

void PasswordFormManager::SendAutofillVotes(
    const PasswordForm& observed,
    PasswordForm* pending) {
  if (pending->form_data.fields.empty())
    return;

  FormStructure pending_structure(pending->form_data);
  FormStructure observed_structure(observed.form_data);

  // Ignore |pending_structure| if its FormData has no fields. This is to
  // weed out those credentials that were saved before FormData was added
  // to PasswordForm. Even without this check, these FormStructure's won't
  // be uploaded, but it makes it hard to see if we are encountering
  // unexpected errors.
  if (pending_structure.FormSignature() != observed_structure.FormSignature()) {
    // Only upload if this is the first time the password has been used.
    // Otherwise the credentials have been used on the same field before so
    // they aren't from an account creation form.
    // Also bypass uploading if the username was edited. Offering generation
    // in cases where we currently save the wrong username isn't great.
    // TODO(gcasto): Determine if generation should be offered in this case.
    if (pending->times_used == 1 && selected_username_.empty()) {
      if (UploadPasswordForm(pending->form_data, pending->username_element,
                             autofill::ACCOUNT_CREATION_PASSWORD,
                             observed_structure.FormSignature())) {
        pending->generation_upload_status =
            autofill::PasswordForm::POSITIVE_SIGNAL_SENT;
      }
    }
  } else if (pending->generation_upload_status ==
             autofill::PasswordForm::POSITIVE_SIGNAL_SENT) {
    // A signal was sent that this was an account creation form, but the
    // credential is now being used on the same form again. This cancels out
    // the previous vote.
    if (UploadPasswordForm(pending->form_data, base::string16(),
                           autofill::NOT_ACCOUNT_CREATION_PASSWORD,
                           std::string())) {
      pending->generation_upload_status =
          autofill::PasswordForm::NEGATIVE_SIGNAL_SENT;
    }
  }
}

bool PasswordFormManager::UploadPasswordForm(
    const autofill::FormData& form_data,
    const base::string16& username_field,
    const autofill::ServerFieldType& password_type,
    const std::string& login_form_signature) {
  DCHECK(password_type == autofill::PASSWORD ||
         password_type == autofill::ACCOUNT_CREATION_PASSWORD ||
         autofill::NOT_ACCOUNT_CREATION_PASSWORD);
  DCHECK(!has_generated_password_);
  autofill::AutofillManager* autofill_manager =
      client_->GetAutofillManagerForMainFrame();
  if (!autofill_manager || !autofill_manager->download_manager())
    return false;

  FormStructure form_structure(form_data);
  if (!autofill_manager->ShouldUploadForm(form_structure) ||
      !form_structure.ShouldBeCrowdsourced()) {
    UMA_HISTOGRAM_BOOLEAN("PasswordGeneration.UploadStarted", false);
    return false;
  }

  // Find the first password field to label. If the provided username field name
  // is not empty, then also find the first field with that name to label.
  // We don't try to label anything else.
  bool found_password_field = false;
  bool should_find_username_field = !username_field.empty();
  for (size_t i = 0; i < form_structure.field_count(); ++i) {
    autofill::AutofillField* field = form_structure.field(i);

    autofill::ServerFieldType type = autofill::UNKNOWN_TYPE;
    if (!found_password_field && field->form_control_type == "password") {
      type = password_type;
      found_password_field = true;
    } else if (should_find_username_field && field->name == username_field) {
      type = autofill::USERNAME;
      should_find_username_field = false;
    }

    autofill::ServerFieldTypeSet types;
    types.insert(type);
    field->set_possible_types(types);
  }
  DCHECK(found_password_field);
  DCHECK(!should_find_username_field);

  autofill::ServerFieldTypeSet available_field_types;
  available_field_types.insert(password_type);
  available_field_types.insert(autofill::USERNAME);

  // Force uploading as these events are relatively rare and we want to make
  // sure to receive them.
  form_structure.set_upload_required(UPLOAD_REQUIRED);

  bool success = autofill_manager->download_manager()->StartUploadRequest(
      form_structure, false /* was_autofilled */, available_field_types,
      login_form_signature, true /* observed_submission */);

  UMA_HISTOGRAM_BOOLEAN("PasswordGeneration.UploadStarted", success);
  return success;
}

bool PasswordFormManager::UploadChangePasswordForm(
    const autofill::ServerFieldType& password_type,
    const std::string& login_form_signature) {
  DCHECK(!has_generated_password_);
  DCHECK(password_type == autofill::NEW_PASSWORD ||
         password_type == autofill::PROBABLY_NEW_PASSWORD ||
         autofill::NOT_NEW_PASSWORD);
  if (!provisionally_saved_form_ ||
      provisionally_saved_form_->new_password_element.empty()) {
    // |new_password_element| is empty for non change password forms, for
    // example when the password was overriden.
    return false;
  }
  autofill::AutofillManager* autofill_manager =
      client_->GetAutofillManagerForMainFrame();
  if (!autofill_manager || !autofill_manager->download_manager())
    return false;

  // Create a map from field names to field types.
  std::map<base::string16, autofill::ServerFieldType> field_types;
  if (!pending_credentials_.username_element.empty())
    field_types[provisionally_saved_form_->username_element] =
        autofill::USERNAME;
  if (!pending_credentials_.password_element.empty())
    field_types[provisionally_saved_form_->password_element] =
        autofill::PASSWORD;
  field_types[provisionally_saved_form_->new_password_element] = password_type;
  // Find all password fields after |new_password_element| and set their type to
  // |password_type|. They are considered to be confirmation fields.
  const autofill::FormData& form_data = observed_form_.form_data;
  bool is_new_password_field_found = false;
  for (size_t i = 0; i < form_data.fields.size(); ++i) {
    const autofill::FormFieldData& field = form_data.fields[i];
    if (field.form_control_type != "password")
      continue;
    if (is_new_password_field_found) {
      field_types[field.name] = password_type;
      // We don't care about password fields after a confirmation field.
      break;
    } else if (field.name == provisionally_saved_form_->new_password_element) {
      is_new_password_field_found = true;
    }
  }
  DCHECK(is_new_password_field_found);

  // Create FormStructure with field type information for uploading a vote.
  FormStructure form_structure(form_data);
  if (!autofill_manager->ShouldUploadForm(form_structure) ||
      !form_structure.ShouldBeCrowdsourced())
    return false;

  autofill::ServerFieldTypeSet available_field_types;
  for (size_t i = 0; i < form_structure.field_count(); ++i) {
    autofill::AutofillField* field = form_structure.field(i);
    autofill::ServerFieldType type = autofill::UNKNOWN_TYPE;
    auto iter = field_types.find(field->name);
    if (iter != field_types.end()) {
      type = iter->second;
      available_field_types.insert(type);
    }

    autofill::ServerFieldTypeSet types;
    types.insert(type);
    field->set_possible_types(types);
  }

  // Force uploading as these events are relatively rare and we want to make
  // sure to receive them. It also makes testing easier if these requests
  // always pass.
  form_structure.set_upload_required(UPLOAD_REQUIRED);

  return autofill_manager->download_manager()->StartUploadRequest(
      form_structure, false /* was_autofilled */, available_field_types,
      login_form_signature, true /* observed_submission */);
}

bool PasswordFormManager::UploadGeneratedVote() {
  DCHECK(has_generated_password_);
  if (generation_element_.empty())
    return false;
  // Create FormStructure with field type information for uploading a vote.
  FormStructure form_structure(observed_form_.form_data);

  autofill::AutofillManager* autofill_manager =
      client_->GetAutofillManagerForMainFrame();
  if (!autofill_manager->ShouldUploadForm(form_structure) ||
      !form_structure.ShouldBeCrowdsourced())
    return false;

  autofill::ServerFieldTypeSet available_field_types;
  available_field_types.insert(autofill::UNKNOWN_TYPE);
  available_field_types.insert(autofill::PASSWORD);

  autofill::AutofillUploadContents::Field::PasswordGenerationType type =
      autofill::AutofillUploadContents::Field::NO_GENERATION;
  if (is_manual_generation_) {
    type = observed_form_.IsPossibleChangePasswordForm()
               ? autofill::AutofillUploadContents::Field::
                     MANUALLY_TRIGGERED_GENERATION_ON_CHANGE_PASSWORD_FORM
               : autofill::AutofillUploadContents::Field::
                     MANUALLY_TRIGGERED_GENERATION_ON_SIGN_UP_FORM;
  } else {
    type = observed_form_.IsPossibleChangePasswordForm()
               ? autofill::AutofillUploadContents::Field::
                     AUTOMATICALLY_TRIGGERED_GENERATION_ON_CHANGE_PASSWORD_FORM
               : autofill::AutofillUploadContents::Field::
                     AUTOMATICALLY_TRIGGERED_GENERATION_ON_SIGN_UP_FORM;
  }

  bool generation_field_found = false;
  for (size_t i = 0; i < form_structure.field_count(); ++i) {
    autofill::AutofillField* field = form_structure.field(i);
    if (field->name == generation_element_) {
      field->set_generation_type(type);
      autofill::ServerFieldTypeSet types;
      types.insert(autofill::PASSWORD);
      field->set_possible_types(types);
      generation_field_found = true;
      break;
    }
  }

  if (!generation_field_found)
    return false;

  return autofill_manager->download_manager()->StartUploadRequest(
      form_structure, false /* was_autofilled */, available_field_types,
      std::string(), true /* observed_submission */);
}

void PasswordFormManager::CreatePendingCredentials() {
  DCHECK(provisionally_saved_form_);
  base::string16 password_to_save(PasswordToSave(*provisionally_saved_form_));

  // Make sure the important fields stay the same as the initially observed or
  // autofilled ones, as they may have changed if the user experienced a login
  // failure.
  // Look for these credentials in the list containing auto-fill entries.
  PasswordForm* saved_form =
      FindBestSavedMatch(provisionally_saved_form_.get());
  if (saved_form != nullptr) {
    // The user signed in with a login we autofilled.
    pending_credentials_ = *saved_form;
    password_overridden_ =
        pending_credentials_.password_value != password_to_save;
    if (IsPendingCredentialsPublicSuffixMatch()) {
      // If the autofilled credentials were a PSL match or credentials stored
      // from Android apps store a copy with the current origin and signon
      // realm. This ensures that on the next visit, a precise match is found.
      is_new_login_ = true;
      user_action_ = password_overridden_ ? kUserActionOverridePassword
                                          : kUserActionChoosePslMatch;

      // Since this credential will not overwrite a previously saved credential,
      // username_value can be updated now.
      if (!selected_username_.empty())
        pending_credentials_.username_value = selected_username_;

      // Update credential to reflect that it has been used for submission.
      // If this isn't updated, then password generation uploads are off for
      // sites where PSL matching is required to fill the login form, as two
      // PASSWORD votes are uploaded per saved password instead of one.
      //
      // TODO(gcasto): It would be nice if other state were shared such that if
      // say a password was updated on one match it would update on all related
      // passwords. This is a much larger change.
      UpdateMetadataForUsage(pending_credentials_);

      // Update |pending_credentials_| in order to be able correctly save it.
      pending_credentials_.origin = provisionally_saved_form_->origin;
      pending_credentials_.signon_realm =
          provisionally_saved_form_->signon_realm;

      // Normally, the copy of the PSL matched credentials, adapted for the
      // current domain, is saved automatically without asking the user, because
      // the copy likely represents the same account, i.e., the one for which
      // the user already agreed to store a password.
      //
      // However, if the user changes the suggested password, it might indicate
      // that the autofilled credentials and |provisionally_saved_form_|
      // actually correspond  to two different accounts (see
      // http://crbug.com/385619). In that case the user should be asked again
      // before saving the password. This is ensured by setting
      // |password_overriden_| on |pending_credentials_| to false and setting
      // |origin| and |signon_realm| to correct values.
      //
      // There is still the edge case when the autofilled credentials represent
      // the same account as |provisionally_saved_form_| but the stored password
      // was out of date. In that case, the user just had to manually enter the
      // new password, which is now in |provisionally_saved_form_|. The best
      // thing would be to save automatically, and also update the original
      // credentials. However, we have no way to tell if this is the case.
      // This will likely happen infrequently, and the inconvenience put on the
      // user by asking them is not significant, so we are fine with asking
      // here again.
      if (password_overridden_) {
        pending_credentials_.is_public_suffix_match = false;
        password_overridden_ = false;
      }
    } else {  // Not a PSL match.
      is_new_login_ = false;
      if (password_overridden_)
        user_action_ = kUserActionOverridePassword;
    }
  } else if (other_possible_username_action_ ==
                 ALLOW_OTHER_POSSIBLE_USERNAMES &&
             UpdatePendingCredentialsIfOtherPossibleUsername(
                 provisionally_saved_form_->username_value)) {
    // |pending_credentials_| is now set. Note we don't update
    // |pending_credentials_.username_value| to |credentials.username_value|
    // yet because we need to keep the original username to modify the stored
    // credential.
    selected_username_ = provisionally_saved_form_->username_value;
    is_new_login_ = false;
  } else if (client_->IsUpdatePasswordUIEnabled() && !best_matches_.empty() &&
             provisionally_saved_form_->type !=
                 autofill::PasswordForm::TYPE_API &&
             (provisionally_saved_form_
                  ->IsPossibleChangePasswordFormWithoutUsername() ||
              provisionally_saved_form_->username_element.empty())) {
    PasswordForm* best_update_match = FindBestMatchForUpdatePassword(
        provisionally_saved_form_->password_value);

    retry_password_form_password_update_ =
        provisionally_saved_form_->username_element.empty() &&
        provisionally_saved_form_->new_password_element.empty();

    is_new_login_ = false;
    if (best_update_match) {
      pending_credentials_ = *best_update_match;
    } else if (has_generated_password_) {
      // If a password was generated and we didn't find match we have to save it
      // in separate entry since we have to store it but we don't know where.
      CreatePendingCredentialsForNewCredentials();
      is_new_login_ = true;
    } else {
      // We don't care about |pending_credentials_| if we didn't find the best
      // match, since the user will select the correct one.
      pending_credentials_.origin = provisionally_saved_form_->origin;
    }
  } else {
    CreatePendingCredentialsForNewCredentials();
  }

  if (!IsValidAndroidFacetURI(pending_credentials_.signon_realm)) {
    pending_credentials_.action = provisionally_saved_form_->action;
    // If the user selected credentials we autofilled from a PasswordForm
    // that contained no action URL (IE6/7 imported passwords, for example),
    // bless it with the action URL from the observed form. See bug 1107719.
    if (pending_credentials_.action.is_empty())
      pending_credentials_.action = observed_form_.action;
  }

  pending_credentials_.password_value = password_to_save;
  pending_credentials_.preferred = provisionally_saved_form_->preferred;

  if (user_action_ == kUserActionOverridePassword &&
      pending_credentials_.type == PasswordForm::TYPE_GENERATED &&
      !has_generated_password_) {
    metrics_util::LogPasswordGenerationSubmissionEvent(
        metrics_util::PASSWORD_OVERRIDDEN);
    pending_credentials_.type = PasswordForm::TYPE_MANUAL;
  }

  if (has_generated_password_)
    pending_credentials_.type = PasswordForm::TYPE_GENERATED;

  // In case of change password forms we need to leave
  // |provisionally_saved_form_| in order to be able to determine which field is
  // password and which is a new password during sending a vote in other cases
  // we can reset |provisionally_saved_form_|.
  if (!client_->IsUpdatePasswordUIEnabled() ||
      !provisionally_saved_form_->IsPossibleChangePasswordForm())
    provisionally_saved_form_.reset();
}

uint32_t PasswordFormManager::ScoreResult(const PasswordForm& candidate) const {
  DCHECK_EQ(state_, MATCHING_PHASE);
  DCHECK(!candidate.blacklisted_by_user);
  // For scoring of candidate login data:
  // The most important element that should match is the signon_realm followed
  // by the origin, the action, the password name, the submit button name, and
  // finally the username input field name.
  // If public suffix origin match was not used, it gives an addition of
  // 128 (1 << 7).
  // Exact origin match gives an addition of 64 (1 << 6) + # of matching url
  // dirs.
  // Partial match gives an addition of 32 (1 << 5) + # matching url dirs
  // That way, a partial match cannot trump an exact match even if
  // the partial one matches all other attributes (action, elements) (and
  // regardless of the matching depth in the URL path).

  // When comparing path segments, only consider at most 63 of them, so that the
  // potential gain from shared path prefix is not more than from an exact
  // origin match.
  const size_t kSegmentCountCap = 63;
  const size_t capped_form_path_segment_count =
      std::min(form_path_segments_.size(), kSegmentCountCap);

  uint32_t score = 0u;
  if (!candidate.is_public_suffix_match) {
    score += 1u << 8;
  }

  if (candidate.preferred)
    score += 1u << 7;

  if (candidate.origin == observed_form_.origin) {
    // This check is here for the most common case which
    // is we have a single match in the db for the given host,
    // so we don't generally need to walk the entire URL path (the else
    // clause).
    score += (1u << 6) + static_cast<uint32_t>(capped_form_path_segment_count);
  } else {
    // Walk the origin URL paths one directory at a time to see how
    // deep the two match.
    std::vector<std::string> candidate_path_segments =
        SplitPathToSegments(candidate.origin.path());
    size_t depth = 0u;
    const size_t max_dirs = std::min(capped_form_path_segment_count,
                                     candidate_path_segments.size());
    while ((depth < max_dirs) &&
           (form_path_segments_[depth] == candidate_path_segments[depth])) {
      depth++;
      score++;
    }
    // do we have a partial match?
    score += (depth > 0u) ? 1u << 5 : 0u;
  }
  if (observed_form_.scheme == PasswordForm::SCHEME_HTML) {
    if (candidate.action == observed_form_.action)
      score += 1u << 3;
    if (candidate.password_element == observed_form_.password_element)
      score += 1u << 2;
    if (candidate.submit_element == observed_form_.submit_element)
      score += 1u << 1;
    if (candidate.username_element == observed_form_.username_element)
      score += 1u << 0;
  }

  return score;
}

bool PasswordFormManager::IsBlacklistMatch(
    const autofill::PasswordForm& blacklisted_form) const {
  DCHECK(blacklisted_form.blacklisted_by_user);

  if (blacklisted_form.is_public_suffix_match)
    return false;
  if (blacklisted_form.origin.GetOrigin() != observed_form_.origin.GetOrigin())
    return false;
  if (observed_form_.scheme == PasswordForm::SCHEME_HTML) {
    if (!AreStringsEqualOrEmpty(blacklisted_form.submit_element,
                                observed_form_.submit_element))
      return false;
    if (!AreStringsEqualOrEmpty(blacklisted_form.password_element,
                                observed_form_.password_element))
      return false;
    if (!AreStringsEqualOrEmpty(blacklisted_form.username_element,
                                observed_form_.username_element))
      return false;
  }
  return true;
}

void PasswordFormManager::DeleteEmptyUsernameCredentials() {
  if (best_matches_.empty() || pending_credentials_.username_value.empty())
    return;
  PasswordStore* password_store = client_->GetPasswordStore();
  if (!password_store) {
    NOTREACHED();
    return;
  }
  for (auto iter = best_matches_.begin(); iter != best_matches_.end(); ++iter) {
    PasswordForm* form = iter->second.get();
    if (!form->is_public_suffix_match && form->username_value.empty() &&
        form->password_value == pending_credentials_.password_value)
      password_store->RemoveLogin(*form);
  }
}

PasswordForm* PasswordFormManager::FindBestMatchForUpdatePassword(
    const base::string16& password) const {
  if (best_matches_.size() == 1 && !has_generated_password_) {
    // In case when the user has only one credential and the current password is
    // not generated, consider it the same as is being saved.
    return best_matches_.begin()->second.get();
  }
  if (password.empty())
    return nullptr;

  for (auto it = best_matches_.begin(); it != best_matches_.end(); ++it) {
    if (it->second->password_value == password)
      return it->second.get();
  }
  return nullptr;
}

PasswordForm* PasswordFormManager::FindBestSavedMatch(
    const PasswordForm* form) const {
  PasswordFormMap::const_iterator it = best_matches_.find(form->username_value);
  if (it != best_matches_.end())
    return it->second.get();
  if (form->type == autofill::PasswordForm::TYPE_API)
    // Match Credential API forms only by username.
    return nullptr;
  if (!form->username_element.empty() || !form->new_password_element.empty())
    return nullptr;
  for (const auto& stored_match : best_matches_) {
    if (stored_match.second->password_value == form->password_value)
      return stored_match.second.get();
  }
  return nullptr;
}

void PasswordFormManager::CreatePendingCredentialsForNewCredentials() {
  // User typed in a new, unknown username.
  user_action_ = kUserActionOverrideUsernameAndPassword;
  pending_credentials_ = observed_form_;
  if (provisionally_saved_form_->was_parsed_using_autofill_predictions)
    pending_credentials_.username_element =
        provisionally_saved_form_->username_element;
  pending_credentials_.username_value =
      provisionally_saved_form_->username_value;
  pending_credentials_.other_possible_usernames =
      provisionally_saved_form_->other_possible_usernames;

  // The password value will be filled in later, remove any garbage for now.
  pending_credentials_.password_value.clear();
  pending_credentials_.new_password_value.clear();

  // If this was a sign-up or change password form, the names of the elements
  // are likely different than those on a login form, so do not bother saving
  // them. We will fill them with meaningful values in UpdateLogin() when the
  // user goes onto a real login form for the first time.
  if (!provisionally_saved_form_->new_password_element.empty()) {
    pending_credentials_.password_element.clear();
  }
}

void PasswordFormManager::OnNopeUpdateClicked() {
  UploadChangePasswordForm(autofill::NOT_NEW_PASSWORD, std::string());
}

void PasswordFormManager::OnNoInteractionOnUpdate() {
  UploadChangePasswordForm(autofill::PROBABLY_NEW_PASSWORD, std::string());
}

void PasswordFormManager::LogSubmitPassed() {
  if (submit_result_ != kSubmitResultFailed) {
    if (has_generated_password_) {
      metrics_util::LogPasswordGenerationSubmissionEvent(
          metrics_util::PASSWORD_SUBMITTED);
    } else if (generation_available_) {
      metrics_util::LogPasswordGenerationAvailableSubmissionEvent(
          metrics_util::PASSWORD_SUBMITTED);
    }
  }
  submit_result_ = kSubmitResultPassed;
}

void PasswordFormManager::LogSubmitFailed() {
  if (has_generated_password_) {
    metrics_util::LogPasswordGenerationSubmissionEvent(
        metrics_util::GENERATED_PASSWORD_FORCE_SAVED);
  } else if (generation_available_) {
    metrics_util::LogPasswordGenerationAvailableSubmissionEvent(
        metrics_util::PASSWORD_SUBMISSION_FAILED);
  }
  submit_result_ = kSubmitResultFailed;
}

void PasswordFormManager::WipeStoreCopyIfOutdated() {
  DCHECK_NE(PRE_MATCHING_PHASE, state_);

  UMA_HISTOGRAM_BOOLEAN("PasswordManager.StoreReadyWhenWiping",
                        HasCompletedMatching());

  PasswordStore* password_store = client_->GetPasswordStore();
  if (!password_store)
    return;

  for (PasswordFormMap::const_iterator stored_credential =
           best_matches_.begin();
       stored_credential != best_matches_.end();
       /*no increment here*/) {
    // Beware erase() below, keep the cycle iterator valid.
    PasswordFormMap::const_iterator credential_to_delete = stored_credential;
    ++stored_credential;

    if (pending_credentials_.password_value ==
        credential_to_delete->second->password_value) {
      continue;
    }
    if (!gaia::AreEmailsSame(
            base::UTF16ToUTF8(pending_credentials_.username_value),
            base::UTF16ToUTF8(credential_to_delete->first))) {
      continue;
    }
    password_store->RemoveLogin(*credential_to_delete->second);
    if (credential_to_delete->second.get() == preferred_match_)
      preferred_match_ = nullptr;
    best_matches_.erase(credential_to_delete);
  }
}

}  // namespace password_manager
