// 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_manager.h"

#include <stddef.h>

#include <algorithm>
#include <map>
#include <memory>
#include <utility>

#include "base/metrics/field_trial.h"
#include "base/metrics/histogram_macros.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/threading/platform_thread.h"
#include "build/build_config.h"
#include "components/autofill/core/browser/autofill_field.h"
#include "components/autofill/core/browser/form_structure.h"
#include "components/autofill/core/browser/logging/log_manager.h"
#include "components/autofill/core/common/form_data_predictions.h"
#include "components/autofill/core/common/password_form_field_prediction_map.h"
#include "components/autofill/core/common/save_password_progress_logger.h"
#include "components/password_manager/core/browser/browser_save_password_progress_logger.h"
#include "components/password_manager/core/browser/form_saver_impl.h"
#include "components/password_manager/core/browser/password_autofill_manager.h"
#include "components/password_manager/core/browser/password_form_manager.h"
#include "components/password_manager/core/browser/password_generation_frame_helper.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_onboarding.h"
#include "components/password_manager/core/browser/password_manager_util.h"
#include "components/password_manager/core/common/password_manager_features.h"
#include "components/password_manager/core/common/password_manager_pref_names.h"
#include "components/pref_registry/pref_registry_syncable.h"
#include "components/prefs/pref_service.h"
#include "google_apis/gaia/gaia_auth_util.h"
#include "net/base/registry_controlled_domains/registry_controlled_domain.h"

#if defined(OS_WIN)
#include "components/prefs/pref_registry_simple.h"
#endif

using autofill::FormData;
using autofill::FormStructure;
using autofill::PasswordForm;
using autofill::mojom::PasswordFormFieldPredictionType;
#if defined(SYNC_PASSWORD_REUSE_DETECTION_ENABLED)
using password_manager::metrics_util::GaiaPasswordHashChange;
#endif  // SYNC_PASSWORD_REUSE_DETECTION_ENABLED

namespace password_manager {

namespace {

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

bool URLsEqualUpToScheme(const GURL& a, const GURL& b) {
  return (a.GetContent() == b.GetContent());
}

bool URLsEqualUpToHttpHttpsSubstitution(const GURL& a, const GURL& b) {
  if (a == b)
    return true;

  // The first-time and retry login forms action URLs sometimes differ in
  // switching from HTTP to HTTPS, see http://crbug.com/400769.
  if (a.SchemeIsHTTPOrHTTPS() && b.SchemeIsHTTPOrHTTPS())
    return URLsEqualUpToScheme(a, b);

  return false;
}

// Since empty or unspecified form's action is automatically set to the page
// origin, this function checks if a form's action is empty by comparing it to
// its origin.
bool HasNonEmptyAction(const PasswordForm& form) {
  return form.action != form.origin;
}

// Checks if the observed form looks like the submitted one to handle "Invalid
// password entered" case so we don't offer a password save when we shouldn't.
bool IsPasswordFormReappeared(const PasswordForm& observed_form,
                              const PasswordForm& submitted_form) {
  if (observed_form.action.is_valid() && HasNonEmptyAction(observed_form) &&
      HasNonEmptyAction(submitted_form) &&
      URLsEqualUpToHttpHttpsSubstitution(submitted_form.action,
                                         observed_form.action)) {
    return true;
  }

  // Match the form if username and password fields are same.
  if (base::EqualsCaseInsensitiveASCII(observed_form.username_element,
                                       submitted_form.username_element) &&
      base::EqualsCaseInsensitiveASCII(observed_form.password_element,
                                       submitted_form.password_element)) {
    return true;
  }

  // Match the form if the observed username field has the same value as in
  // the submitted form.
  if (!submitted_form.username_value.empty() &&
      observed_form.username_value == submitted_form.username_value) {
    return true;
  }

  return false;
}

bool AreAllFieldsEmpty(const PasswordForm& form) {
  return form.username_value.empty() && form.password_value.empty() &&
         form.new_password_value.empty();
}

// Returns true if the user needs to be prompted before a password can be
// saved (instead of automatically saving the password), based on inspecting
// the state of |manager|.
bool ShouldPromptUserToSavePassword(
    const PasswordFormManagerInterface& manager) {
  if (manager.IsPasswordUpdate()) {
    // Updating a credential might erase a useful stored value by accident.
    // Always ask the user to confirm.
    return true;
  }

  // User successfully signed-in with PSL match credentials. These credentials
  // should be automatically saved in order to be autofilled on next login.
  if (manager.IsPendingCredentialsPublicSuffixMatch())
    return false;

  if (manager.HasGeneratedPassword())
    return false;

  return manager.IsNewLogin();
}

// Checks that |form| has visible password fields. It should be used only for
// GAIA forms.
bool IsThereVisiblePasswordField(const FormData& form) {
  for (const autofill::FormFieldData& field : form.fields) {
    if (field.form_control_type == "password" && field.is_focusable)
      return true;
  }
  return false;
}

// Finds the matched form manager for |form| in |form_managers|.
PasswordFormManager* FindMatchedManager(
    const FormData& form,
    const std::vector<std::unique_ptr<PasswordFormManager>>& form_managers,
    const PasswordManagerDriver* driver) {
  for (const auto& form_manager : form_managers) {
    if (form_manager->DoesManage(form, driver))
      return form_manager.get();
  }
  return nullptr;
}

// Finds the matched form manager with id |form_renderer_id| in |form_managers|.
PasswordFormManager* FindMatchedManagerByRendererId(
    uint32_t form_renderer_id,
    const std::vector<std::unique_ptr<PasswordFormManager>>& form_managers,
    const PasswordManagerDriver* driver) {
  for (const auto& form_manager : form_managers) {
    if (form_manager->DoesManageAccordingToRendererId(form_renderer_id, driver))
      return form_manager.get();
  }
  return nullptr;
}

bool HasSingleUsernameVote(const FormStructure& form) {
  for (const auto& field : form) {
    if (field->server_type() == autofill::SINGLE_USERNAME)
      return true;
  }
  return false;
}

// Returns true if at least one of the fields in |form| has a prediction to be a
// new-password related field.
// corresponds to a field for creating or changing a password.
bool HasNewPasswordVote(const FormStructure& form) {
  for (const auto& field : form) {
    if (field->server_type() == autofill::ACCOUNT_CREATION_PASSWORD ||
        field->server_type() == autofill::NEW_PASSWORD) {
      return true;
    }
  }
  return false;
}

}  // namespace

// static
void PasswordManager::RegisterProfilePrefs(
    user_prefs::PrefRegistrySyncable* registry) {
  registry->RegisterBooleanPref(prefs::kBlacklistedCredentialsNormalized,
                                false);
  registry->RegisterBooleanPref(
      prefs::kCredentialsEnableService, true,
      user_prefs::PrefRegistrySyncable::SYNCABLE_PRIORITY_PREF);
  registry->RegisterBooleanPref(
      prefs::kCredentialsEnableAutosignin, true,
      user_prefs::PrefRegistrySyncable::SYNCABLE_PRIORITY_PREF);
  registry->RegisterStringPref(prefs::kSyncPasswordHash, std::string(),
                               PrefRegistry::NO_REGISTRATION_FLAGS);
  registry->RegisterStringPref(prefs::kSyncPasswordLengthAndHashSalt,
                               std::string(),
                               PrefRegistry::NO_REGISTRATION_FLAGS);
  registry->RegisterBooleanPref(
      prefs::kWasAutoSignInFirstRunExperienceShown, false,
      user_prefs::PrefRegistrySyncable::SYNCABLE_PRIORITY_PREF);
  registry->RegisterDoublePref(prefs::kLastTimeObsoleteHttpCredentialsRemoved,
                               0.0);
  registry->RegisterIntegerPref(
      prefs::kPasswordManagerOnboardingState,
      static_cast<int>(metrics_util::OnboardingState::kDoNotShow));

#if defined(OS_MACOSX)
  registry->RegisterIntegerPref(prefs::kKeychainMigrationStatus,
                                4 /* MIGRATED_DELETED */);
#endif
  registry->RegisterListPref(prefs::kPasswordHashDataList,
                             PrefRegistry::NO_REGISTRATION_FLAGS);
  registry->RegisterBooleanPref(
      prefs::kPasswordLeakDetectionEnabled, true,
      user_prefs::PrefRegistrySyncable::SYNCABLE_PREF);
}

// static
void PasswordManager::RegisterLocalPrefs(PrefRegistrySimple* registry) {
#if defined(OS_WIN)
  registry->RegisterInt64Pref(prefs::kOsPasswordLastChanged, 0);
  registry->RegisterBooleanPref(prefs::kOsPasswordBlank, false);
#endif

#if defined(OS_MACOSX) && !defined(OS_IOS)
  registry->RegisterTimePref(prefs::kPasswordRecovery, base::Time());
#endif
}

PasswordManager::PasswordManager(PasswordManagerClient* client)
    : client_(client)
#if !defined(OS_IOS)
      ,
      leak_delegate_(client)
#endif  // !defined(OS_IOS)
{
  DCHECK(client_);
}

PasswordManager::~PasswordManager() = default;

void PasswordManager::OnGeneratedPasswordAccepted(
    PasswordManagerDriver* driver,
    const FormData& form_data,
    uint32_t generation_element_id,
    const base::string16& password) {
  PasswordFormManager* manager = GetMatchedManager(driver, form_data);
  if (manager) {
    manager->OnGeneratedPasswordAccepted(form_data, generation_element_id,
                                         password);
  } else {
    // OnPresaveGeneratedPassword records the histogram in all other cases.
    UMA_HISTOGRAM_BOOLEAN("PasswordManager.GeneratedFormHasNoFormManager",
                          true);
  }
}

void PasswordManager::OnPresaveGeneratedPassword(PasswordManagerDriver* driver,
                                                 const PasswordForm& form) {
  DCHECK(client_->IsSavingAndFillingEnabled(form.origin));
  PasswordFormManagerInterface* form_manager = GetMatchedManager(driver, form);
  UMA_HISTOGRAM_BOOLEAN("PasswordManager.GeneratedFormHasNoFormManager",
                        !form_manager);
  if (form_manager)
    form_manager->PresaveGeneratedPassword(form);
}

void PasswordManager::OnPasswordNoLongerGenerated(PasswordManagerDriver* driver,
                                                  const PasswordForm& form) {
  DCHECK(client_->IsSavingAndFillingEnabled(form.origin));

  PasswordFormManagerInterface* form_manager = GetMatchedManager(driver, form);
  if (form_manager)
    form_manager->PasswordNoLongerGenerated();
}

void PasswordManager::SetGenerationElementAndReasonForForm(
    password_manager::PasswordManagerDriver* driver,
    const PasswordForm& form,
    const base::string16& generation_element,
    bool is_manually_triggered) {
  DCHECK(client_->IsSavingAndFillingEnabled(form.origin));

  PasswordFormManagerInterface* form_manager = GetMatchedManager(driver, form);
  if (form_manager) {
    form_manager->SetGenerationElement(generation_element);
    form_manager->SetGenerationPopupWasShown(true, is_manually_triggered);
  }
}

void PasswordManager::DidNavigateMainFrame(bool form_may_be_submitted) {
  std::unique_ptr<BrowserSavePasswordProgressLogger> logger;
  if (password_manager_util::IsLoggingActive(client_)) {
    logger.reset(
        new BrowserSavePasswordProgressLogger(client_->GetLogManager()));
    logger->LogBoolean(Logger::STRING_DID_NAVIGATE_MAIN_FRAME,
                       form_may_be_submitted);
  }

  if (client_->IsNewTabPage()) {
    if (logger)
      logger->LogMessage(Logger::STRING_NAVIGATION_NTP);
    // On a successful Chrome sign-in the page navigates to the new tab page
    // (ntp). OnPasswordFormsRendered is not called on ntp. That is why the
    // standard flow for saving hash does not work. Save a password hash now
    // since a navigation to ntp is the sign of successful sign-in.
    PasswordFormManagerInterface* manager = GetSubmittedManager();
    if (manager && manager->GetSubmittedForm()
                       ->form_data.is_gaia_with_skip_save_password_form) {
      MaybeSavePasswordHash(manager);
    }
  }

  for (std::unique_ptr<PasswordFormManager>& manager : form_managers_) {
    if (form_may_be_submitted && manager->is_submitted()) {
      owned_submitted_form_manager_ = std::move(manager);
      break;
    }
  }
  form_managers_.clear();
  predictions_.clear();
  store_password_called_ = false;
}

void PasswordManager::UpdateFormManagers() {
  std::vector<PasswordFormManagerInterface*> form_managers;
  for (const auto& form_manager : form_managers_)
    form_managers.push_back(form_manager.get());

  // Get the fetchers and all the drivers.
  std::vector<FormFetcher*> fetchers;
  std::vector<PasswordManagerDriver*> drivers;
  for (PasswordFormManagerInterface* form_manager : form_managers) {
    fetchers.push_back(form_manager->GetFormFetcher());
    for (const auto& driver : form_manager->GetDrivers()) {
      if (driver)
        drivers.push_back(driver.get());
    }
  }

  // Remove the duplicates.
  std::sort(fetchers.begin(), fetchers.end());
  fetchers.erase(std::unique(fetchers.begin(), fetchers.end()), fetchers.end());
  std::sort(drivers.begin(), drivers.end());
  drivers.erase(std::unique(drivers.begin(), drivers.end()), drivers.end());
  // Refetch credentials for all the forms and update the drivers.
  for (FormFetcher* fetcher : fetchers)
    fetcher->Fetch();

  // The autofill manager will be repopulated again when the credentials
  // are retrieved.
  for (PasswordManagerDriver* driver : drivers) {
    // GetPasswordAutofillManager() is returning nullptr in iOS Chrome, since
    // PasswordAutofillManager is not instantiated on iOS Chrome.
    // See //ios/chrome/browser/passwords/ios_chrome_password_manager_driver.mm
    if (driver->GetPasswordAutofillManager()) {
      driver->GetPasswordAutofillManager()->DeleteFillData();
    }
  }
}

void PasswordManager::DropFormManagers() {
  form_managers_.clear();
  owned_submitted_form_manager_.reset();
  all_visible_forms_.clear();
  predictions_.clear();
}

bool PasswordManager::IsPasswordFieldDetectedOnPage() {
  return !form_managers_.empty();
}

void PasswordManager::OnPasswordFormSubmitted(
    password_manager::PasswordManagerDriver* driver,
    const PasswordForm& password_form) {
  ProvisionallySaveForm(password_form.form_data, driver, false);
}


void PasswordManager::OnPasswordFormSubmittedNoChecks(
    password_manager::PasswordManagerDriver* driver,
    const PasswordForm& password_form) {
  if (password_manager_util::IsLoggingActive(client_)) {
    BrowserSavePasswordProgressLogger logger(client_->GetLogManager());
    logger.LogMessage(Logger::STRING_ON_SAME_DOCUMENT_NAVIGATION);
  }

  if (gaia::IsGaiaSignonRealm(GURL(password_form.signon_realm)) &&
      !IsThereVisiblePasswordField(password_form.form_data)) {
    // Gaia form without visible password fields is found.
    // It might happen only when Password Manager autofilled a username
    // (visible) and a password (invisible) fields. Then the user typed a new
    // username. A page removed the form. As result a form is inconsistent - the
    // username from one account, the password from another. Skip such form.
    return;
  }

  ProvisionallySaveForm(password_form.form_data, driver, false);

  if (IsAutomaticSavePromptAvailable())
    OnLoginSuccessful();
}

void PasswordManager::OnUserModifiedNonPasswordField(
    password_manager::PasswordManagerDriver* driver,
    int32_t renderer_id,
    const base::string16& value) {
  // TODO(https://crbug.com/959776): Implemented processing |value| as possible
  // username for username first flow.
}

void PasswordManager::ShowManualFallbackForSaving(
    password_manager::PasswordManagerDriver* driver,
    const PasswordForm& password_form) {
  PasswordFormManager* manager =
      ProvisionallySaveForm(password_form.form_data, driver, true);

  if (manager && password_form.form_data.is_gaia_with_skip_save_password_form) {
    manager->GetMetricsRecorder()
        ->set_user_typed_password_on_chrome_sign_in_page();
  }

  if (!client_->GetProfilePasswordStore()->IsAbleToSavePasswords() ||
      !client_->IsSavingAndFillingEnabled(password_form.origin) ||
      ShouldBlockPasswordForSameOriginButDifferentScheme(
          password_form.origin) ||
      !client_->GetStoreResultFilter()->ShouldSave(password_form)) {
    return;
  }

  auto availability =
      manager ? PasswordManagerMetricsRecorder::FormManagerAvailable::kSuccess
              : PasswordManagerMetricsRecorder::FormManagerAvailable::
                    kMissingManual;
  if (client_ && client_->GetMetricsRecorder())
    client_->GetMetricsRecorder()->RecordFormManagerAvailable(availability);
  if (!manager)
    return;

  // Show the fallback if a prompt or a confirmation bubble should be available.
  bool has_generated_password = manager->HasGeneratedPassword();
  if (ShouldPromptUserToSavePassword(*manager) || has_generated_password) {
    bool is_update = manager->IsPasswordUpdate();
    manager->GetMetricsRecorder()->RecordShowManualFallbackForSaving(
        has_generated_password, is_update);
    client_->ShowManualFallbackForSaving(manager->Clone(),
                                         has_generated_password, is_update);
  } else {
    HideManualFallbackForSaving();
  }
}

void PasswordManager::HideManualFallbackForSaving() {
  client_->HideManualFallbackForSaving();
}

void PasswordManager::OnPasswordFormsParsed(
    password_manager::PasswordManagerDriver* driver,
    const std::vector<PasswordForm>& forms) {
  CreatePendingLoginManagers(driver, forms);

  PasswordGenerationFrameHelper* password_generation_manager =
      driver ? driver->GetPasswordGenerationHelper() : nullptr;
  if (password_generation_manager) {
    password_generation_manager->PrefetchSpec(
        client_->GetLastCommittedEntryURL().GetOrigin());
  }
}

void PasswordManager::CreatePendingLoginManagers(
    password_manager::PasswordManagerDriver* driver,
    const std::vector<PasswordForm>& forms) {
  std::unique_ptr<BrowserSavePasswordProgressLogger> logger;
  if (password_manager_util::IsLoggingActive(client_)) {
    logger.reset(
        new BrowserSavePasswordProgressLogger(client_->GetLogManager()));
    logger->LogMessage(Logger::STRING_CREATE_LOGIN_MANAGERS_METHOD);
  }

  CreateFormManagers(driver, forms);

  // Record whether or not this top-level URL has at least one password field.
  client_->AnnotateNavigationEntry(!forms.empty());

  // Only report SSL error status for cases where there are potentially forms to
  // fill or save from.
  if (!forms.empty()) {
    metrics_util::CertificateError cert_error =
        metrics_util::CertificateError::NONE;
    const net::CertStatus cert_status = client_->GetMainFrameCertStatus();
    // The order of the if statements matters -- if the status involves multiple
    // errors, Chrome should report the one highest up in the list below.
    if (cert_status & net::CERT_STATUS_AUTHORITY_INVALID)
      cert_error = metrics_util::CertificateError::AUTHORITY_INVALID;
    else if (cert_status & net::CERT_STATUS_COMMON_NAME_INVALID)
      cert_error = metrics_util::CertificateError::COMMON_NAME_INVALID;
    else if (cert_status & net::CERT_STATUS_WEAK_SIGNATURE_ALGORITHM)
      cert_error = metrics_util::CertificateError::WEAK_SIGNATURE_ALGORITHM;
    else if (cert_status & net::CERT_STATUS_DATE_INVALID)
      cert_error = metrics_util::CertificateError::DATE_INVALID;
    else if (net::IsCertStatusError(cert_status))
      cert_error = metrics_util::CertificateError::OTHER;

    UMA_HISTOGRAM_ENUMERATION(
        "PasswordManager.CertificateErrorsWhileSeeingForms", cert_error,
        metrics_util::CertificateError::COUNT);
  }
}

void PasswordManager::CreateFormManagers(
    password_manager::PasswordManagerDriver* driver,
    const std::vector<PasswordForm>& forms) {
  // Find new forms.
  std::vector<const PasswordForm*> new_forms;
  for (const PasswordForm& form : forms) {
    if (!client_->IsFillingEnabled(form.origin))
      continue;

    PasswordFormManager* manager =
        FindMatchedManager(form.form_data, form_managers_, driver);

    if (manager) {
      // This extra filling is just duplicating redundancy that was in
      // PasswordFormManager, that helps to fix cases when the site overrides
      // filled values.
      // TODO(https://crbug.com/831123): Implement more robust filling and
      // remove the next line.
      manager->FillForm(form.form_data);
    } else {
      new_forms.push_back(&form);
    }
  }

  // Create form manager for new forms.
  for (const PasswordForm* new_form : new_forms) {
    auto* manager = CreateFormManager(driver, new_form->form_data);
    manager->set_old_parsing_result(*new_form);
  }
}

PasswordFormManager* PasswordManager::CreateFormManager(
    PasswordManagerDriver* driver,
    const autofill::FormData& form) {
  form_managers_.push_back(std::make_unique<PasswordFormManager>(
      client_,
      driver ? driver->AsWeakPtr() : base::WeakPtr<PasswordManagerDriver>(),
      form, nullptr,
      std::make_unique<FormSaverImpl>(client_->GetProfilePasswordStore()),
      nullptr));
  form_managers_.back()->ProcessServerPredictions(predictions_);
  return form_managers_.back().get();
}

PasswordFormManager* PasswordManager::ProvisionallySaveForm(
    const FormData& submitted_form,
    PasswordManagerDriver* driver,
    bool is_manual_fallback) {
  std::unique_ptr<BrowserSavePasswordProgressLogger> logger;
  if (password_manager_util::IsLoggingActive(client_)) {
    logger.reset(
        new BrowserSavePasswordProgressLogger(client_->GetLogManager()));
    logger->LogMessage(Logger::STRING_PROVISIONALLY_SAVE_FORM_METHOD);
  }
  if (!client_->IsSavingAndFillingEnabled(submitted_form.url)) {
    RecordProvisionalSaveFailure(
        PasswordManagerMetricsRecorder::SAVING_DISABLED, submitted_form.url,
        logger.get());
    return nullptr;
  }

  if (store_password_called_)
    return nullptr;

  // No need to report PasswordManagerMetricsRecorder::EMPTY_PASSWORD, because
  // PasswordToSave in PasswordFormManager DCHECKs that the password is never
  // empty.

  const GURL& origin = submitted_form.url;
  if (ShouldBlockPasswordForSameOriginButDifferentScheme(origin)) {
    RecordProvisionalSaveFailure(
        PasswordManagerMetricsRecorder::SAVING_ON_HTTP_AFTER_HTTPS, origin,
        logger.get());
    return nullptr;
  }

  PasswordFormManager* matched_manager =
      GetMatchedManager(driver, submitted_form);

  auto availability =
      matched_manager
          ? PasswordManagerMetricsRecorder::FormManagerAvailable::kSuccess
          : PasswordManagerMetricsRecorder::FormManagerAvailable::
                kMissingProvisionallySave;
  if (client_ && client_->GetMetricsRecorder())
    client_->GetMetricsRecorder()->RecordFormManagerAvailable(availability);

  if (!matched_manager) {
    RecordProvisionalSaveFailure(
        PasswordManagerMetricsRecorder::NO_MATCHING_FORM, submitted_form.url,
        logger.get());
    matched_manager = CreateFormManager(driver, submitted_form);
  }

  if (is_manual_fallback && matched_manager->GetFormFetcher()->GetState() ==
                                FormFetcher::State::WAITING) {
    // In case of manual fallback, the form manager has to be ready for saving.
    return nullptr;
  }

  if (!matched_manager->ProvisionallySave(submitted_form, driver))
    return nullptr;

  // Set all other form managers to no submission state.
  for (const auto& manager : form_managers_) {
    if (manager.get() != matched_manager)
      manager->set_not_submitted();
  }

  // Cache the user-visible URL (i.e., the one seen in the omnibox). Once the
  // post-submit navigation concludes, we compare the landing URL against the
  // cached and report the difference through UMA.
  main_frame_url_ = client_->GetMainFrameURL();

  ReportSubmittedFormFrameMetric(driver, *matched_manager->GetSubmittedForm());

  return matched_manager;
}

void PasswordManager::LogFirstFillingResult(PasswordManagerDriver* driver,
                                            uint32_t form_renderer_id,
                                            int32_t result) {
  PasswordFormManager* matching_manager =
      FindMatchedManagerByRendererId(form_renderer_id, form_managers_, driver);
  if (!matching_manager)
    return;
  matching_manager->GetMetricsRecorder()->RecordFirstFillingResult(result);
}

void PasswordManager::NotifyStorePasswordCalled() {
  store_password_called_ = true;
  DropFormManagers();
}

#if defined(OS_IOS)
void PasswordManager::PresaveGeneratedPassword(
    PasswordManagerDriver* driver,
    const FormData& form,
    const base::string16& generated_password,
    const base::string16& generation_element) {
  PasswordFormManager* form_manager =
      FindMatchedManager(form, form_managers_, driver);
  UMA_HISTOGRAM_BOOLEAN("PasswordManager.GeneratedFormHasNoFormManager",
                        !form_manager);

  // TODO(https://crbug.com/886583): Create form manager if not found.
  if (form_manager) {
    form_manager->PresaveGeneratedPassword(driver, form, generated_password,
                                           generation_element);
  }
}

void PasswordManager::UpdateGeneratedPasswordOnUserInput(
    const base::string16& form_identifier,
    const base::string16& field_identifier,
    const base::string16& field_value) {
  for (std::unique_ptr<PasswordFormManager>& manager : form_managers_) {
    if (manager->UpdateGeneratedPasswordOnUserInput(
            form_identifier, field_identifier, field_value)) {
      break;
    }
  }
}

void PasswordManager::OnPasswordNoLongerGenerated(
    PasswordManagerDriver* driver) {
  for (std::unique_ptr<PasswordFormManager>& manager : form_managers_)
    manager->PasswordNoLongerGenerated();
}
#endif

bool PasswordManager::IsAutomaticSavePromptAvailable() {
  std::unique_ptr<BrowserSavePasswordProgressLogger> logger;
  if (password_manager_util::IsLoggingActive(client_)) {
    logger.reset(
        new BrowserSavePasswordProgressLogger(client_->GetLogManager()));
    logger->LogMessage(Logger::STRING_CAN_PROVISIONAL_MANAGER_SAVE_METHOD);
  }

  PasswordFormManagerInterface* submitted_manager = GetSubmittedManager();

  if (!submitted_manager) {
    if (logger) {
      logger->LogMessage(Logger::STRING_NO_PROVISIONAL_SAVE_MANAGER);
    }
    return false;
  }

  if (submitted_manager->GetFormFetcher()->GetState() ==
      FormFetcher::State::WAITING) {
    // We have a provisional save manager, but it didn't finish matching yet.
    // We just give up.
    RecordProvisionalSaveFailure(
        PasswordManagerMetricsRecorder::MATCHING_NOT_COMPLETE,
        submitted_manager->GetOrigin(), logger.get());
    return false;
  }

  return !submitted_manager->GetPendingCredentials().only_for_fallback;
}

bool PasswordManager::ShouldBlockPasswordForSameOriginButDifferentScheme(
    const GURL& origin) const {
  const GURL& old_origin = main_frame_url_.GetOrigin();
  return old_origin.host_piece() == origin.host_piece() &&
         old_origin.SchemeIsCryptographic() && !origin.SchemeIsCryptographic();
}

void PasswordManager::OnPasswordFormsRendered(
    password_manager::PasswordManagerDriver* driver,
    const std::vector<PasswordForm>& visible_forms,
    bool did_stop_loading) {
  CreatePendingLoginManagers(driver, visible_forms);
  std::unique_ptr<BrowserSavePasswordProgressLogger> logger;
  if (password_manager_util::IsLoggingActive(client_)) {
    logger.reset(
        new BrowserSavePasswordProgressLogger(client_->GetLogManager()));
    logger->LogMessage(Logger::STRING_ON_PASSWORD_FORMS_RENDERED_METHOD);
  }

  if (!IsAutomaticSavePromptAvailable())
    return;

  PasswordFormManagerInterface* submitted_manager = GetSubmittedManager();

  // If the server throws an internal error, access denied page, page not
  // found etc. after a login attempt, we do not save the credentials.
  if (client_->WasLastNavigationHTTPError()) {
    if (logger)
      logger->LogMessage(Logger::STRING_DECISION_DROP);
    submitted_manager->GetMetricsRecorder()->LogSubmitFailed();
    owned_submitted_form_manager_.reset();
    return;
  }

  if (logger) {
    logger->LogNumber(Logger::STRING_NUMBER_OF_VISIBLE_FORMS,
                      visible_forms.size());
  }

  // Record all visible forms from the frame.
  all_visible_forms_.insert(all_visible_forms_.end(),
                            visible_forms.begin(),
                            visible_forms.end());

  if (!did_stop_loading &&
      !submitted_manager->GetSubmittedForm()
           ->form_data.is_gaia_with_skip_save_password_form) {
    // |form_data.is_gaia_with_skip_save_password_form| = true means that this
    // is a Chrome sign-in page. Chrome sign-in pages are redirected to an empty
    // pages, and for some reasons |did_stop_loading| might be false. So
    // |did_stop_loading| is ignored for them.
    return;
  }

  // If we see the login form again, then the login failed.
  if (submitted_manager->GetPendingCredentials().scheme ==
      PasswordForm::Scheme::kHtml) {
    for (const PasswordForm& form : all_visible_forms_) {
      if (IsPasswordFormReappeared(
              form, submitted_manager->GetPendingCredentials())) {
        if (submitted_manager->IsPossibleChangePasswordFormWithoutUsername() &&
            AreAllFieldsEmpty(form)) {
          continue;
        }
        submitted_manager->GetMetricsRecorder()->LogSubmitFailed();
        if (logger) {
          logger->LogPasswordForm(Logger::STRING_PASSWORD_FORM_REAPPEARED,
                                  form);
          logger->LogMessage(Logger::STRING_DECISION_DROP);
        }
        owned_submitted_form_manager_.reset();
        // Clear all_visible_forms_ once we found the match.
        all_visible_forms_.clear();
        return;
      }
    }
  } else {
    if (logger)
      logger->LogMessage(Logger::STRING_PROVISIONALLY_SAVED_FORM_IS_NOT_HTML);
  }

  // Clear all_visible_forms_ after checking all the visible forms.
  all_visible_forms_.clear();

  // Looks like a successful login attempt. Either show an infobar or
  // automatically save the login data. We prompt when the user hasn't
  // already given consent, either through previously accepting the infobar
  // or by having the browser generate the password.
  OnLoginSuccessful();
}

void PasswordManager::OnLoginSuccessful() {
  std::unique_ptr<BrowserSavePasswordProgressLogger> logger;
  if (password_manager_util::IsLoggingActive(client_)) {
    logger.reset(
        new BrowserSavePasswordProgressLogger(client_->GetLogManager()));
    logger->LogMessage(Logger::STRING_ON_ASK_USER_OR_SAVE_PASSWORD);
  }

  PasswordFormManagerInterface* submitted_manager = GetSubmittedManager();
  DCHECK(submitted_manager);
  DCHECK(submitted_manager->GetSubmittedForm());

  client_->GetStoreResultFilter()->ReportFormLoginSuccess(*submitted_manager);
#if !defined(OS_IOS)
  leak_delegate_.StartLeakCheck(submitted_manager->GetPendingCredentials());
#endif

  auto submission_event =
      submitted_manager->GetSubmittedForm()->submission_event;
  metrics_util::LogPasswordSuccessfulSubmissionIndicatorEvent(submission_event);
  if (logger)
    logger->LogSuccessfulSubmissionIndicatorEvent(submission_event);

  bool able_to_save_passwords =
      client_->GetProfilePasswordStore()->IsAbleToSavePasswords();
  UMA_HISTOGRAM_BOOLEAN("PasswordManager.AbleToSavePasswordsOnSuccessfulLogin",
                        able_to_save_passwords);
  if (!able_to_save_passwords)
    return;

  MaybeSavePasswordHash(submitted_manager);

  // TODO(https://crbug.com/831123): Implement checking whether to save with
  // PasswordFormManager.
  if (!client_->GetStoreResultFilter()->ShouldSave(
          *submitted_manager->GetSubmittedForm())) {
    RecordProvisionalSaveFailure(
        PasswordManagerMetricsRecorder::SYNC_CREDENTIAL,
        submitted_manager->GetOrigin(), logger.get());
    owned_submitted_form_manager_.reset();
    return;
  }

  submitted_manager->GetMetricsRecorder()->LogSubmitPassed();

  UMA_HISTOGRAM_BOOLEAN(
      "PasswordManager.SuccessfulLoginHappened",
      submitted_manager->GetSubmittedForm()->origin.SchemeIsCryptographic());

  // If the form is eligible only for saving fallback, it shouldn't go here.
  DCHECK(!submitted_manager->GetPendingCredentials().only_for_fallback);

  if (ShouldPromptUserToSavePassword(*submitted_manager)) {
    if (logger)
      logger->LogMessage(Logger::STRING_DECISION_ASK);
    bool update_password = submitted_manager->IsPasswordUpdate();
    bool is_blacklisted = submitted_manager->IsBlacklisted();
    SyncState password_sync_state = client_->GetPasswordSyncState();
    if (ShouldShowOnboarding(
            client_->GetPrefs(), PasswordUpdateBool(update_password),
            BlacklistedBool(is_blacklisted), password_sync_state)) {
      if (client_->ShowOnboarding(MoveOwnedSubmittedManager())) {
        if (logger)
          logger->LogMessage(Logger::STRING_SHOW_ONBOARDING);
      }
    } else if (client_->PromptUserToSaveOrUpdatePassword(
                   MoveOwnedSubmittedManager(), update_password)) {
      if (logger)
        logger->LogMessage(Logger::STRING_SHOW_PASSWORD_PROMPT);
    }
  } else {
    if (logger)
      logger->LogMessage(Logger::STRING_DECISION_SAVE);
    submitted_manager->Save();

    if (!submitted_manager->IsNewLogin()) {
      client_->NotifySuccessfulLoginWithExistingPassword(
          submitted_manager->GetPendingCredentials());
    }

    if (submitted_manager->HasGeneratedPassword())
      client_->AutomaticPasswordSave(MoveOwnedSubmittedManager());
  }
  owned_submitted_form_manager_.reset();
}

void PasswordManager::MaybeSavePasswordHash(
    PasswordFormManagerInterface* submitted_manager) {
#if defined(SYNC_PASSWORD_REUSE_DETECTION_ENABLED)
  const PasswordForm* submitted_form = submitted_manager->GetSubmittedForm();
  // When |username_value| is empty, it's not clear whether the submitted
  // credentials are really Gaia or enterprise credentials. Don't save
  // password hash in that case.
  std::string username = base::UTF16ToUTF8(submitted_form->username_value);
  if (username.empty())
    return;

  password_manager::PasswordStore* store = client_->GetProfilePasswordStore();
  // May be null in tests.
  if (!store)
    return;

  bool should_save_enterprise_pw =
      client_->GetStoreResultFilter()->ShouldSaveEnterprisePasswordHash(
          *submitted_form);
  bool should_save_gaia_pw =
      client_->GetStoreResultFilter()->ShouldSaveGaiaPasswordHash(
          *submitted_form);

  if (!should_save_enterprise_pw && !should_save_gaia_pw)
    return;

  if (submitted_form->form_data.is_gaia_with_skip_save_password_form) {
    submitted_manager->GetMetricsRecorder()
        ->set_password_hash_saved_on_chrome_sing_in_page();
  }

  if (password_manager_util::IsLoggingActive(client_)) {
    BrowserSavePasswordProgressLogger logger(client_->GetLogManager());
    logger.LogMessage(Logger::STRING_SAVE_PASSWORD_HASH);
  }

  // Canonicalizes username if it is an email.
  if (username.find('@') != std::string::npos)
    username = gaia::CanonicalizeEmail(username);
  bool is_password_change = !submitted_form->new_password_element.empty();
  const base::string16 password = is_password_change
                                      ? submitted_form->new_password_value
                                      : submitted_form->password_value;

  if (should_save_enterprise_pw) {
    store->SaveEnterprisePasswordHash(username, password);
    return;
  }

  DCHECK(should_save_gaia_pw);
  GaiaPasswordHashChange event =
      client_->GetStoreResultFilter()->IsSyncAccountEmail(username)
          ? (is_password_change
                 ? GaiaPasswordHashChange::CHANGED_IN_CONTENT_AREA
                 : GaiaPasswordHashChange::SAVED_IN_CONTENT_AREA)
          : GaiaPasswordHashChange::NOT_SYNC_PASSWORD_CHANGE;
  store->SaveGaiaPasswordHash(username, password, event);
#endif
}

void PasswordManager::ProcessAutofillPredictions(
    PasswordManagerDriver* driver,
    const std::vector<FormStructure*>& forms) {
  std::unique_ptr<BrowserSavePasswordProgressLogger> logger;
  if (password_manager_util::IsLoggingActive(client_)) {
    logger.reset(
        new BrowserSavePasswordProgressLogger(client_->GetLogManager()));
  }

    for (const FormStructure* form : forms)
      predictions_[form->form_signature()] = ConvertToFormPredictions(*form);
    for (auto& manager : form_managers_)
      manager->ProcessServerPredictions(predictions_);

    // Create form managers for non-password forms with single usernames.
    for (const FormStructure* form : forms) {
      if (form->has_password_field())
        continue;

      // Do not skip the form if it either contains a field for the Username
      // first flow or a clear-text password field.
      if (!(HasSingleUsernameVote(*form) || HasNewPasswordVote(*form)))
        continue;

      if (FindMatchedManagerByRendererId(form->unique_renderer_id(),
                                         form_managers_, driver)) {
        // The form manager is already created.
        continue;
      }

      FormData form_data = form->ToFormData();
      auto* manager = CreateFormManager(driver, form_data);
      manager->ProcessServerPredictions(predictions_);
    }

}

PasswordFormManagerInterface* PasswordManager::GetSubmittedManager() const {
  if (owned_submitted_form_manager_)
    return owned_submitted_form_manager_.get();

  for (const std::unique_ptr<PasswordFormManager>& manager : form_managers_) {
    if (manager->is_submitted())
      return manager.get();
  }

  return nullptr;
}

std::unique_ptr<PasswordFormManagerForUI>
PasswordManager::MoveOwnedSubmittedManager() {
  if (owned_submitted_form_manager_)
    return std::move(owned_submitted_form_manager_);

  for (auto iter = form_managers_.begin(); iter != form_managers_.end();
       ++iter) {
    if ((*iter)->is_submitted()) {
      std::unique_ptr<PasswordFormManager> submitted_manager = std::move(*iter);
      form_managers_.erase(iter);
      return std::move(submitted_manager);
    }
  }

  NOTREACHED();
  return nullptr;
}

void PasswordManager::RecordProvisionalSaveFailure(
    PasswordManagerMetricsRecorder::ProvisionalSaveFailure failure,
    const GURL& form_origin,
    BrowserSavePasswordProgressLogger* logger) {
  if (client_ && client_->GetMetricsRecorder()) {
    client_->GetMetricsRecorder()->RecordProvisionalSaveFailure(
        failure, main_frame_url_, form_origin, logger);
  }
}

// TODO(https://crbug.com/831123): Implement creating missing
// PasswordFormManager when PasswordFormManager is gone.
PasswordFormManagerInterface* PasswordManager::GetMatchedManager(
    const PasswordManagerDriver* driver,
    const PasswordForm& form) {
  return GetMatchedManager(driver, form.form_data);
}

PasswordFormManager* PasswordManager::GetMatchedManager(
    const PasswordManagerDriver* driver,
    const FormData& form) {
  for (auto& form_manager : form_managers_) {
    if (form_manager->DoesManage(form, driver))
      return form_manager.get();
  }
  return nullptr;
}

void PasswordManager::ReportSubmittedFormFrameMetric(
    const PasswordManagerDriver* driver,
    const PasswordForm& form) {
  if (!driver)
    return;
  metrics_util::SubmittedFormFrame frame;
  if (driver->IsMainFrame()) {
    frame = metrics_util::SubmittedFormFrame::MAIN_FRAME;
  } else if (form.origin == main_frame_url_) {
    frame =
        metrics_util::SubmittedFormFrame::IFRAME_WITH_SAME_URL_AS_MAIN_FRAME;
  } else {
    GURL::Replacements rep;
    rep.SetPathStr("");
    std::string main_frame_signon_realm =
        main_frame_url_.ReplaceComponents(rep).spec();
    frame = (main_frame_signon_realm == form.signon_realm)
                ? metrics_util::SubmittedFormFrame::
                      IFRAME_WITH_DIFFERENT_URL_SAME_SIGNON_REALM_AS_MAIN_FRAME
                : metrics_util::SubmittedFormFrame::
                      IFRAME_WITH_DIFFERENT_SIGNON_REALM;
  }
  metrics_util::LogSubmittedFormFrame(frame);
}

}  // namespace password_manager
