// 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 <map>
#include <memory>
#include <set>
#include <utility>

#include "base/feature_list.h"
#include "base/macros.h"
#include "base/message_loop/message_loop.h"
#include "base/metrics/metrics_hashes.h"
#include "base/strings/string_piece.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/metrics/user_action_tester.h"
#include "base/test/scoped_feature_list.h"
#include "components/autofill/core/browser/autofill_experiments.h"
#include "components/autofill/core/browser/autofill_manager.h"
#include "components/autofill/core/browser/proto/server.pb.h"
#include "components/autofill/core/browser/test_autofill_client.h"
#include "components/autofill/core/browser/test_autofill_driver.h"
#include "components/autofill/core/browser/test_personal_data_manager.h"
#include "components/autofill/core/common/autofill_features.h"
#include "components/autofill/core/common/autofill_prefs.h"
#include "components/autofill/core/common/password_form.h"
#include "components/password_manager/core/browser/fake_form_fetcher.h"
#include "components/password_manager/core/browser/password_manager.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_test_utils.h"
#include "components/password_manager/core/browser/statistics_table.h"
#include "components/password_manager/core/browser/stub_credentials_filter.h"
#include "components/password_manager/core/browser/stub_form_saver.h"
#include "components/password_manager/core/browser/stub_password_manager_client.h"
#include "components/password_manager/core/browser/stub_password_manager_driver.h"
#include "components/password_manager/core/browser/vote_uploads_test_matchers.h"
#include "components/password_manager/core/common/password_manager_features.h"
#include "components/password_manager/core/common/password_manager_pref_names.h"
#include "components/prefs/pref_registry_simple.h"
#include "components/prefs/pref_service.h"
#include "components/prefs/testing_pref_service.h"
#include "components/ukm/test_ukm_recorder.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"
#include "url/origin.h"

using autofill::features::kAutofillEnforceMinRequiredFieldsForHeuristics;
using autofill::features::kAutofillEnforceMinRequiredFieldsForQuery;
using autofill::features::kAutofillEnforceMinRequiredFieldsForUpload;
using autofill::FieldPropertiesFlags;
using autofill::FieldPropertiesMask;
using autofill::PasswordForm;
using autofill::ValueElementPair;
using base::ASCIIToUTF16;
using ::testing::_;
using ::testing::AllOf;
using ::testing::AtMost;
using ::testing::Contains;
using ::testing::ElementsAre;
using ::testing::InSequence;
using ::testing::IsEmpty;
using ::testing::Mock;
using ::testing::NiceMock;
using ::testing::Not;
using ::testing::Pair;
using ::testing::Pointee;
using ::testing::Return;
using ::testing::SaveArg;
using ::testing::SaveArgPointee;
using ::testing::UnorderedElementsAre;
using ::testing::WithArg;

namespace password_manager {

namespace {

// Enum that describes what button the user pressed on the save prompt.
enum SavePromptInteraction { SAVE, NEVER, NO_INTERACTION };

// Creates a form with 2 text fields and 1 password field. The first and second
// fields are username and password respectively. |observed_form| is used for
// default values.
// TODO(crbug.com/824834): The minimal case should be a smaller form.
PasswordForm CreateMinimalCrowdsourcableForm(
    const PasswordForm& observed_form) {
  PasswordForm form = observed_form;
  autofill::FormFieldData field;
  field.name = ASCIIToUTF16("email");
  field.form_control_type = "text";
  form.form_data.fields.push_back(field);
  field.name = ASCIIToUTF16("password");
  field.form_control_type = "password";
  form.form_data.fields.push_back(field);
  field.name = ASCIIToUTF16("petname");
  field.form_control_type = "text";
  form.form_data.fields.push_back(field);
  form.username_element = ASCIIToUTF16("email");
  form.password_element = ASCIIToUTF16("password");
  return form;
}

class MockFormSaver : public StubFormSaver {
 public:
  MockFormSaver() = default;

  ~MockFormSaver() override = default;

  // FormSaver:
  MOCK_METHOD1(PermanentlyBlacklist, void(autofill::PasswordForm* observed));
  MOCK_METHOD2(
      Save,
      void(const autofill::PasswordForm& pending,
           const std::map<base::string16, const PasswordForm*>& best_matches));
  MOCK_METHOD4(
      Update,
      void(const autofill::PasswordForm& pending,
           const std::map<base::string16, const PasswordForm*>& best_matches,
           const std::vector<autofill::PasswordForm>* credentials_to_update,
           const autofill::PasswordForm* old_primary_key));
  MOCK_METHOD3(WipeOutdatedCopies,
               void(const autofill::PasswordForm& pending,
                    std::map<base::string16, const PasswordForm*>* best_matches,
                    const autofill::PasswordForm** preferred_match));
  MOCK_METHOD1(PresaveGeneratedPassword,
               void(const autofill::PasswordForm& generated));
  MOCK_METHOD0(RemovePresavedPassword, void());

  std::unique_ptr<FormSaver> Clone() override {
    return std::make_unique<MockFormSaver>();
  }

  // Convenience downcasting method.
  static MockFormSaver& Get(PasswordFormManager* form_manager) {
    return *static_cast<MockFormSaver*>(form_manager->form_saver());
  }

 private:
  DISALLOW_COPY_AND_ASSIGN(MockFormSaver);
};

class MockFormFetcher : public FakeFormFetcher {
 public:
  MOCK_METHOD1(AddConsumer, void(Consumer*));
  MOCK_METHOD1(RemoveConsumer, void(Consumer*));
  MOCK_METHOD0(Clone, std::unique_ptr<FormFetcher>());
};

MATCHER_P(UsernamePtrIs, username_value, "") {
  if (!arg)
    return false;
  if (arg->username_value != username_value) {
    *result_listener << "has username: " << arg->username_value;
    return false;
  }
  return true;
}

MATCHER_P(PasswordsWereRevealed, revealed, "") {
  return arg.passwords_were_revealed() == revealed;
}

MATCHER_P(HasPasswordAttributesVote, is_vote_expected, "") {
  base::Optional<std::pair<autofill::PasswordAttribute, bool>> vote =
      arg.get_password_attributes_vote_for_testing();
  EXPECT_EQ(is_vote_expected, vote.has_value());
  if (vote.has_value()) {
    size_t reported_length = arg.get_password_length_vote_for_testing();
    EXPECT_LT(0u, reported_length);
    EXPECT_LE(reported_length, 5u /* actual password length */);
  }
  return true;
}

// Matches iff the masks in |expected_field_properties| match the mask in the
// uploaded form exactly.
MATCHER_P(UploadedFieldPropertiesMasksAre, expected_field_properties, "") {
  size_t matched_count = 0;
  bool conflict_found = false;
  for (const auto& field : arg) {
    auto expectation = expected_field_properties.find(field->name);
    if (expectation == expected_field_properties.end())
      continue;

    matched_count++;
    autofill::FieldPropertiesMask expected_mask = expectation->second;

    if (field->properties_mask != expected_mask) {
      *result_listener << (conflict_found ? ", " : "") << field->name
                       << " field: expected mask " << expected_mask
                       << ", but found " << field->properties_mask;
      conflict_found = true;
    }
  }

  if (matched_count != expected_field_properties.size()) {
    *result_listener
        << (conflict_found ? ", " : "")
        << "some expectations did not correspond to an uploaded field";
    conflict_found = true;
  }

  return !conflict_found;
}

class MockAutofillDownloadManager : public autofill::AutofillDownloadManager {
 public:
  MockAutofillDownloadManager(
      autofill::AutofillDriver* driver,
      autofill::AutofillDownloadManager::Observer* observer)
      : AutofillDownloadManager(driver, observer) {}

  MOCK_METHOD5(StartUploadRequest,
               bool(const autofill::FormStructure&,
                    bool,
                    const autofill::ServerFieldTypeSet&,
                    const std::string&,
                    bool));

 private:
  DISALLOW_COPY_AND_ASSIGN(MockAutofillDownloadManager);
};

class MockAutofillManager : public autofill::AutofillManager {
 public:
  MockAutofillManager(autofill::AutofillDriver* driver,
                      autofill::AutofillClient* client,
                      autofill::PersonalDataManager* data_manager)
      : AutofillManager(driver, client, data_manager) {}

  void SetDownloadManager(autofill::AutofillDownloadManager* manager) {
    set_download_manager(manager);
  }

  // Workaround for std::unique_ptr<> lacking a copy constructor.
  bool MaybeStartVoteUploadProcess(
      std::unique_ptr<FormStructure> form_structure,
      const base::TimeTicks& timestamp,
      bool observed_submission) override {
    MaybeStartVoteUploadProcessPtr(form_structure.release(), timestamp,
                                   observed_submission);
    return true;
  }

  MOCK_METHOD3(MaybeStartVoteUploadProcessPtr,
               void(FormStructure*, const base::TimeTicks&, bool));

 private:
  DISALLOW_COPY_AND_ASSIGN(MockAutofillManager);
};

class MockPasswordManagerDriver : public StubPasswordManagerDriver {
 public:
  MockPasswordManagerDriver()
      : mock_autofill_manager_(&test_autofill_driver_,
                               &test_autofill_client_,
                               &test_personal_data_manager_) {
    std::unique_ptr<TestingPrefServiceSimple> prefs(
        new TestingPrefServiceSimple());
    prefs->registry()->RegisterBooleanPref(
        autofill::prefs::kAutofillCreditCardEnabled, true);
    prefs->registry()->RegisterBooleanPref(
        autofill::prefs::kAutofillProfileEnabled, true);
    test_autofill_client_.SetPrefs(std::move(prefs));
    mock_autofill_download_manager_ = new MockAutofillDownloadManager(
        &test_autofill_driver_, &mock_autofill_manager_);
    // AutofillManager takes ownership of |mock_autofill_download_manager_|.
    mock_autofill_manager_.SetDownloadManager(mock_autofill_download_manager_);
  }

  ~MockPasswordManagerDriver() override {}

  MOCK_METHOD1(FillPasswordForm, void(const autofill::PasswordFormFillData&));
  MOCK_METHOD0(InformNoSavedCredentials, void());
  MOCK_METHOD1(ShowInitialPasswordAccountSuggestions,
               void(const autofill::PasswordFormFillData&));
  MOCK_METHOD1(AllowPasswordGenerationForForm,
               void(const autofill::PasswordForm&));

  MockAutofillManager* mock_autofill_manager() {
    return &mock_autofill_manager_;
  }

  MockAutofillDownloadManager* mock_autofill_download_manager() {
    return mock_autofill_download_manager_;
  }

 private:
  autofill::TestAutofillDriver test_autofill_driver_;
  autofill::TestAutofillClient test_autofill_client_;
  autofill::TestPersonalDataManager test_personal_data_manager_;
  MockAutofillDownloadManager* mock_autofill_download_manager_;

  NiceMock<MockAutofillManager> mock_autofill_manager_;
};

class TestPasswordManagerClient : public StubPasswordManagerClient {
 public:
  TestPasswordManagerClient()
      : driver_(new NiceMock<MockPasswordManagerDriver>) {
    prefs_ = std::make_unique<TestingPrefServiceSimple>();
    prefs_->registry()->RegisterBooleanPref(prefs::kCredentialsEnableService,
                                            true);
  }

  PrefService* GetPrefs() const override { return prefs_.get(); }

  MockPasswordManagerDriver* mock_driver() { return driver_.get(); }

  base::WeakPtr<PasswordManagerDriver> driver() { return driver_->AsWeakPtr(); }

  autofill::AutofillManager* GetAutofillManagerForMainFrame() override {
    return mock_driver()->mock_autofill_manager();
  }

  void KillDriver() { driver_.reset(); }

  const GURL& GetMainFrameURL() const override {
    static GURL url("https://www.example.com");
    return url;
  }

 private:
  std::unique_ptr<TestingPrefServiceSimple> prefs_;
  std::unique_ptr<MockPasswordManagerDriver> driver_;
};

ACTION_P(SaveToUniquePtr, scoped) {
  scoped->reset(arg0);
}

}  // namespace

class PasswordFormManagerTest : public testing::Test {
 public:
  PasswordFormManagerTest() { fake_form_fetcher_.Fetch(); }

  void SetUp() override {
    observed_form_.origin = GURL("http://accounts.google.com/a/LoginAuth");
    observed_form_.action = GURL("http://accounts.google.com/a/Login");
    observed_form_.username_element = ASCIIToUTF16("Email");
    observed_form_.password_element = ASCIIToUTF16("Passwd");
    observed_form_.submit_element = ASCIIToUTF16("signIn");
    observed_form_.signon_realm = "http://accounts.google.com";
    observed_form_.form_data.name = ASCIIToUTF16("the-form-name");

    saved_match_ = observed_form_;
    saved_match_.origin = GURL("http://accounts.google.com/a/ServiceLoginAuth");
    saved_match_.action = GURL("http://accounts.google.com/a/ServiceLogin");
    saved_match_.preferred = true;
    saved_match_.username_value = ASCIIToUTF16("test@gmail.com");
    saved_match_.password_value = ASCIIToUTF16("test1");
    saved_match_.other_possible_usernames.push_back(ValueElementPair(
        ASCIIToUTF16("test2@gmail.com"), ASCIIToUTF16("full_name")));
    saved_match_.all_possible_passwords = {
        {ASCIIToUTF16("password"), base::string16()},
        {ASCIIToUTF16("password"), ASCIIToUTF16("Passwd")}};

    autofill::FormFieldData field;
    field.label = ASCIIToUTF16("Full name");
    field.name = ASCIIToUTF16("full_name");
    field.form_control_type = "text";
    saved_match_.form_data.fields.push_back(field);

    field.label = ASCIIToUTF16("Email");
    field.name = ASCIIToUTF16("Email");
    field.form_control_type = "text";
    saved_match_.form_data.fields.push_back(field);

    field.label = ASCIIToUTF16("password");
    field.name = ASCIIToUTF16("Passwd");
    field.form_control_type = "password";
    saved_match_.form_data.fields.push_back(field);

    psl_saved_match_ = saved_match_;
    psl_saved_match_.is_public_suffix_match = true;
    psl_saved_match_.origin =
        GURL("http://m.accounts.google.com/a/ServiceLoginAuth");
    psl_saved_match_.action = GURL("http://m.accounts.google.com/a/Login");
    psl_saved_match_.signon_realm = "http://m.accounts.google.com";

    password_manager_.reset(new PasswordManager(&client_));
    form_manager_.reset(new PasswordFormManager(
        password_manager_.get(), &client_, client_.driver(), observed_form_,
        std::make_unique<NiceMock<MockFormSaver>>(), &fake_form_fetcher_));
    form_manager_->Init(nullptr);
  }

  // Save saved_match() for observed_form() where |observed_form_data|,
  // |times_used|, and |status| are used to overwrite the default values for
  // observed_form(). |field_type| is the upload that we expect from saving,
  // with nullptr meaning no upload expected.
  void AccountCreationUploadTest(const autofill::FormData& observed_form_data,
                                 int times_used,
                                 PasswordForm::GenerationUploadStatus status,
                                 const autofill::ServerFieldType* field_type) {
    PasswordForm form(*observed_form());

    form.form_data = observed_form_data;

    FakeFormFetcher fetcher;
    fetcher.Fetch();
    PasswordFormManager form_manager(
        password_manager(), client(), client()->driver(), form,
        std::make_unique<NiceMock<MockFormSaver>>(), &fetcher);
    form_manager.Init(nullptr);
    PasswordForm match = CreateSavedMatch(false);
    match.generation_upload_status = status;
    match.times_used = times_used;

    PasswordForm form_to_save(form);
    form_to_save.preferred = true;
    form_to_save.username_element = ASCIIToUTF16("observed-username-field");
    form_to_save.password_element = ASCIIToUTF16("observed-password-field");
    form_to_save.username_value = match.username_value;
    form_to_save.password_value = match.password_value;

    fetcher.SetNonFederated({&match}, 0u);
    std::string expected_login_signature;
    autofill::FormStructure observed_structure(observed_form_data);
    autofill::FormStructure pending_structure(saved_match()->form_data);
    if (observed_structure.FormSignatureAsStr() !=
            pending_structure.FormSignatureAsStr() &&
        times_used == 0) {
      expected_login_signature = observed_structure.FormSignatureAsStr();
    }
    autofill::ServerFieldTypeSet expected_available_field_types;
    FieldTypeMap expected_types;
    expected_types[ASCIIToUTF16("full_name")] = autofill::UNKNOWN_TYPE;

    // When we're voting for an account creation form, we should also vote
    // for its username field.
    bool expect_username_vote = false;
    if (field_type && *field_type == autofill::ACCOUNT_CREATION_PASSWORD) {
      expected_types[match.username_element] = autofill::USERNAME;
      expected_available_field_types.insert(autofill::USERNAME);
      expect_username_vote = true;
    } else {
      expected_types[match.username_element] = autofill::UNKNOWN_TYPE;
    }

    bool expect_generation_vote = false;
    if (field_type) {
      // Show the password generation popup to check that the generation vote
      // would be ignored.
      form_manager.set_generation_element(saved_match()->password_element);
      form_manager.SetGenerationPopupWasShown(/*shown=*/true,
                                              /*manually_triggered*/ true);
      expect_generation_vote =
          *field_type != autofill::ACCOUNT_CREATION_PASSWORD;

      expected_available_field_types.insert(*field_type);
      expected_types[saved_match()->password_element] = *field_type;
    }

    if (field_type) {
      if (expect_username_vote) {
        EXPECT_CALL(
            *client()->mock_driver()->mock_autofill_download_manager(),
            StartUploadRequest(AllOf(SignatureIsSameAs(*saved_match()),
                                     UploadedAutofillTypesAre(expected_types),
                                     HasGenerationVote(expect_generation_vote),
                                     VoteTypesAre(VoteTypeMap(
                                         {{match.username_element,
                                           autofill::AutofillUploadContents::
                                               Field::CREDENTIALS_REUSED}})),
                                     HasPasswordAttributesVote(false)),
                               false, expected_available_field_types,
                               expected_login_signature, true));
      } else {
        EXPECT_CALL(
            *client()->mock_driver()->mock_autofill_download_manager(),
            StartUploadRequest(AllOf(SignatureIsSameAs(*saved_match()),
                                     UploadedAutofillTypesAre(expected_types),
                                     HasGenerationVote(expect_generation_vote),
                                     HasPasswordAttributesVote(false)),
                               false, expected_available_field_types,
                               expected_login_signature, true));
      }
    } else {
      EXPECT_CALL(*client()->mock_driver()->mock_autofill_download_manager(),
                  StartUploadRequest(_, _, _, _, _))
          .Times(0);
    }
    form_manager.ProvisionallySave(form_to_save);
    form_manager.Save();
    Mock::VerifyAndClearExpectations(
        client()->mock_driver()->mock_autofill_download_manager());
  }

  // Test upload votes on change password forms. |field_type| is a vote that we
  // expect to be uploaded.
  void ChangePasswordUploadTest(autofill::ServerFieldType field_type,
                                bool has_confirmation_field) {
    SCOPED_TRACE(testing::Message()
                 << "field_type=" << field_type
                 << " has_confirmation_field=" << has_confirmation_field);

    // |observed_form_| should have |form_data| in order to be uploaded.
    observed_form()->form_data = saved_match()->form_data;
    // Turn |observed_form_| and  into change password form.
    observed_form()->new_password_element = ASCIIToUTF16("NewPasswd");
    autofill::FormFieldData field;
    field.label = ASCIIToUTF16("NewPasswd");
    field.name = ASCIIToUTF16("NewPasswd");
    field.form_control_type = "password";
    observed_form()->form_data.fields.push_back(field);
    autofill::FormFieldData empty_field;
    observed_form()->form_data.fields.push_back(empty_field);
    if (has_confirmation_field) {
      field.label = ASCIIToUTF16("ConfPwd");
      field.name = ASCIIToUTF16("ConfPwd");
      field.form_control_type = "password";
      observed_form()->form_data.fields.push_back(field);
    }

    FakeFormFetcher fetcher;
    fetcher.Fetch();
    PasswordFormManager form_manager(
        password_manager(), client(), client()->driver(), *observed_form(),
        std::make_unique<NiceMock<MockFormSaver>>(), &fetcher);
    form_manager.Init(nullptr);
    fetcher.SetNonFederated({saved_match()}, 0u);

    // User submits current and new credentials to the observed form.
    PasswordForm submitted_form(*observed_form());
    // credentials.username_element.clear();
    submitted_form.username_value = saved_match()->username_value;
    submitted_form.password_value = saved_match()->password_value;
    submitted_form.new_password_value = ASCIIToUTF16("test2");
    if (has_confirmation_field)
      submitted_form.confirmation_password_element = ASCIIToUTF16("ConfPwd");
    submitted_form.preferred = true;
    form_manager.ProvisionallySave(submitted_form);

    // Successful login. The PasswordManager would instruct PasswordFormManager
    // to update.
    EXPECT_FALSE(form_manager.IsNewLogin());
    EXPECT_FALSE(
        form_manager.is_possible_change_password_form_without_username());

    // By now, the PasswordFormManager should have promoted the new password
    // value already to be the current password, and should no longer maintain
    // any info about the new password value.
    EXPECT_EQ(submitted_form.new_password_value,
              form_manager.GetPendingCredentials().password_value);
    EXPECT_TRUE(
        form_manager.GetPendingCredentials().new_password_value.empty());

    std::map<base::string16, autofill::ServerFieldType> expected_types;
    expected_types[ASCIIToUTF16("full_name")] = autofill::UNKNOWN_TYPE;
    expected_types[observed_form_.username_element] = autofill::UNKNOWN_TYPE;
    expected_types[observed_form_.password_element] = autofill::PASSWORD;
    expected_types[observed_form_.new_password_element] = field_type;
    expected_types[base::string16()] = autofill::UNKNOWN_TYPE;

    autofill::ServerFieldTypeSet expected_available_field_types;
    expected_available_field_types.insert(autofill::PASSWORD);
    expected_available_field_types.insert(field_type);
    if (has_confirmation_field) {
      expected_types[submitted_form.confirmation_password_element] =
          autofill::CONFIRMATION_PASSWORD;
      expected_available_field_types.insert(autofill::CONFIRMATION_PASSWORD);
    }

    std::string expected_login_signature;
    if (field_type == autofill::NEW_PASSWORD) {
      autofill::FormStructure pending_structure(saved_match()->form_data);
      expected_login_signature = pending_structure.FormSignatureAsStr();

      // An unrelated vote that the credentials were used for the first time.
      EXPECT_CALL(
          *client()->mock_driver()->mock_autofill_download_manager(),
          StartUploadRequest(SignatureIsSameAs(submitted_form), _, _, _, _));
    }
    EXPECT_CALL(
        *client()->mock_driver()->mock_autofill_download_manager(),
        StartUploadRequest(
            AllOf(SignatureIsSameAs(*observed_form()),
                  UploadedAutofillTypesAre(expected_types),
                  HasGenerationVote(false), HasPasswordAttributesVote(false)),
            false, expected_available_field_types, expected_login_signature,
            true));

    switch (field_type) {
      case autofill::NEW_PASSWORD:
        form_manager.Update(*saved_match());
        break;
      case autofill::PROBABLY_NEW_PASSWORD:
        form_manager.OnNoInteraction(true /* it is an update */);
        break;
      case autofill::NOT_NEW_PASSWORD:
        form_manager.OnNopeUpdateClicked();
        break;
      default:
        NOTREACHED();
    }
    Mock::VerifyAndClearExpectations(
        client()->mock_driver()->mock_autofill_download_manager());
  }

  autofill::AutofillUploadContents::Field::PasswordGenerationType
  GetExpectedPasswordGenerationType(bool is_manual_generation,
                                    bool is_change_password_form,
                                    bool has_generated_password) {
    if (!has_generated_password)
      return autofill::AutofillUploadContents::Field::IGNORED_GENERATION_POPUP;

    if (is_manual_generation) {
      if (is_change_password_form) {
        return autofill::AutofillUploadContents::Field::
            MANUALLY_TRIGGERED_GENERATION_ON_CHANGE_PASSWORD_FORM;
      } else {
        return autofill::AutofillUploadContents::Field::
            MANUALLY_TRIGGERED_GENERATION_ON_SIGN_UP_FORM;
      }
    } else {
      if (is_change_password_form) {
        return autofill::AutofillUploadContents::Field::
            AUTOMATICALLY_TRIGGERED_GENERATION_ON_CHANGE_PASSWORD_FORM;
      } else {
        return autofill::AutofillUploadContents::Field::
            AUTOMATICALLY_TRIGGERED_GENERATION_ON_SIGN_UP_FORM;
      }
    }
  }

  // The user types username and generates password on SignUp or change password
  // form. The password generation might be triggered automatically or manually.
  // This function checks that correct vote is uploaded on server. The vote must
  // be uploaded regardless of the user's interaction with the prompt.
  void GeneratedVoteUploadTest(bool is_manual_generation,
                               bool is_change_password_form,
                               bool has_generated_password,
                               bool generated_password_changed,
                               SavePromptInteraction interaction) {
    SCOPED_TRACE(testing::Message()
                 << "is_manual_generation=" << is_manual_generation
                 << " is_change_password_form=" << is_change_password_form
                 << " has_generated_password=" << has_generated_password
                 << " generated_password_changed=" << generated_password_changed
                 << " interaction=" << interaction);
    PasswordForm form(*observed_form());
    form.form_data = saved_match()->form_data;

    if (is_change_password_form) {
      // Turn |form| to a change password form.
      form.new_password_element = ASCIIToUTF16("NewPasswd");

      autofill::FormFieldData field;
      field.label = ASCIIToUTF16("password");
      field.name = ASCIIToUTF16("NewPasswd");
      field.form_control_type = "password";
      form.form_data.fields.push_back(field);
    }

    // Create submitted form.
    PasswordForm submitted_form(form);
    submitted_form.preferred = true;
    submitted_form.username_value = saved_match()->username_value;
    submitted_form.password_value = saved_match()->password_value;

    if (is_change_password_form) {
      submitted_form.new_password_value =
          saved_match()->password_value + ASCIIToUTF16("1");
    }

    FakeFormFetcher fetcher;
    fetcher.Fetch();
    PasswordFormManager form_manager(
        password_manager(), client(), client()->driver(), form,
        std::make_unique<NiceMock<MockFormSaver>>(), &fetcher);
    form_manager.Init(nullptr);
    fetcher.SetNonFederated(std::vector<const PasswordForm*>(), 0u);

    autofill::ServerFieldTypeSet expected_available_field_types;
    // Don't send autofill votes if the user didn't press "Save" button.
    if (interaction == SAVE)
      expected_available_field_types.insert(autofill::PASSWORD);

    base::string16 generation_element = is_change_password_form
                                            ? form.new_password_element
                                            : form.password_element;
    form_manager.set_generation_element(generation_element);
    form_manager.SetGenerationPopupWasShown(true, is_manual_generation);
    form_manager.SetHasGeneratedPassword(has_generated_password);
    if (has_generated_password)
      form_manager.SetGeneratedPasswordChanged(generated_password_changed);

    // Figure out expected generation event type.
    autofill::AutofillUploadContents::Field::PasswordGenerationType
        expected_generation_type = GetExpectedPasswordGenerationType(
            is_manual_generation, is_change_password_form,
            has_generated_password);
    std::map<base::string16,
             autofill::AutofillUploadContents::Field::PasswordGenerationType>
        expected_generation_types;
    expected_generation_types[generation_element] = expected_generation_type;

    EXPECT_CALL(
        *client()->mock_driver()->mock_autofill_download_manager(),
        StartUploadRequest(
            AllOf(SignatureIsSameAs(submitted_form),
                  UploadedGenerationTypesAre(expected_generation_types,
                                             generated_password_changed)),
            false, expected_available_field_types, std::string(), true));
    base::HistogramTester histogram_tester;

    form_manager.ProvisionallySave(submitted_form);
    switch (interaction) {
      case SAVE:
        form_manager.Save();
        break;
      case NEVER:
        form_manager.OnNeverClicked();
        break;
      case NO_INTERACTION:
        form_manager.OnNoInteraction(false /* not an update prompt*/);
        break;
    }
    if (has_generated_password) {
      histogram_tester.ExpectUniqueSample(
          "PasswordGeneration.GeneratedPasswordWasEdited",
          generated_password_changed /* sample */, 1);
      histogram_tester.ExpectUniqueSample(
          "PasswordGeneration.IsTriggeredManually",
          is_manual_generation /* sample */, 1);
    }
    Mock::VerifyAndClearExpectations(
        client()->mock_driver()->mock_autofill_download_manager());
  }

  void GeneratedPasswordUkmTest(bool is_manual_generation,
                                bool is_change_password_form,
                                bool has_generated_password,
                                bool generated_password_changed,
                                SavePromptInteraction interaction) {
    SCOPED_TRACE(testing::Message()
                 << "is_manual_generation=" << is_manual_generation
                 << " is_change_password_form=" << is_change_password_form
                 << " has_generated_password=" << has_generated_password
                 << " generated_password_changed=" << generated_password_changed
                 << " interaction=" << interaction);

    ukm::TestAutoSetUkmRecorder test_ukm_recorder;
    test_ukm_recorder.UpdateSourceURL(client()->GetUkmSourceId(),
                                      client()->GetMainFrameURL());

    PasswordForm form(*observed_form());
    form.form_data = saved_match()->form_data;

    if (is_change_password_form) {
      // Turn |form| to a change password form.
      form.new_password_element = ASCIIToUTF16("NewPasswd");

      autofill::FormFieldData field;
      field.label = ASCIIToUTF16("password");
      field.name = ASCIIToUTF16("NewPasswd");
      field.form_control_type = "password";
      form.form_data.fields.push_back(field);
    }

    // Create submitted form.
    PasswordForm submitted_form(form);
    submitted_form.preferred = true;
    submitted_form.username_value = saved_match()->username_value;
    submitted_form.password_value = saved_match()->password_value;

    if (is_change_password_form) {
      submitted_form.new_password_value =
          saved_match()->password_value + ASCIIToUTF16("1");
    }

    FakeFormFetcher fetcher;
    fetcher.Fetch();
    auto metrics_recorder = base::MakeRefCounted<PasswordFormMetricsRecorder>(
        form.origin.SchemeIsCryptographic(), client()->GetUkmSourceId());
    auto form_manager = std::make_unique<PasswordFormManager>(
        password_manager(), client(), client()->driver(), form,
        std::make_unique<NiceMock<MockFormSaver>>(), &fetcher);
    // *Move* the metrics recorder to not hold on to a reference.
    form_manager->Init(std::move(metrics_recorder));
    fetcher.SetNonFederated(std::vector<const PasswordForm*>(), 0u);

    autofill::ServerFieldTypeSet expected_available_field_types;
    // Don't send autofill votes if the user didn't press "Save" button.
    if (interaction == SAVE)
      expected_available_field_types.insert(autofill::PASSWORD);

    base::string16 generation_element = is_change_password_form
                                            ? form.new_password_element
                                            : form.password_element;
    form_manager->set_generation_element(generation_element);
    form_manager->SetGenerationPopupWasShown(true, is_manual_generation);
    form_manager->SetHasGeneratedPassword(has_generated_password);
    if (has_generated_password)
      form_manager->SetGeneratedPasswordChanged(generated_password_changed);

    // Figure out expected generation event type.
    autofill::AutofillUploadContents::Field::PasswordGenerationType
        expected_generation_type = GetExpectedPasswordGenerationType(
            is_manual_generation, is_change_password_form,
            has_generated_password);
    std::map<base::string16,
             autofill::AutofillUploadContents::Field::PasswordGenerationType>
        expected_generation_types;
    expected_generation_types[generation_element] = expected_generation_type;

    EXPECT_CALL(
        *client()->mock_driver()->mock_autofill_download_manager(),
        StartUploadRequest(
            AllOf(SignatureIsSameAs(submitted_form),
                  UploadedGenerationTypesAre(expected_generation_types,
                                             generated_password_changed)),
            false, expected_available_field_types, std::string(), true));
    form_manager->ProvisionallySave(submitted_form);
    switch (interaction) {
      case SAVE:
        form_manager->Save();
        break;
      case NEVER:
        form_manager->OnNeverClicked();
        break;
      case NO_INTERACTION:
        form_manager->OnNoInteraction(false /* not an update prompt*/);
        break;
    }
    // Reset form manager to flush UKM metrics.
    form_manager.reset();

    auto entries = test_ukm_recorder.GetEntriesByName(
        ukm::builders::PasswordForm::kEntryName);
    ASSERT_EQ(1u, entries.size());

    ukm::TestUkmRecorder::ExpectEntryMetric(
        entries[0], ukm::builders::PasswordForm::kGeneration_PopupShownName,
        is_manual_generation
            ? static_cast<int64_t>(
                  password_manager::PasswordFormMetricsRecorder::
                      PasswordGenerationPopupShown::kShownManually)
            : static_cast<int64_t>(
                  password_manager::PasswordFormMetricsRecorder::
                      PasswordGenerationPopupShown::kShownAutomatically));

    ukm::TestUkmRecorder::ExpectEntryMetric(
        entries[0],
        ukm::builders::PasswordForm::kGeneration_GeneratedPasswordName,
        has_generated_password ? 1 : 0);

    if (has_generated_password) {
      ukm::TestUkmRecorder::ExpectEntryMetric(
          entries[0],
          ukm::builders::PasswordForm::
              kGeneration_GeneratedPasswordModifiedName,
          generated_password_changed ? 1 : 0);
    }
    Mock::VerifyAndClearExpectations(
        client()->mock_driver()->mock_autofill_download_manager());
  }

  PasswordForm* observed_form() { return &observed_form_; }
  PasswordForm* saved_match() { return &saved_match_; }
  PasswordForm* psl_saved_match() { return &psl_saved_match_; }
  PasswordForm CreateSavedMatch(bool blacklisted) {
    PasswordForm match = saved_match_;
    match.blacklisted_by_user = blacklisted;
    return match;
  }

  TestPasswordManagerClient* client() { return &client_; }

  PasswordManager* password_manager() { return password_manager_.get(); }

  PasswordFormManager* form_manager() { return form_manager_.get(); }

  FakeFormFetcher* fake_form_fetcher() { return &fake_form_fetcher_; }

  // To spare typing for PasswordFormManager instances which need no driver.
  const base::WeakPtr<PasswordManagerDriver> kNoDriver;

 protected:
  enum class SimulatedManagerAction { NONE, AUTOFILLED, OFFERED, OFFERED_PSL };
  enum class SimulatedSubmitResult { NONE, PASSED, FAILED };
  enum class SuppressedFormType { HTTPS, PSL_MATCH, SAME_ORGANIZATION_NAME };

  PasswordForm CreateSuppressedForm(SuppressedFormType suppression_type,
                                    const char* username,
                                    const char* password,
                                    PasswordForm::Type manual_or_generated) {
    PasswordForm form = *saved_match();
    switch (suppression_type) {
      case SuppressedFormType::HTTPS:
        form.origin = GURL("https://accounts.google.com/a/LoginAuth");
        form.signon_realm = "https://accounts.google.com/";
        break;
      case SuppressedFormType::PSL_MATCH:
        form.origin = GURL("http://other.google.com/");
        form.signon_realm = "http://other.google.com/";
        break;
      case SuppressedFormType::SAME_ORGANIZATION_NAME:
        form.origin = GURL("https://may-or-may-not-be.google.appspot.com/");
        form.signon_realm = "https://may-or-may-not-be.google.appspot.com/";
        break;
    }
    form.type = manual_or_generated;
    form.username_value = ASCIIToUTF16(username);
    form.password_value = ASCIIToUTF16(password);
    return form;
  }

  void SimulateActionsOnHTTPObservedForm(
      FakeFormFetcher* fetcher,
      SimulatedManagerAction manager_action,
      SimulatedSubmitResult submit_result,
      const char* filled_username,
      const char* filled_password,
      const char* submitted_password = nullptr) {
    PasswordFormManager form_manager(
        password_manager(), client(), client()->driver(), *observed_form(),
        std::make_unique<NiceMock<MockFormSaver>>(), fetcher);
    form_manager.Init(nullptr);

    EXPECT_CALL(*client()->mock_driver()->mock_autofill_download_manager(),
                StartUploadRequest(_, _, _, _, _))
        .Times(::testing::AnyNumber());

    PasswordForm http_stored_form = *saved_match();
    http_stored_form.username_value = base::ASCIIToUTF16(filled_username);
    http_stored_form.password_value = base::ASCIIToUTF16(filled_password);
    if (manager_action == SimulatedManagerAction::OFFERED_PSL)
      http_stored_form.is_public_suffix_match = true;

    std::vector<const PasswordForm*> matches;
    if (manager_action != SimulatedManagerAction::NONE)
      matches.push_back(&http_stored_form);

    // Extra mile: kChoose is only recorded if there were multiple
    // logins available and the preferred one was changed.
    PasswordForm http_stored_form2 = http_stored_form;
    if (manager_action == SimulatedManagerAction::OFFERED) {
      http_stored_form.preferred = false;
      http_stored_form2.username_value = ASCIIToUTF16("user-other@gmail.com");
      matches.push_back(&http_stored_form2);
    }

    fetcher->Fetch();
    fetcher->SetNonFederated(matches, 0u);

    if (submit_result != SimulatedSubmitResult::NONE) {
      PasswordForm submitted_form(*observed_form());
      submitted_form.preferred = true;
      submitted_form.username_value = base::ASCIIToUTF16(filled_username);
      submitted_form.password_value =
          submitted_password ? base::ASCIIToUTF16(submitted_password)
                             : base::ASCIIToUTF16(filled_password);

      form_manager.ProvisionallySave(submitted_form);
      if (submit_result == SimulatedSubmitResult::PASSED) {
        form_manager.LogSubmitPassed();
        form_manager.Save();
      } else {
        form_manager.LogSubmitFailed();
      }
    }
  }

 private:
  // Necessary for callbacks, and for TestAutofillDriver.
  base::MessageLoop message_loop_;

  PasswordForm observed_form_;
  PasswordForm saved_match_;
  PasswordForm psl_saved_match_;
  TestPasswordManagerClient client_;
  std::unique_ptr<PasswordManager> password_manager_;
  // Define |fake_form_fetcher_| before |form_manager_|, because the former
  // needs to outlive the latter.
  FakeFormFetcher fake_form_fetcher_;
  std::unique_ptr<PasswordFormManager> form_manager_;
};

class PasswordFormManagerFillOnAccountSelectTest
    : public PasswordFormManagerTest {
 public:
  PasswordFormManagerFillOnAccountSelectTest() {
    scoped_feature_list_.InitAndEnableFeature(features::kFillOnAccountSelect);
  }

  base::test::ScopedFeatureList scoped_feature_list_;
};

// Test provisionally saving a new login.
TEST_F(PasswordFormManagerTest, TestNewLogin) {
  fake_form_fetcher()->SetNonFederated(std::vector<const PasswordForm*>(), 0u);

  // User submits credentials for the observed form.
  PasswordForm credentials = *observed_form();
  credentials.username_value = saved_match()->username_value;
  credentials.password_value = saved_match()->password_value;
  credentials.preferred = true;
  form_manager()->ProvisionallySave(credentials);

  // Successful login. The PasswordManager would instruct PasswordFormManager
  // to save, which should know this is a new login.
  EXPECT_TRUE(form_manager()->IsNewLogin());
  // Make sure the credentials that would be submitted on successful login
  // are going to match the stored entry in the db.
  EXPECT_EQ(observed_form()->origin.spec(),
            form_manager()->GetPendingCredentials().origin.spec());
  EXPECT_EQ(observed_form()->signon_realm,
            form_manager()->GetPendingCredentials().signon_realm);
  EXPECT_EQ(observed_form()->action,
            form_manager()->GetPendingCredentials().action);
  EXPECT_TRUE(form_manager()->GetPendingCredentials().preferred);
  EXPECT_EQ(saved_match()->password_value,
            form_manager()->GetPendingCredentials().password_value);
  EXPECT_EQ(saved_match()->username_value,
            form_manager()->GetPendingCredentials().username_value);
  EXPECT_TRUE(
      form_manager()->GetPendingCredentials().new_password_element.empty());
  EXPECT_TRUE(
      form_manager()->GetPendingCredentials().new_password_value.empty());
}

// Test provisionally saving a new login in presence of other saved logins.
TEST_F(PasswordFormManagerTest, TestAdditionalLogin) {
  fake_form_fetcher()->SetNonFederated({saved_match()}, 0u);

  base::string16 new_user = ASCIIToUTF16("newuser");
  base::string16 new_pass = ASCIIToUTF16("newpass");
  ASSERT_NE(new_user, saved_match()->username_value);

  PasswordForm new_login = *observed_form();
  new_login.username_value = new_user;
  new_login.password_value = new_pass;
  new_login.preferred = true;

  form_manager()->ProvisionallySave(new_login);

  // The username value differs from the saved match, so this is a new login.
  EXPECT_TRUE(form_manager()->IsNewLogin());

  EXPECT_EQ(observed_form()->origin.spec(),
            form_manager()->GetPendingCredentials().origin.spec());
  EXPECT_EQ(observed_form()->signon_realm,
            form_manager()->GetPendingCredentials().signon_realm);
  EXPECT_TRUE(form_manager()->GetPendingCredentials().preferred);
  EXPECT_EQ(new_pass, form_manager()->GetPendingCredentials().password_value);
  EXPECT_EQ(new_user, form_manager()->GetPendingCredentials().username_value);
  EXPECT_TRUE(
      form_manager()->GetPendingCredentials().new_password_element.empty());
  EXPECT_TRUE(
      form_manager()->GetPendingCredentials().new_password_value.empty());
}

// Test blacklisting in the presence of saved results.
TEST_F(PasswordFormManagerTest, TestBlacklist) {
  saved_match()->origin = observed_form()->origin;
  saved_match()->action = observed_form()->action;
  fake_form_fetcher()->SetNonFederated({saved_match()}, 0u);

  PasswordForm new_login = *observed_form();
  new_login.username_value = ASCIIToUTF16("newuser");
  new_login.password_value = ASCIIToUTF16("newpass");
  // Pretend Chrome detected a form submission with |new_login|.
  form_manager()->ProvisionallySave(new_login);

  EXPECT_TRUE(form_manager()->IsNewLogin());
  EXPECT_EQ(observed_form()->origin.spec(),
            form_manager()->GetPendingCredentials().origin.spec());
  EXPECT_EQ(observed_form()->signon_realm,
            form_manager()->GetPendingCredentials().signon_realm);

  const PasswordForm pending_form = form_manager()->GetPendingCredentials();
  PasswordForm actual_add_form;
  // Now pretend the user wants to never save passwords on this origin. Chrome
  // is supposed to only request blacklisting of a single form.
  EXPECT_CALL(MockFormSaver::Get(form_manager()), PermanentlyBlacklist(_))
      .WillOnce(SaveArgPointee<0>(&actual_add_form));
  form_manager()->PermanentlyBlacklist();
  EXPECT_EQ(pending_form, form_manager()->GetPendingCredentials());
  // The PasswordFormManager should have updated its knowledge of blacklisting
  // without waiting for PasswordStore updates.
  EXPECT_TRUE(form_manager()->IsBlacklisted());
  EXPECT_THAT(form_manager()->GetBlacklistedMatches(),
              UnorderedElementsAre(Pointee(actual_add_form)));
}

// Test that stored blacklisted forms are correctly evaluated for whether they
// apply to the observed form.
TEST_F(PasswordFormManagerTest, TestBlacklistMatching) {
  // Doesn't apply because it is just a PSL match of the observed form.
  PasswordForm blacklisted_psl = *observed_form();
  blacklisted_psl.signon_realm = "http://m.accounts.google.com";
  blacklisted_psl.is_public_suffix_match = true;
  blacklisted_psl.blacklisted_by_user = true;

  // Doesn't apply because of different PasswordForm::Scheme.
  PasswordForm blacklisted_not_match = *observed_form();
  blacklisted_not_match.scheme = PasswordForm::SCHEME_BASIC;

  // Applies despite different element names and path.
  PasswordForm blacklisted_match = *observed_form();
  blacklisted_match.origin = GURL("http://accounts.google.com/a/LoginAuth1234");
  blacklisted_match.username_element = ASCIIToUTF16("Element1");
  blacklisted_match.password_element = ASCIIToUTF16("Element2");
  blacklisted_match.submit_element = ASCIIToUTF16("Element3");
  blacklisted_match.blacklisted_by_user = true;

  std::vector<const PasswordForm*> matches = {&blacklisted_psl,
                                              &blacklisted_not_match,
                                              &blacklisted_match,
                                              saved_match()};
  fake_form_fetcher()->SetNonFederated(matches, 0u);

  EXPECT_TRUE(form_manager()->IsBlacklisted());
  EXPECT_THAT(form_manager()->GetBlacklistedMatches(),
              ElementsAre(Pointee(blacklisted_match)));
  EXPECT_EQ(1u, form_manager()->GetBestMatches().size());
  EXPECT_EQ(*saved_match(), *form_manager()->GetPreferredMatch());
}

// Test that even in the presence of blacklisted matches, the non-blacklisted
// ones are still autofilled.
TEST_F(PasswordFormManagerTest, AutofillBlacklisted) {
  PasswordForm saved_form = *observed_form();
  saved_form.username_value = ASCIIToUTF16("user");
  saved_form.password_value = ASCIIToUTF16("pass");

  PasswordForm blacklisted = *observed_form();
  blacklisted.blacklisted_by_user = true;
  blacklisted.username_value.clear();

  autofill::PasswordFormFillData fill_data;
  EXPECT_CALL(*client()->mock_driver(), FillPasswordForm(_))
      .WillOnce(SaveArg<0>(&fill_data));

  fake_form_fetcher()->SetNonFederated({&saved_form, &blacklisted}, 0u);
  EXPECT_EQ(1u, form_manager()->GetBlacklistedMatches().size());
  EXPECT_TRUE(form_manager()->IsBlacklisted());
  EXPECT_EQ(1u, form_manager()->GetBestMatches().size());
  EXPECT_TRUE(fill_data.additional_logins.empty());
}

// If PSL-matched credentials had been suggested, but the user has overwritten
// the password, the provisionally saved credentials should no longer be
// considered as PSL-matched, so that the exception for not prompting before
// saving PSL-matched credentials should no longer apply.
TEST_F(PasswordFormManagerTest,
       OverriddenPSLMatchedCredentialsNotMarkedAsPSLMatched) {
  // The suggestion needs to be PSL-matched.
  fake_form_fetcher()->SetNonFederated({psl_saved_match()}, 0u);

  // User modifies the suggested password and submits the form.
  PasswordForm credentials(*observed_form());
  credentials.username_value = saved_match()->username_value;
  credentials.password_value =
      saved_match()->password_value + ASCIIToUTF16("modify");
  form_manager()->ProvisionallySave(credentials);

  EXPECT_TRUE(form_manager()->IsNewLogin());
  EXPECT_FALSE(form_manager()->IsPendingCredentialsPublicSuffixMatch());
}

// Test that if a PSL-matched suggestion is saved on a new origin, its metadata
// are correctly updated.
TEST_F(PasswordFormManagerTest, PSLMatchedCredentialsMetadataUpdated) {
  PasswordForm psl_suggestion = *saved_match();
  psl_suggestion.is_public_suffix_match = true;
  fake_form_fetcher()->SetNonFederated({&psl_suggestion}, 0u);

  PasswordForm submitted_form(*observed_form());
  submitted_form.preferred = true;
  submitted_form.username_value = saved_match()->username_value;
  submitted_form.password_value = saved_match()->password_value;
  form_manager()->ProvisionallySave(submitted_form);

  PasswordForm expected_saved_form(submitted_form);
  expected_saved_form.times_used = 1;
  expected_saved_form.other_possible_usernames.clear();
  expected_saved_form.form_data = saved_match()->form_data;
  expected_saved_form.origin = observed_form()->origin;
  expected_saved_form.is_public_suffix_match = true;
  PasswordForm actual_saved_form;

  autofill::ServerFieldTypeSet expected_available_field_types;
  expected_available_field_types.insert(autofill::ACCOUNT_CREATION_PASSWORD);
  expected_available_field_types.insert(autofill::USERNAME);
  EXPECT_CALL(
      *client()->mock_driver()->mock_autofill_download_manager(),
      StartUploadRequest(_, false, expected_available_field_types, _, true));
  EXPECT_CALL(MockFormSaver::Get(form_manager()), Save(_, _))
      .WillOnce(SaveArg<0>(&actual_saved_form));
  form_manager()->Save();

  // Can't verify time, so ignore it.
  actual_saved_form.date_created = base::Time();
  EXPECT_EQ(expected_saved_form, actual_saved_form);
}

// Test that when the submitted form contains a "new-password" field, then the
// password value is taken from there.
TEST_F(PasswordFormManagerTest, TestNewLoginFromNewPasswordElement) {
  observed_form()->new_password_element = ASCIIToUTF16("NewPasswd");
  observed_form()->username_marked_by_site = true;

  FakeFormFetcher fetcher;
  fetcher.Fetch();
  PasswordFormManager form_manager(password_manager(), client(),
                                   client()->driver(), *observed_form(),
                                   std::make_unique<MockFormSaver>(), &fetcher);
  form_manager.Init(nullptr);
  fetcher.SetNonFederated(std::vector<const PasswordForm*>(), 0u);

  // User enters current and new credentials to the observed form.
  PasswordForm credentials(*observed_form());
  credentials.username_value = saved_match()->username_value;
  credentials.password_value = ASCIIToUTF16("oldpassword");
  credentials.new_password_value = ASCIIToUTF16("newpassword");
  credentials.preferred = true;
  form_manager.ProvisionallySave(credentials);

  // Successful login. The PasswordManager would instruct PasswordFormManager
  // to save, which should know this is a new login.
  EXPECT_TRUE(form_manager.IsNewLogin());
  EXPECT_EQ(credentials.origin, form_manager.GetPendingCredentials().origin);
  EXPECT_EQ(credentials.signon_realm,
            form_manager.GetPendingCredentials().signon_realm);
  EXPECT_EQ(credentials.action, form_manager.GetPendingCredentials().action);
  EXPECT_TRUE(form_manager.GetPendingCredentials().preferred);
  EXPECT_EQ(credentials.username_value,
            form_manager.GetPendingCredentials().username_value);

  // By this point, the PasswordFormManager should have promoted the new
  // password value to be the current password.
  EXPECT_EQ(credentials.new_password_value,
            form_manager.GetPendingCredentials().password_value);
  EXPECT_EQ(credentials.new_password_element,
            form_manager.GetPendingCredentials().password_element);
  EXPECT_TRUE(form_manager.GetPendingCredentials().new_password_value.empty());
  EXPECT_TRUE(
      form_manager.GetPendingCredentials().new_password_element.empty());
}

TEST_F(PasswordFormManagerTest, TestUpdatePassword) {
  fake_form_fetcher()->SetNonFederated({saved_match()}, 0u);

  // User submits credentials for the observed form using a username previously
  // stored, but a new password. Note that the observed form may have different
  // origin URL (as it does in this case) than the saved_match, but we want to
  // make sure the updated password is reflected in saved_match, because that is
  // what we autofilled.
  base::string16 new_pass = ASCIIToUTF16("test2");
  PasswordForm credentials = *observed_form();
  credentials.username_value = saved_match()->username_value;
  credentials.password_value = new_pass;
  credentials.preferred = true;
  form_manager()->ProvisionallySave(credentials);

  // Successful login. The PasswordManager would instruct PasswordFormManager
  // to save, and since this is an update, it should know not to save as a new
  // login.
  EXPECT_FALSE(form_manager()->IsNewLogin());

  // Make sure the credentials that would be submitted on successful login
  // are going to match the stored entry in the db. (This verifies correct
  // behaviour for bug 1074420).
  EXPECT_EQ(form_manager()->GetPendingCredentials().origin.spec(),
            saved_match()->origin.spec());
  EXPECT_EQ(form_manager()->GetPendingCredentials().signon_realm,
            saved_match()->signon_realm);
  EXPECT_TRUE(form_manager()->GetPendingCredentials().preferred);
  EXPECT_EQ(new_pass, form_manager()->GetPendingCredentials().password_value);
}

TEST_F(PasswordFormManagerTest, TestUpdatePasswordFromNewPasswordElement) {
  // Add a new password field to the test form. The PasswordFormManager should
  // save the password from this field, instead of the current password field.
  observed_form()->new_password_element = ASCIIToUTF16("NewPasswd");

  FakeFormFetcher fetcher;
  fetcher.Fetch();
  PasswordFormManager form_manager(password_manager(), client(),
                                   client()->driver(), *observed_form(),
                                   std::make_unique<MockFormSaver>(), &fetcher);
  form_manager.Init(nullptr);
  fetcher.SetNonFederated({saved_match()}, 0u);

  // User submits current and new credentials to the observed form.
  PasswordForm credentials(*observed_form());
  credentials.username_value = saved_match()->username_value;
  credentials.password_value = saved_match()->password_value;
  credentials.new_password_value = ASCIIToUTF16("test2");
  credentials.preferred = true;
  form_manager.ProvisionallySave(credentials);

  // Successful login. The PasswordManager would instruct PasswordFormManager
  // to save, and since this is an update, it should know not to save as a new
  // login.
  EXPECT_FALSE(form_manager.IsNewLogin());

  // By now, the PasswordFormManager should have promoted the new password value
  // already to be the current password, and should no longer maintain any info
  // about the new password.
  EXPECT_EQ(credentials.new_password_value,
            form_manager.GetPendingCredentials().password_value);
  EXPECT_TRUE(
      form_manager.GetPendingCredentials().new_password_element.empty());
  EXPECT_TRUE(form_manager.GetPendingCredentials().new_password_value.empty());

  // Trigger saving to exercise some special case handling for updating.
  PasswordForm new_credentials;
  EXPECT_CALL(MockFormSaver::Get(&form_manager), Update(_, _, _, nullptr))
      .WillOnce(testing::SaveArg<0>(&new_credentials));

  form_manager.Save();

  // The password should be updated.
  EXPECT_EQ(credentials.new_password_value, new_credentials.password_value);
  EXPECT_EQ(saved_match()->username_element, new_credentials.username_element);
  EXPECT_EQ(saved_match()->password_element, new_credentials.password_element);
  EXPECT_EQ(saved_match()->submit_element, new_credentials.submit_element);
}

// Test that saved results are not ignored if they differ in paths for action or
// origin.
TEST_F(PasswordFormManagerTest, TestIgnoreResult_Paths) {
  PasswordForm observed(*observed_form());
  observed.origin = GURL("https://accounts.google.com/a/LoginAuth");
  observed.action = GURL("https://accounts.google.com/a/Login");
  observed.signon_realm = "https://accounts.google.com";

  FakeFormFetcher fetcher;
  fetcher.Fetch();
  PasswordFormManager form_manager(password_manager(), client(),
                                   client()->driver(), observed,
                                   std::make_unique<MockFormSaver>(), &fetcher);
  form_manager.Init(nullptr);

  PasswordForm saved_form = observed;
  saved_form.origin = GURL("https://accounts.google.com/a/OtherLoginAuth");
  saved_form.action = GURL("https://accounts.google.com/a/OtherLogin");
  fetcher.SetNonFederated({&saved_form}, 0u);

  // Different paths for action / origin are okay.
  EXPECT_EQ(1u, form_manager.GetBestMatches().size());
  EXPECT_EQ(*form_manager.GetBestMatches().begin()->second, saved_form);
}

// Test that saved empty action URL is updated with the submitted action URL.
TEST_F(PasswordFormManagerTest, TestEmptyAction) {
  saved_match()->action = GURL();
  fake_form_fetcher()->SetNonFederated({saved_match()}, 0u);

  // User logs in with the autofilled username / password from saved_match.
  PasswordForm login = *observed_form();
  login.username_value = saved_match()->username_value;
  login.password_value = saved_match()->password_value;
  form_manager()->ProvisionallySave(login);
  EXPECT_FALSE(form_manager()->IsNewLogin());
  // Chrome updates the saved PasswordForm entry with the action URL of the
  // observed form.
  EXPECT_EQ(observed_form()->action,
            form_manager()->GetPendingCredentials().action);
}

TEST_F(PasswordFormManagerTest, TestUpdateAction) {
  saved_match()->action = GURL("http://accounts.google.com/a/ServiceLogin");
  fake_form_fetcher()->SetNonFederated({saved_match()}, 0u);

  // User logs in with the autofilled username / password from saved_match.
  observed_form()->action = GURL("http://accounts.google.com/a/Login");
  PasswordForm login = *observed_form();
  login.username_value = saved_match()->username_value;
  login.password_value = saved_match()->password_value;

  form_manager()->ProvisionallySave(login);
  EXPECT_FALSE(form_manager()->IsNewLogin());
  // The observed action URL is different from the previously saved one. Chrome
  // should update the store by setting the pending credential's action URL to
  // be that of the currently observed form.
  EXPECT_EQ(observed_form()->action,
            form_manager()->GetPendingCredentials().action);
}

TEST_F(PasswordFormManagerTest, TestDynamicAction) {
  fake_form_fetcher()->SetNonFederated(std::vector<const PasswordForm*>(), 0u);

  observed_form()->action = GURL("http://accounts.google.com/a/Login");
  PasswordForm login(*observed_form());
  // The submitted action URL is different from the one observed on page load.
  login.action = GURL("http://www.google.com/new_action");

  form_manager()->ProvisionallySave(login);
  EXPECT_TRUE(form_manager()->IsNewLogin());
  // Check that the provisionally saved action URL is the same as the submitted
  // action URL, not the one observed on page load.
  EXPECT_EQ(login.action, form_manager()->GetPendingCredentials().action);
}

// Test that if the saved match has other possible usernames stored, and the
// user chooses the main one, then the other possible usernames are dropped on
// update.
TEST_F(PasswordFormManagerTest, TestAlternateUsername_NoChange) {
  EXPECT_CALL(*client()->mock_driver(), AllowPasswordGenerationForForm(_));

  PasswordForm saved_form = *saved_match();
  saved_form.other_possible_usernames.push_back(
      ValueElementPair(ASCIIToUTF16("other_possible@gmail.com"),
                       ASCIIToUTF16("other_username")));

  fake_form_fetcher()->SetNonFederated({&saved_form}, 0u);

  // The saved match has the right username already.
  PasswordForm login(*observed_form());
  login.preferred = true;
  login.username_value = saved_match()->username_value;
  login.password_value = saved_match()->password_value;

  form_manager()->ProvisionallySave(login);

  EXPECT_FALSE(form_manager()->IsNewLogin());

  PasswordForm saved_result;
  EXPECT_CALL(MockFormSaver::Get(form_manager()), Update(_, _, _, nullptr))
      .WillOnce(SaveArg<0>(&saved_result));
  EXPECT_CALL(*client()->mock_driver()->mock_autofill_download_manager(),
              StartUploadRequest(_, false, _, _, true));

  form_manager()->Save();
  // Should be only one password stored, and should not have
  // |other_possible_usernames| set anymore.
  EXPECT_EQ(saved_match()->username_value, saved_result.username_value);
  EXPECT_TRUE(saved_result.other_possible_usernames.empty());
}

TEST_F(PasswordFormManagerTest, TestSendNotBlacklistedMessage_NoCredentials) {
  // First time sign-up attempt. Password store does not contain matching
  // credentials. AllowPasswordGenerationForForm should be called to send the
  // "not blacklisted" message.
  EXPECT_CALL(*(client()->mock_driver()), AllowPasswordGenerationForForm(_));
  fake_form_fetcher()->SetNonFederated(std::vector<const PasswordForm*>(), 0u);
}

TEST_F(PasswordFormManagerTest, TestSendNotBlacklistedMessage_Credentials) {
  // Signing up on a previously visited site. Credentials are found in the
  // password store, and are not blacklisted. AllowPasswordGenerationForForm
  // should be called to send the "not blacklisted" message.
  EXPECT_CALL(*(client()->mock_driver()), AllowPasswordGenerationForForm(_));
  PasswordForm simulated_result = CreateSavedMatch(false);
  fake_form_fetcher()->SetNonFederated({&simulated_result}, 0u);
}

TEST_F(PasswordFormManagerTest,
       TestSendNotBlacklistedMessage_DroppedCredentials) {
  // There are cases, such as when a form is made explicitly for creating a new
  // password, where we may ignore saved credentials. Make sure that we still
  // allow generation in that case.
  PasswordForm signup_form(*observed_form());
  signup_form.new_password_element = base::ASCIIToUTF16("new_password_field");

  FakeFormFetcher fetcher;
  fetcher.Fetch();
  PasswordFormManager form_manager(password_manager(), client(),
                                   client()->driver(), signup_form,
                                   std::make_unique<MockFormSaver>(), &fetcher);
  form_manager.Init(nullptr);
  EXPECT_CALL(*(client()->mock_driver()), AllowPasswordGenerationForForm(_));
  PasswordForm simulated_result = CreateSavedMatch(false);
  fetcher.SetNonFederated({&simulated_result}, 0u);
}

// Test that exactly one match for each username is chosen as a best match, even
// though it is a PSL match.
TEST_F(PasswordFormManagerTest, TestBestCredentialsForEachUsernameAreIncluded) {
  // Add a best scoring match. It should be in |best_matches| and chosen as a
  // prefferred match.
  PasswordForm best_scoring = *saved_match();

  // Add a match saved on another form, it has lower score. It should not be in
  // |best_matches|.
  PasswordForm other_form = *saved_match();
  other_form.password_element = ASCIIToUTF16("signup_password");
  other_form.username_element = ASCIIToUTF16("signup_username");

  // Add a match saved on another form with a different username. It should be
  // in |best_matches|.
  PasswordForm other_username = other_form;
  const base::string16 kUsername1 =
      other_username.username_value + ASCIIToUTF16("1");
  other_username.username_value = kUsername1;

  // Add a PSL match, it should not be in |best_matches|.
  PasswordForm psl_match = *psl_saved_match();

  // Add a PSL match with a different username. It should be in |best_matches|.
  PasswordForm psl_match_other = psl_match;
  const base::string16 kUsername2 =
      psl_match_other.username_value + ASCIIToUTF16("2");
  psl_match_other.username_value = kUsername2;

  autofill::PasswordFormFillData fill_data;
  EXPECT_CALL(*client()->mock_driver(), FillPasswordForm(_))
      .WillOnce(SaveArg<0>(&fill_data));

  fake_form_fetcher()->SetNonFederated(
      {&best_scoring, &other_form, &other_username, &psl_match,
       &psl_match_other},
      0u);

  const std::map<base::string16, const PasswordForm*>& best_matches =
      form_manager()->GetBestMatches();
  EXPECT_EQ(3u, best_matches.size());
  EXPECT_NE(best_matches.end(),
            best_matches.find(saved_match()->username_value));
  EXPECT_EQ(*saved_match(),
            *best_matches.find(saved_match()->username_value)->second);
  EXPECT_NE(best_matches.end(), best_matches.find(kUsername1));
  EXPECT_NE(best_matches.end(), best_matches.find(kUsername2));

  EXPECT_EQ(*saved_match(), *form_manager()->GetPreferredMatch());
  EXPECT_EQ(2u, fill_data.additional_logins.size());
}

TEST_F(PasswordFormManagerTest, TestSanitizePossibleUsernames) {
  const ValueElementPair kUsernameOther(ASCIIToUTF16("other username"),
                                        ASCIIToUTF16("other_username_id"));

  fake_form_fetcher()->SetNonFederated(std::vector<const PasswordForm*>(), 0u);

  PasswordForm credentials(*observed_form());
  credentials.other_possible_usernames.push_back(
      ValueElementPair(ASCIIToUTF16("543-43-1234"), ASCIIToUTF16("id1")));
  credentials.other_possible_usernames.push_back(
      ValueElementPair(ASCIIToUTF16("378282246310005"), ASCIIToUTF16("id2")));
  credentials.other_possible_usernames.push_back(kUsernameOther);
  credentials.username_value = ASCIIToUTF16("test@gmail.com");
  credentials.preferred = true;

  form_manager()->ProvisionallySave(credentials);

  PasswordForm saved_result;
  EXPECT_CALL(MockFormSaver::Get(form_manager()), Save(_, _))
      .WillOnce(SaveArg<0>(&saved_result));
  form_manager()->Save();

  // Possible credit card number and SSN are stripped.
  EXPECT_THAT(saved_result.other_possible_usernames,
              UnorderedElementsAre(kUsernameOther));
}

TEST_F(PasswordFormManagerTest, TestSanitizePossibleUsernamesDuplicates) {
  const ValueElementPair kUsernameSsn(ASCIIToUTF16("511-32-9830"),
                                      ASCIIToUTF16("ssn_id"));
  const ValueElementPair kUsernameEmail(ASCIIToUTF16("test@gmail.com"),
                                        ASCIIToUTF16("email_id"));
  const ValueElementPair kUsernameDuplicate(ASCIIToUTF16("duplicate"),
                                            ASCIIToUTF16("duplicate_id"));
  const ValueElementPair kUsernameRandom(ASCIIToUTF16("random"),
                                         ASCIIToUTF16("random_id"));

  fake_form_fetcher()->SetNonFederated(std::vector<const PasswordForm*>(), 0u);

  PasswordForm credentials(*observed_form());
  credentials.other_possible_usernames.push_back(kUsernameSsn);
  credentials.other_possible_usernames.push_back(kUsernameDuplicate);
  credentials.other_possible_usernames.push_back(kUsernameDuplicate);
  credentials.other_possible_usernames.push_back(kUsernameRandom);
  credentials.other_possible_usernames.push_back(kUsernameEmail);
  credentials.username_value = kUsernameEmail.first;
  credentials.preferred = true;

  form_manager()->ProvisionallySave(credentials);

  PasswordForm saved_result;
  EXPECT_CALL(MockFormSaver::Get(form_manager()), Save(_, _))
      .WillOnce(SaveArg<0>(&saved_result));
  form_manager()->Save();

  // SSN, duplicate in |other_possible_usernames| and duplicate of
  // |username_value| all removed.
  EXPECT_THAT(saved_result.other_possible_usernames,
              UnorderedElementsAre(kUsernameDuplicate, kUsernameRandom));
}

TEST_F(PasswordFormManagerTest, TestAllPossiblePasswords) {
  fake_form_fetcher()->SetNonFederated(std::vector<const PasswordForm*>(), 0u);

  ValueElementPair pair1 = {ASCIIToUTF16("pass1"), ASCIIToUTF16("el1")};
  ValueElementPair pair2 = {ASCIIToUTF16("pass2"), ASCIIToUTF16("el2")};
  ValueElementPair pair3 = {ASCIIToUTF16("pass3"), ASCIIToUTF16("el3")};

  PasswordForm credentials(*observed_form());
  credentials.all_possible_passwords.push_back(pair1);
  credentials.all_possible_passwords.push_back(pair2);
  credentials.all_possible_passwords.push_back(pair3);

  form_manager()->ProvisionallySave(credentials);

  EXPECT_THAT(form_manager()->GetPendingCredentials().all_possible_passwords,
              UnorderedElementsAre(pair1, pair2, pair3));
}

// Test that public-suffix-matched credentials score lower than same-origin
// ones.
TEST_F(PasswordFormManagerTest, TestScoringPublicSuffixMatch) {
  EXPECT_CALL(*(client()->mock_driver()), AllowPasswordGenerationForForm(_));

  PasswordForm base_match = CreateSavedMatch(false);
  base_match.origin = GURL("http://accounts.google.com/a/ServiceLoginAuth");
  base_match.action = GURL("http://accounts.google.com/a/ServiceLogin");

  PasswordForm psl_match = base_match;
  psl_match.is_public_suffix_match = true;

  // Change origin and action URLs to decrease the score.
  PasswordForm same_origin_match = base_match;
  psl_match.origin = GURL("http://accounts.google.com/a/ServiceLoginAuth2");
  psl_match.action = GURL("http://accounts.google.com/a/ServiceLogin2");

  autofill::PasswordFormFillData fill_data;
  EXPECT_CALL(*client()->mock_driver(), FillPasswordForm(_))
      .WillOnce(SaveArg<0>(&fill_data));

  fake_form_fetcher()->SetNonFederated({&psl_match, &same_origin_match}, 0u);
  EXPECT_TRUE(fill_data.additional_logins.empty());
  EXPECT_EQ(1u, form_manager()->GetBestMatches().size());
  EXPECT_FALSE(
      form_manager()->GetBestMatches().begin()->second->is_public_suffix_match);
}

TEST_F(PasswordFormManagerTest, AndroidCredentialsAreAutofilled) {
  EXPECT_CALL(*(client()->mock_driver()), AllowPasswordGenerationForForm(_));

  // Although Android-based credentials are treated similarly to PSL-matched
  // credentials in some respects, they should be autofilled as opposed to be
  // filled on username-select.
  PasswordForm android_login;
  android_login.signon_realm = "android://hash@com.google.android";
  android_login.origin = GURL("android://hash@com.google.android/");
  android_login.is_affiliation_based_match = true;
  android_login.username_value = saved_match()->username_value;
  android_login.password_value = saved_match()->password_value;
  android_login.preferred = false;
  android_login.times_used = 42;

  autofill::PasswordFormFillData fill_data;
  EXPECT_CALL(*client()->mock_driver(), FillPasswordForm(_))
      .WillOnce(SaveArg<0>(&fill_data));

  fake_form_fetcher()->SetNonFederated({&android_login}, 0u);
  EXPECT_TRUE(fill_data.additional_logins.empty());
  EXPECT_FALSE(fill_data.wait_for_username);
  EXPECT_EQ(1u, form_manager()->GetBestMatches().size());

  // When the user submits the filled form, no copy of the credential should be
  // created, instead the usage counter of the original credential should be
  // incremented in-place, as if it were a regular credential for that website.
  PasswordForm credential(*observed_form());
  credential.username_value = android_login.username_value;
  credential.password_value = android_login.password_value;
  credential.preferred = true;
  form_manager()->ProvisionallySave(credential);
  EXPECT_FALSE(form_manager()->IsNewLogin());

  PasswordForm updated_credential;
  EXPECT_CALL(MockFormSaver::Get(form_manager()), Update(_, _, _, nullptr))
      .WillOnce(testing::SaveArg<0>(&updated_credential));
  form_manager()->Save();

  EXPECT_EQ(android_login.username_value, updated_credential.username_value);
  EXPECT_EQ(android_login.password_value, updated_credential.password_value);
  EXPECT_EQ(android_login.times_used + 1, updated_credential.times_used);
  EXPECT_TRUE(updated_credential.preferred);
  EXPECT_EQ(GURL(), updated_credential.action);
  EXPECT_EQ(base::string16(), updated_credential.username_element);
  EXPECT_EQ(base::string16(), updated_credential.password_element);
  EXPECT_EQ(base::string16(), updated_credential.submit_element);
}

// Credentials saved through Android apps should always be shown in the drop-
// down menu, unless there is a better-scoring match with the same username.
TEST_F(PasswordFormManagerTest, AndroidCredentialsAreProtected) {
  const char kTestUsername1[] = "test-user@gmail.com";
  const char kTestUsername2[] = "test-other-user@gmail.com";
  const char kTestWebPassword[] = "web-password";
  const char kTestAndroidPassword1[] = "android-password-alpha";
  const char kTestAndroidPassword2[] = "android-password-beta";

  EXPECT_CALL(*(client()->mock_driver()), AllowPasswordGenerationForForm(_));

  // Suppose there is one login saved through the website, and two other coming
  // from Android: the first has the same username as the web-based credential,
  // so it should be suppressed, but the second has a different username, so it
  // should be shown.
  PasswordForm website_login = CreateSavedMatch(false);
  website_login.username_value = ASCIIToUTF16(kTestUsername1);
  website_login.password_value = ASCIIToUTF16(kTestWebPassword);

  PasswordForm android_same;
  android_same.signon_realm = "android://hash@com.google.android";
  android_same.origin = GURL("android://hash@com.google.android/");
  android_same.username_value = ASCIIToUTF16(kTestUsername1);
  android_same.password_value = ASCIIToUTF16(kTestAndroidPassword1);

  PasswordForm android_other = android_same;
  android_other.username_value = ASCIIToUTF16(kTestUsername2);
  android_other.password_value = ASCIIToUTF16(kTestAndroidPassword2);

  std::vector<std::unique_ptr<PasswordForm>> expected_matches;
  expected_matches.push_back(std::make_unique<PasswordForm>(website_login));
  expected_matches.push_back(std::make_unique<PasswordForm>(android_other));

  autofill::PasswordFormFillData fill_data;
  EXPECT_CALL(*client()->mock_driver(), FillPasswordForm(_))
      .WillOnce(SaveArg<0>(&fill_data));
  fake_form_fetcher()->SetNonFederated(
      {&website_login, &android_same, &android_other}, 0u);

  EXPECT_FALSE(fill_data.wait_for_username);
  EXPECT_EQ(1u, fill_data.additional_logins.size());

  std::vector<std::unique_ptr<PasswordForm>> actual_matches;
  for (const auto& username_match_pair : form_manager()->GetBestMatches())
    actual_matches.push_back(
        std::make_unique<PasswordForm>(*username_match_pair.second));
  EXPECT_THAT(actual_matches,
              UnorderedPasswordFormElementsAre(&expected_matches));
}

TEST_F(PasswordFormManagerTest, InvalidActionURLsDoNotMatch) {
  PasswordForm invalid_action_form(*observed_form());
  invalid_action_form.action = GURL("http://");
  ASSERT_FALSE(invalid_action_form.action.is_valid());
  ASSERT_FALSE(invalid_action_form.action.is_empty());
  // Non-empty invalid action URLs should not match other actions.
  // First when the compared form has an invalid URL:
  EXPECT_EQ(0, form_manager()->DoesManage(invalid_action_form, nullptr) &
                   PasswordFormManager::RESULT_ACTION_MATCH);
  // Then when the observed form has an invalid URL:
  PasswordForm valid_action_form(*observed_form());
  PasswordFormManager invalid_manager(
      password_manager(), client(), client()->driver(), invalid_action_form,
      std::make_unique<MockFormSaver>(), fake_form_fetcher());
  invalid_manager.Init(nullptr);
  EXPECT_EQ(0, invalid_manager.DoesManage(valid_action_form, nullptr) &
                   PasswordFormManager::RESULT_ACTION_MATCH);
}

TEST_F(PasswordFormManagerTest, EmptyActionURLsDoNotMatchNonEmpty) {
  PasswordForm empty_action_form(*observed_form());
  empty_action_form.action = GURL();
  ASSERT_FALSE(empty_action_form.action.is_valid());
  ASSERT_TRUE(empty_action_form.action.is_empty());
  // First when the compared form has an empty URL:
  EXPECT_EQ(0, form_manager()->DoesManage(empty_action_form, nullptr) &
                   PasswordFormManager::RESULT_ACTION_MATCH);
  // Then when the observed form has an empty URL:
  PasswordForm valid_action_form(*observed_form());
  PasswordFormManager empty_action_manager(
      password_manager(), client(), client()->driver(), empty_action_form,
      std::make_unique<MockFormSaver>(), fake_form_fetcher());
  empty_action_manager.Init(nullptr);
  EXPECT_EQ(0, empty_action_manager.DoesManage(valid_action_form, nullptr) &
                   PasswordFormManager::RESULT_ACTION_MATCH);
}

TEST_F(PasswordFormManagerTest, NonHTMLFormsDoNotMatchHTMLForms) {
  ASSERT_EQ(PasswordForm::SCHEME_HTML, observed_form()->scheme);
  PasswordForm non_html_form(*observed_form());
  non_html_form.scheme = PasswordForm::SCHEME_DIGEST;
  EXPECT_EQ(PasswordFormManager::RESULT_NO_MATCH,
            form_manager()->DoesManage(non_html_form, nullptr));

  // The other way round: observing a non-HTML form, don't match a HTML form.
  PasswordForm html_form(*observed_form());
  PasswordFormManager non_html_manager(
      password_manager(), client(), kNoDriver, non_html_form,
      std::make_unique<MockFormSaver>(), fake_form_fetcher());
  non_html_manager.Init(nullptr);
  EXPECT_EQ(PasswordFormManager::RESULT_NO_MATCH,
            non_html_manager.DoesManage(html_form, nullptr));
}

TEST_F(PasswordFormManagerTest, OriginCheck_HostsMatchExactly) {
  // Host part of origins must match exactly, not just by prefix.
  PasswordForm form_longer_host(*observed_form());
  form_longer_host.origin = GURL("http://accounts.google.com.au/a/LoginAuth");
  // Check that accounts.google.com does not match accounts.google.com.au.
  EXPECT_EQ(PasswordFormManager::RESULT_NO_MATCH,
            form_manager()->DoesManage(form_longer_host, nullptr));
}

TEST_F(PasswordFormManagerTest, OriginCheck_MoreSecureSchemePathsMatchPrefix) {
  // If the URL scheme of the observed form is HTTP, and the compared form is
  // HTTPS, then the compared form can extend the path.
  PasswordForm form_longer_path(*observed_form());
  form_longer_path.origin = GURL("https://accounts.google.com/a/LoginAuth/sec");
  EXPECT_NE(0, form_manager()->DoesManage(form_longer_path, nullptr) &
                   PasswordFormManager::RESULT_ORIGINS_OR_FRAMES_MATCH);
}

TEST_F(PasswordFormManagerTest,
       OriginCheck_NotMoreSecureSchemePathsMatchExactly) {
  // If the origin URL scheme of the compared form is not more secure than that
  // of the observed form, then the paths must match exactly.
  PasswordForm form_longer_path(*observed_form());
  form_longer_path.origin = GURL("http://accounts.google.com/a/LoginAuth/sec");
  // Check that /a/LoginAuth does not match /a/LoginAuth/more.
  EXPECT_EQ(PasswordFormManager::RESULT_NO_MATCH,
            form_manager()->DoesManage(form_longer_path, nullptr));

  PasswordForm secure_observed_form(*observed_form());
  secure_observed_form.origin = GURL("https://accounts.google.com/a/LoginAuth");
  PasswordFormManager secure_manager(
      password_manager(), client(), client()->driver(), secure_observed_form,
      std::make_unique<MockFormSaver>(), fake_form_fetcher());
  secure_manager.Init(nullptr);
  // Also for HTTPS in the observed form, and HTTP in the compared form, an
  // exact path match is expected.
  EXPECT_EQ(PasswordFormManager::RESULT_NO_MATCH,
            secure_manager.DoesManage(form_longer_path, nullptr));
  // Not even upgrade to HTTPS in the compared form should help.
  form_longer_path.origin = GURL("https://accounts.google.com/a/LoginAuth/sec");
  EXPECT_EQ(PasswordFormManager::RESULT_NO_MATCH,
            secure_manager.DoesManage(form_longer_path, nullptr));
}

TEST_F(PasswordFormManagerTest, OriginCheck_OnlyOriginsMatch) {
  // Make sure DoesManage() can distinguish when only origins match.

  PasswordForm same_origin_only(*observed_form());
  same_origin_only.form_data.name = ASCIIToUTF16("other_name");
  same_origin_only.action = GURL("https://somewhere/else");

  EXPECT_EQ(PasswordFormManager::RESULT_ORIGINS_OR_FRAMES_MATCH,
            form_manager()->DoesManage(same_origin_only, nullptr));
}

TEST_F(PasswordFormManagerTest, FormsMatchIfNamesMatch) {
  PasswordForm other_form(*observed_form());
  autofill::FormFieldData field;
  field.name = ASCIIToUTF16("another-field-name");
  other_form.form_data.fields.push_back(field);
  other_form.action = GURL("https://somewhere/else");
  // Names should match, other things may not.
  EXPECT_EQ(PasswordFormManager::RESULT_FORM_NAME_MATCH,
            form_manager()->DoesManage(other_form, nullptr) &
                PasswordFormManager::RESULT_FORM_NAME_MATCH);
}

TEST_F(PasswordFormManagerTest, FormsMatchIfSignaturesMatch) {
  PasswordForm other_form(*observed_form());
  other_form.action = GURL("https://somewhere/else");
  // Signatures should match, other things may not.
  EXPECT_EQ(PasswordFormManager::RESULT_SIGNATURE_MATCH,
            form_manager()->DoesManage(other_form, nullptr) &
                PasswordFormManager::RESULT_SIGNATURE_MATCH);
}

TEST_F(PasswordFormManagerTest, FormWithEmptyActionAndNameMatchesItself) {
  observed_form()->form_data.name.clear();
  observed_form()->action = GURL::EmptyGURL();
  PasswordFormManager form_manager(
      password_manager(), client(), client()->driver(), *observed_form(),
      std::make_unique<NiceMock<MockFormSaver>>(), fake_form_fetcher());
  form_manager.Init(nullptr);
  // Any form should match itself regardless of missing properties. Otherwise,
  // a PasswordFormManager instance is created for the same form multiple times.
  PasswordForm other_form(*observed_form());
  EXPECT_EQ(PasswordFormManager::RESULT_COMPLETE_MATCH,
            form_manager.DoesManage(other_form, nullptr));
}

// Test that if multiple credentials with the same username are stored, and the
// user updates the password, then all of the stored passwords get updated as
// long as they have the same password value.
TEST_F(PasswordFormManagerTest, CorrectlyUpdatePasswordsWithSameUsername) {
  EXPECT_CALL(*client()->mock_driver(), AllowPasswordGenerationForForm(_));

  PasswordForm first(*saved_match());
  first.action = observed_form()->action;
  first.password_value = ASCIIToUTF16("first");
  first.preferred = true;

  // The second credential has the same password value, but it has a different
  // |username_element| to make a different unique key for the database
  // (otherwise the two credentials could not be stored at the same time). The
  // different unique key results in a slightly lower score than for |first|.
  PasswordForm second(first);
  second.username_element.clear();
  second.preferred = false;

  // The third credential has a different password value. It also has a
  // different |password_element| to make a different unique key for the
  // database again.
  PasswordForm third(first);
  third.password_element.clear();
  third.password_value = ASCIIToUTF16("second");
  third.preferred = false;

  fake_form_fetcher()->SetNonFederated({&first, &second, &third}, 0u);

  // |first| scored slightly higher.
  EXPECT_EQ(ASCIIToUTF16("first"),
            form_manager()->GetPreferredMatch()->password_value);

  PasswordForm login(*observed_form());
  login.username_value = saved_match()->username_value;
  login.password_value = ASCIIToUTF16("third");
  login.preferred = true;
  form_manager()->ProvisionallySave(login);

  EXPECT_FALSE(form_manager()->IsNewLogin());

  PasswordForm saved_result;
  std::vector<PasswordForm> credentials_to_update;
  EXPECT_CALL(MockFormSaver::Get(form_manager()), Update(_, _, _, nullptr))
      .WillOnce(testing::DoAll(SaveArg<0>(&saved_result),
                               SaveArgPointee<2>(&credentials_to_update)));
  EXPECT_CALL(*client()->mock_driver()->mock_autofill_download_manager(),
              StartUploadRequest(_, false, _, _, true));

  form_manager()->Save();

  // What was |first| above should be the main credential updated.
  EXPECT_EQ(ASCIIToUTF16("third"), saved_result.password_value);
  EXPECT_FALSE(saved_result.password_element.empty());
  EXPECT_FALSE(saved_result.username_element.empty());

  // What was |second| above should be another credential updated.
  ASSERT_EQ(1u, credentials_to_update.size());
  EXPECT_EQ(ASCIIToUTF16("third"), credentials_to_update[0].password_value);
  EXPECT_FALSE(credentials_to_update[0].password_element.empty());
  EXPECT_TRUE(credentials_to_update[0].username_element.empty());
}

TEST_F(PasswordFormManagerTest, UploadFormData_NewPassword) {
  // For newly saved passwords, upload a password vote for autofill::PASSWORD.
  // Don't vote for the username field yet.
  FakeFormFetcher fetcher;
  fetcher.Fetch();
  PasswordFormManager form_manager(
      password_manager(), client(), client()->driver(), *saved_match(),
      std::make_unique<NiceMock<MockFormSaver>>(), &fetcher);
  form_manager.Init(nullptr);
  fetcher.SetNonFederated(std::vector<const PasswordForm*>(), 0u);

  PasswordForm form_to_save(*saved_match());
  form_to_save.preferred = true;
  form_to_save.username_value = ASCIIToUTF16("username");
  form_to_save.password_value = ASCIIToUTF16("1234");

  autofill::ServerFieldTypeSet expected_available_field_types;
  expected_available_field_types.insert(autofill::PASSWORD);
  EXPECT_CALL(
      *client()->mock_driver()->mock_autofill_download_manager(),
      StartUploadRequest(_, false, expected_available_field_types, _, true));
  form_manager.ProvisionallySave(form_to_save);
  form_manager.Save();
}

TEST_F(PasswordFormManagerTest, UploadFormData_NewPassword_Blacklist) {
  // Do not upload a vote if the user is blacklisting the form.
  FakeFormFetcher fetcher;
  fetcher.Fetch();
  PasswordFormManager blacklist_form_manager(
      password_manager(), client(), client()->driver(), *saved_match(),
      std::make_unique<NiceMock<MockFormSaver>>(), &fetcher);
  blacklist_form_manager.Init(nullptr);
  fetcher.SetNonFederated(std::vector<const PasswordForm*>(), 0u);

  autofill::ServerFieldTypeSet expected_available_field_types;
  expected_available_field_types.insert(autofill::USERNAME);
  expected_available_field_types.insert(autofill::PASSWORD);
  EXPECT_CALL(*client()->mock_driver()->mock_autofill_download_manager(),
              StartUploadRequest(_, _, expected_available_field_types, _, true))
      .Times(0);
  blacklist_form_manager.PermanentlyBlacklist();
}

TEST_F(PasswordFormManagerTest, UploadPasswordForm) {
  autofill::FormData observed_form_data;
  autofill::FormFieldData field;
  field.label = ASCIIToUTF16("Email:");
  field.name = ASCIIToUTF16("observed-username-field");
  field.form_control_type = "text";
  observed_form_data.fields.push_back(field);

  field.label = ASCIIToUTF16("Password:");
  field.name = ASCIIToUTF16("observed-password-field");
  field.form_control_type = "password";
  observed_form_data.fields.push_back(field);

  // Form data is different than saved form data, account creation signal should
  // be sent.
  autofill::ServerFieldType field_type = autofill::ACCOUNT_CREATION_PASSWORD;
  AccountCreationUploadTest(observed_form_data, 0, PasswordForm::NO_SIGNAL_SENT,
                            &field_type);

  // Non-zero times used will not upload since we only upload a positive signal
  // at most once.
  AccountCreationUploadTest(observed_form_data, 1, PasswordForm::NO_SIGNAL_SENT,
                            nullptr);

  // Same form data as saved match and POSITIVE_SIGNAL_SENT means there should
  // be a negative autofill ping sent.
  field_type = autofill::NOT_ACCOUNT_CREATION_PASSWORD;
  AccountCreationUploadTest(saved_match()->form_data, 2,
                            PasswordForm::POSITIVE_SIGNAL_SENT, &field_type);

  // For any other GenerationUplaodStatus, no autofill upload should occur
  // if the observed form data matches the saved form data.
  AccountCreationUploadTest(saved_match()->form_data, 3,
                            PasswordForm::NO_SIGNAL_SENT, nullptr);
  AccountCreationUploadTest(saved_match()->form_data, 3,
                            PasswordForm::NEGATIVE_SIGNAL_SENT, nullptr);
}

TEST_F(PasswordFormManagerTest, CorrectlySavePasswordWithoutUsernameFields) {
  EXPECT_CALL(*client()->mock_driver(), AllowPasswordGenerationForForm(_));

  fake_form_fetcher()->SetNonFederated(std::vector<const PasswordForm*>(), 0u);

  PasswordForm login(*observed_form());
  login.username_element.clear();
  login.password_value = ASCIIToUTF16("password");
  login.preferred = true;

  form_manager()->ProvisionallySave(login);

  EXPECT_TRUE(form_manager()->IsNewLogin());

  PasswordForm saved_result;
  EXPECT_CALL(MockFormSaver::Get(form_manager()), Save(_, _))
      .WillOnce(SaveArg<0>(&saved_result));

  form_manager()->Save();

  // Make sure that the password is updated appropriately.
  EXPECT_EQ(ASCIIToUTF16("password"), saved_result.password_value);
}

TEST_F(PasswordFormManagerTest, DriverDeletedBeforeStoreDone) {
  // Test graceful handling of the following situation:
  // 1. A form appears in a frame, a PFM is created for that form.
  // 2. The PFM asks the store for credentials for this form.
  // 3. The frame (and associated driver) gets deleted.
  // 4. The PFM returns the callback with credentials.
  // This test checks implicitly that after step 4 the PFM does not attempt
  // use-after-free of the deleted driver.
  std::string example_url("http://example.com");
  PasswordForm form;
  form.origin = GURL(example_url);
  form.signon_realm = example_url;
  form.action = GURL(example_url);
  form.username_element = ASCIIToUTF16("u");
  form.password_element = ASCIIToUTF16("p");
  form.submit_element = ASCIIToUTF16("s");

  FakeFormFetcher fetcher;
  fetcher.Fetch();
  PasswordFormManager form_manager(password_manager(), client(),
                                   client()->driver(), form,
                                   std::make_unique<MockFormSaver>(), &fetcher);
  form_manager.Init(nullptr);

  // Suddenly, the frame and its driver disappear.
  client()->KillDriver();

  fetcher.SetNonFederated({&form}, 0u);
}

TEST_F(PasswordFormManagerTest, PreferredMatchIsUpToDate) {
  // Check that GetPreferredMatch() is always a member of GetBestMatches().
  PasswordForm form = *observed_form();
  form.username_value = ASCIIToUTF16("username");
  form.password_value = ASCIIToUTF16("password1");
  form.preferred = false;

  PasswordForm generated_form = form;
  generated_form.type = PasswordForm::TYPE_GENERATED;
  generated_form.password_value = ASCIIToUTF16("password2");
  generated_form.preferred = true;

  fake_form_fetcher()->SetNonFederated({&form, &generated_form}, 0u);

  EXPECT_EQ(1u, form_manager()->GetBestMatches().size());
  EXPECT_EQ(form_manager()->GetPreferredMatch(),
            form_manager()->GetBestMatches().begin()->second);
  // Make sure to access all fields of preferred_match; this way if it was
  // deleted, ASAN might notice it.
  PasswordForm dummy(*form_manager()->GetPreferredMatch());
}

TEST_F(PasswordFormManagerTest, PasswordToSave_NoElements) {
  PasswordForm form;
  EXPECT_TRUE(PasswordFormManager::PasswordToSave(form).first.empty());
}

TEST_F(PasswordFormManagerTest, PasswordToSave_NoNewElement) {
  PasswordForm form;
  form.password_element = base::ASCIIToUTF16("pwd");
  base::string16 kValue = base::ASCIIToUTF16("val");
  form.password_value = kValue;
  EXPECT_EQ(kValue, PasswordFormManager::PasswordToSave(form).first);
}

TEST_F(PasswordFormManagerTest, PasswordToSave_NoOldElement) {
  PasswordForm form;
  form.new_password_element = base::ASCIIToUTF16("new_pwd");
  base::string16 kNewValue = base::ASCIIToUTF16("new_val");
  form.new_password_value = kNewValue;
  EXPECT_EQ(kNewValue, PasswordFormManager::PasswordToSave(form).first);
}

TEST_F(PasswordFormManagerTest, PasswordToSave_BothButNoNewValue) {
  PasswordForm form;
  form.password_element = base::ASCIIToUTF16("pwd");
  form.new_password_element = base::ASCIIToUTF16("new_pwd");
  base::string16 kValue = base::ASCIIToUTF16("val");
  form.password_value = kValue;
  EXPECT_EQ(kValue, PasswordFormManager::PasswordToSave(form).first);
}

TEST_F(PasswordFormManagerTest, PasswordToSave_NewValue) {
  PasswordForm form;
  form.password_element = base::ASCIIToUTF16("pwd");
  form.new_password_element = base::ASCIIToUTF16("new_pwd");
  form.password_value = base::ASCIIToUTF16("val");
  base::string16 kNewValue = base::ASCIIToUTF16("new_val");
  form.new_password_value = kNewValue;
  EXPECT_EQ(kNewValue, PasswordFormManager::PasswordToSave(form).first);
}

TEST_F(PasswordFormManagerTest, TestSuggestingPasswordChangeForms) {
  // Suggesting password on the password change form on the previously visited
  // site. Credentials are found in the password store, and are not blacklisted.
  PasswordForm observed_change_password_form = *observed_form();
  observed_change_password_form.new_password_element =
      base::ASCIIToUTF16("new_pwd");
  FakeFormFetcher fetcher;
  fetcher.Fetch();
  PasswordFormManager manager_creds(
      password_manager(), client(), client()->driver(),
      observed_change_password_form, std::make_unique<MockFormSaver>(),
      &fetcher);
  manager_creds.Init(nullptr);

  autofill::PasswordFormFillData fill_data;
  EXPECT_CALL(*client()->mock_driver(), FillPasswordForm(_))
      .WillOnce(SaveArg<0>(&fill_data));

  PasswordForm result = CreateSavedMatch(false);
  fetcher.SetNonFederated({&result}, 0u);
  EXPECT_EQ(1u, manager_creds.GetBestMatches().size());
  EXPECT_EQ(0u, fill_data.additional_logins.size());
  EXPECT_TRUE(fill_data.wait_for_username);
}

TEST_F(PasswordFormManagerTest, TestUpdateMethod) {
  // Add a new password field to the test form. The PasswordFormManager should
  // save the password from this field, instead of the current password field.
  observed_form()->new_password_element = ASCIIToUTF16("NewPasswd");
  autofill::FormFieldData field;
  field.label = ASCIIToUTF16("NewPasswd");
  field.name = ASCIIToUTF16("NewPasswd");
  field.form_control_type = "password";
  observed_form()->form_data.fields.push_back(field);

  FakeFormFetcher fetcher;
  fetcher.Fetch();
  PasswordFormManager form_manager(password_manager(), client(),
                                   client()->driver(), *observed_form(),
                                   std::make_unique<MockFormSaver>(), &fetcher);
  form_manager.Init(nullptr);
  fetcher.SetNonFederated({saved_match()}, 0u);

  // User submits current and new credentials to the observed form.
  PasswordForm credentials(*observed_form());
  credentials.username_element.clear();
  credentials.password_value = saved_match()->password_value;
  credentials.new_password_value = ASCIIToUTF16("test2");
  credentials.preferred = true;
  form_manager.ProvisionallySave(credentials);

  // Successful login. The PasswordManager would instruct PasswordFormManager
  // to save, and since this is an update, it should know not to save as a new
  // login.
  EXPECT_FALSE(form_manager.IsNewLogin());
  EXPECT_FALSE(
      form_manager.is_possible_change_password_form_without_username());

  // By now, the PasswordFormManager should have promoted the new password value
  // already to be the current password, and should no longer maintain any info
  // about the new password value.
  EXPECT_EQ(credentials.new_password_value,
            form_manager.GetPendingCredentials().password_value);
  EXPECT_TRUE(form_manager.GetPendingCredentials().new_password_value.empty());

  // Trigger saving to exercise some special case handling during updating.
  PasswordForm new_credentials;
  EXPECT_CALL(MockFormSaver::Get(&form_manager), Update(_, _, _, nullptr))
      .WillOnce(SaveArg<0>(&new_credentials));

  form_manager.Update(*saved_match());

  // The password is updated.
  EXPECT_EQ(credentials.new_password_value, new_credentials.password_value);
  EXPECT_EQ(saved_match()->username_element, new_credentials.username_element);
  EXPECT_EQ(saved_match()->password_element, new_credentials.password_element);
  EXPECT_EQ(saved_match()->submit_element, new_credentials.submit_element);
}

TEST_F(PasswordFormManagerTest, TestUpdateNoUsernameTextfieldPresent) {
  // Add a new password field to the test form and insert a |username_value|
  // unlikely to be a real username. The PasswordFormManager should still save
  // the password from this field, instead of the current password field.
  observed_form()->new_password_element = ASCIIToUTF16("NewPasswd");
  autofill::FormFieldData field;
  field.label = ASCIIToUTF16("NewPasswd");
  field.name = ASCIIToUTF16("NewPasswd");
  field.form_control_type = "password";
  observed_form()->form_data.fields.push_back(field);

  FakeFormFetcher fetcher;
  fetcher.Fetch();
  PasswordFormManager form_manager(password_manager(), client(),
                                   client()->driver(), *observed_form(),
                                   std::make_unique<MockFormSaver>(), &fetcher);
  form_manager.Init(nullptr);
  fetcher.SetNonFederated({saved_match()}, 0u);

  // User submits current and new credentials to the observed form.
  PasswordForm credentials(*observed_form());
  // The |username_value| contains a text that's unlikely to be real username.
  credentials.username_value = ASCIIToUTF16("3");
  credentials.password_value = saved_match()->password_value;
  credentials.new_password_value = ASCIIToUTF16("test2");
  credentials.preferred = true;
  form_manager.ProvisionallySave(credentials);

  // Successful login. The PasswordManager would instruct PasswordFormManager
  // to save, and since this is an update, it should know not to save as a new
  // login.
  EXPECT_FALSE(form_manager.IsNewLogin());
  EXPECT_TRUE(form_manager.is_possible_change_password_form_without_username());

  // By now, the PasswordFormManager should have promoted the new password value
  // already to be the current password, and should no longer maintain any info
  // about the new password value.
  EXPECT_EQ(saved_match()->username_value,
            form_manager.GetPendingCredentials().username_value);
  EXPECT_EQ(credentials.new_password_value,
            form_manager.GetPendingCredentials().password_value);
  EXPECT_TRUE(form_manager.GetPendingCredentials().new_password_value.empty());

  // Trigger saving to exercise some special case handling during updating.
  PasswordForm new_credentials;
  EXPECT_CALL(MockFormSaver::Get(&form_manager), Update(_, _, _, nullptr))
      .WillOnce(SaveArg<0>(&new_credentials));

  form_manager.Update(form_manager.GetPendingCredentials());

  // The password should be updated, but the username should not.
  EXPECT_EQ(saved_match()->username_value, new_credentials.username_value);
  EXPECT_EQ(credentials.new_password_value, new_credentials.password_value);
  EXPECT_EQ(saved_match()->username_element, new_credentials.username_element);
  EXPECT_EQ(saved_match()->password_element, new_credentials.password_element);
  EXPECT_TRUE(new_credentials.new_password_value.empty());
  EXPECT_TRUE(new_credentials.new_password_element.empty());
  EXPECT_EQ(saved_match()->submit_element, new_credentials.submit_element);
}

// Test the case when a user changes the username to the value of another field
// from the form.
TEST_F(PasswordFormManagerTest, UpdateUsername_ValueOfAnotherField) {
  for (bool captured_username_is_empty : {false, true}) {
    SCOPED_TRACE(testing::Message() << "captured_username_is_empty="
                                    << captured_username_is_empty);
    PasswordForm observed(*observed_form());
    // Set |FormData| to upload a username vote.
    autofill::FormFieldData field;
    field.name = ASCIIToUTF16("full_name");
    field.form_control_type = "text";
    observed.form_data.fields.push_back(field);
    field.name = ASCIIToUTF16("correct_username_element");
    field.form_control_type = "text";
    observed.form_data.fields.push_back(field);
    field.name = ASCIIToUTF16("Passwd");
    field.form_control_type = "password";
    observed.form_data.fields.push_back(field);

    PasswordFormManager form_manager(
        password_manager(), client(), client()->driver(), observed,
        std::make_unique<NiceMock<MockFormSaver>>(), fake_form_fetcher());
    form_manager.Init(nullptr);
    fake_form_fetcher()->SetNonFederated(std::vector<const PasswordForm*>(),
                                         0u);

    // User enters credential in the form.
    PasswordForm credential(observed);
    credential.username_value = captured_username_is_empty
                                    ? base::string16()
                                    : ASCIIToUTF16("typed_username");
    credential.password_value = ASCIIToUTF16("password");
    credential.other_possible_usernames.push_back(
        ValueElementPair(ASCIIToUTF16("edited_username"),
                         ASCIIToUTF16("correct_username_element")));
    form_manager.ProvisionallySave(credential);

    // User edits username in a prompt.
    form_manager.UpdateUsername(ASCIIToUTF16("edited_username"));
    EXPECT_EQ(form_manager.GetPendingCredentials().username_value,
              ASCIIToUTF16("edited_username"));
    EXPECT_EQ(form_manager.GetPendingCredentials().username_element,
              ASCIIToUTF16("correct_username_element"));
    EXPECT_EQ(form_manager.GetPendingCredentials().password_value,
              ASCIIToUTF16("password"));
    EXPECT_TRUE(form_manager.IsNewLogin());

    // User clicks save, the edited username is saved.
    PasswordForm saved_result;
    EXPECT_CALL(MockFormSaver::Get(&form_manager), Save(_, IsEmpty()))
        .WillOnce(SaveArg<0>(&saved_result));
    // Expect a username edited vote.
    FieldTypeMap expected_types;
    expected_types[ASCIIToUTF16("full_name")] = autofill::UNKNOWN_TYPE;
    expected_types[ASCIIToUTF16("correct_username_element")] =
        autofill::USERNAME;
    expected_types[ASCIIToUTF16("Passwd")] = autofill::PASSWORD;
    VoteTypeMap expected_vote_types = {
        {ASCIIToUTF16("correct_username_element"),
         autofill::AutofillUploadContents::Field::USERNAME_EDITED}};
    EXPECT_CALL(
        *client()->mock_driver()->mock_autofill_download_manager(),
        StartUploadRequest(
            AllOf(SignatureIsSameAs(observed),
                  UploadedAutofillTypesAre(expected_types),
                  HasGenerationVote(false), VoteTypesAre(expected_vote_types)),
            _, Contains(autofill::USERNAME), _, _));
    form_manager.Save();

    // Check what is saved.
    EXPECT_EQ(ASCIIToUTF16("edited_username"), saved_result.username_value);
    EXPECT_EQ(ASCIIToUTF16("correct_username_element"),
              saved_result.username_element);
    EXPECT_EQ(ASCIIToUTF16("password"), saved_result.password_value);
    if (captured_username_is_empty) {
      EXPECT_TRUE(saved_result.other_possible_usernames.empty());
    } else {
      EXPECT_THAT(
          saved_result.other_possible_usernames,
          ElementsAre(ValueElementPair(ASCIIToUTF16("typed_username"),
                                       observed_form()->username_element)));
    }
  }
}

// Test the case when a user updates the username to an already existing one.
TEST_F(PasswordFormManagerTest, UpdateUsername_ValueSavedInStore) {
  for (bool captured_username_is_empty : {false, true}) {
    SCOPED_TRACE(testing::Message() << "captured_username_is_empty="
                                    << captured_username_is_empty);
    // We have an already existing credential.
    fake_form_fetcher()->SetNonFederated({saved_match()}, 0u);

    // User enters credential in the form.
    PasswordForm credential(*observed_form());
    credential.username_value = captured_username_is_empty
                                    ? base::string16()
                                    : ASCIIToUTF16("different_username");
    credential.password_value = ASCIIToUTF16("different_pass");
    credential.preferred = true;
    form_manager()->ProvisionallySave(credential);

    // User edits username in a prompt to one already existing.
    form_manager()->UpdateUsername(saved_match()->username_value);

    // The username in credentials is expected to be updated.
    EXPECT_EQ(saved_match()->username_value,
              form_manager()->GetPendingCredentials().username_value);
    EXPECT_EQ(saved_match()->username_element,
              form_manager()->GetPendingCredentials().username_element);
    EXPECT_EQ(ASCIIToUTF16("different_pass"),
              form_manager()->GetPendingCredentials().password_value);
    EXPECT_FALSE(form_manager()->IsNewLogin());

    // Create the expected credential to be saved.
    PasswordForm expected_pending(credential);
    expected_pending.origin = saved_match()->origin;
    expected_pending.form_data = saved_match()->form_data;
    expected_pending.times_used = 1;
    expected_pending.username_value = saved_match()->username_value;

    // User clicks save, edited username is saved, password updated.
    EXPECT_CALL(MockFormSaver::Get(form_manager()),
                Update(expected_pending,
                       ElementsAre(Pair(saved_match()->username_value,
                                        Pointee(*saved_match()))),
                       Pointee(IsEmpty()), nullptr));
    // Expect a username reusing vote.
    FieldTypeMap expected_types;
    expected_types[ASCIIToUTF16("full_name")] = autofill::UNKNOWN_TYPE;
    expected_types[expected_pending.username_element] = autofill::USERNAME;
    expected_types[expected_pending.password_element] =
        autofill::ACCOUNT_CREATION_PASSWORD;
    VoteTypeMap expected_vote_types = {
        {expected_pending.username_element,
         autofill::AutofillUploadContents::Field::CREDENTIALS_REUSED}};
    EXPECT_CALL(
        *client()->mock_driver()->mock_autofill_download_manager(),
        StartUploadRequest(
            AllOf(SignatureIsSameAs(expected_pending),
                  UploadedAutofillTypesAre(expected_types),
                  HasGenerationVote(false), VoteTypesAre(expected_vote_types)),
            _, Contains(autofill::USERNAME), _, _));
    form_manager()->Save();
  }
}

// Tests the case when the username value edited in prompt doesn't coincides
// neither with other values on the form nor with saved usernames.
TEST_F(PasswordFormManagerTest, UpdateUsername_NoMatchNeitherOnFormNorInStore) {
  for (bool captured_username_is_empty : {false, true}) {
    SCOPED_TRACE(testing::Message() << "captured_username_is_empty="
                                    << captured_username_is_empty);
    PasswordForm observed(*observed_form());
    // Assign any |FormData| to allow crowdsourcing of this form.
    observed.form_data = saved_match()->form_data;
    PasswordFormManager form_manager(
        password_manager(), client(), client()->driver(), observed,
        std::make_unique<NiceMock<MockFormSaver>>(), fake_form_fetcher());
    form_manager.Init(nullptr);
    // We have an already existing credential.
    fake_form_fetcher()->SetNonFederated({saved_match()}, 0u);

    // A user enters a credential in the form.
    PasswordForm credential(observed);
    credential.username_value = captured_username_is_empty
                                    ? base::string16()
                                    : ASCIIToUTF16("captured_username");
    credential.password_value = ASCIIToUTF16("different_pass");
    credential.preferred = true;
    form_manager.ProvisionallySave(credential);

    // User edits username. The username doesn't exist neither in the store nor
    // on the form.
    form_manager.UpdateUsername(ASCIIToUTF16("new_username"));

    // As there is no match on the form, |username_element| is empty.
    EXPECT_TRUE(form_manager.GetPendingCredentials().username_element.empty());
    EXPECT_EQ(ASCIIToUTF16("new_username"),
              form_manager.GetPendingCredentials().username_value);
    EXPECT_EQ(ASCIIToUTF16("different_pass"),
              form_manager.GetPendingCredentials().password_value);
    EXPECT_TRUE(form_manager.IsNewLogin());

    PasswordForm expected_pending(credential);
    expected_pending.username_value = ASCIIToUTF16("new_username");
    expected_pending.username_element = base::string16();
    if (!captured_username_is_empty) {
      // A non-empty captured username value should be saved to recover later if
      // a user makes a mistake in username editing.
      expected_pending.other_possible_usernames.push_back(ValueElementPair(
          ASCIIToUTF16("captured_username"), ASCIIToUTF16("Email")));
    }

    // User clicks save, the edited username is saved, the password is updated,
    // no username vote is uploaded.
    PasswordForm actual_saved_form;
    EXPECT_CALL(MockFormSaver::Get(&form_manager),
                Save(_, ElementsAre(Pair(saved_match()->username_value,
                                         Pointee(*saved_match())))))
        .WillOnce(SaveArg<0>(&actual_saved_form));
    EXPECT_CALL(
        *client()->mock_driver()->mock_autofill_download_manager(),
        StartUploadRequest(_, _, Not(Contains(autofill::USERNAME)), _, _));
    form_manager.Save();

    // Can't verify |date_created |, so ignore it in form comparison.
    actual_saved_form.date_created = expected_pending.date_created;
    EXPECT_EQ(expected_pending, actual_saved_form);
  }
}

// Tests the case when a user clears the username value in a prompt.
TEST_F(PasswordFormManagerTest, UpdateUsername_UserRemovedUsername) {
  PasswordForm observed(*observed_form());
  // Assign any |FormData| to allow crowdsourcing of this form.
  observed.form_data = saved_match()->form_data;
  PasswordFormManager form_manager(
      password_manager(), client(), client()->driver(), observed,
      std::make_unique<NiceMock<MockFormSaver>>(), fake_form_fetcher());
  form_manager.Init(nullptr);
  fake_form_fetcher()->SetNonFederated(std::vector<const PasswordForm*>(), 0u);

  // The user enters credential in the form.
  PasswordForm credential(observed);
  credential.username_value = ASCIIToUTF16("pin_code");
  credential.password_value = ASCIIToUTF16("password");
  credential.other_possible_usernames.push_back(
      ValueElementPair(base::string16(), ASCIIToUTF16("empty_field")));
  form_manager.ProvisionallySave(credential);

  // The user clears the username value in the prompt.
  form_manager.UpdateUsername(base::string16());
  EXPECT_TRUE(form_manager.GetPendingCredentials().username_value.empty());
  EXPECT_TRUE(form_manager.GetPendingCredentials().username_element.empty());
  EXPECT_EQ(form_manager.GetPendingCredentials().password_value,
            ASCIIToUTF16("password"));
  EXPECT_TRUE(form_manager.IsNewLogin());

  // The user clicks save, empty username is saved.
  PasswordForm saved_result;
  EXPECT_CALL(MockFormSaver::Get(&form_manager), Save(_, IsEmpty()))
      .WillOnce(SaveArg<0>(&saved_result));
  EXPECT_CALL(
      *client()->mock_driver()->mock_autofill_download_manager(),
      StartUploadRequest(_, _, Not(Contains(autofill::USERNAME)), _, _));
  form_manager.Save();

  EXPECT_TRUE(saved_result.username_value.empty());
  EXPECT_TRUE(saved_result.username_element.empty());
  EXPECT_EQ(ASCIIToUTF16("password"), saved_result.password_value);
  EXPECT_THAT(saved_result.other_possible_usernames,
              ElementsAre(ValueElementPair(ASCIIToUTF16("pin_code"),
                                           observed_form()->username_element)));
}

// Test that when user updates username to a PSL matching credential, we should
// handle it as a new login.
TEST_F(PasswordFormManagerTest, UpdateUsername_PslMatch) {
  fake_form_fetcher()->SetNonFederated({psl_saved_match()}, 0u);
  // The user submits a credential of the observed form.
  PasswordForm credential(*observed_form());
  credential.username_value = ASCIIToUTF16("some_username");
  credential.password_value = ASCIIToUTF16("some_pass");
  form_manager()->ProvisionallySave(credential);

  // The user edits the username to match the PSL entry.
  form_manager()->UpdateUsername(psl_saved_match()->username_value);
  EXPECT_EQ(psl_saved_match()->username_value,
            form_manager()->GetPendingCredentials().username_value);
  EXPECT_TRUE(form_manager()->IsNewLogin());
  EXPECT_EQ(ASCIIToUTF16("some_pass"),
            form_manager()->GetPendingCredentials().password_value);

  // The user clicks save, the edited username is saved.
  PasswordForm saved_result;
  EXPECT_CALL(MockFormSaver::Get(form_manager()),
              Save(_, ElementsAre(Pair(psl_saved_match()->username_value,
                                       Pointee(*psl_saved_match())))))
      .WillOnce(SaveArg<0>(&saved_result));
  // As the credential is re-used successfully, expect a username vote.
  EXPECT_CALL(*client()->mock_driver()->mock_autofill_download_manager(),
              StartUploadRequest(_, _, Contains(autofill::USERNAME), _, _));
  form_manager()->Save();

  // Check what is saved.
  EXPECT_EQ(psl_saved_match()->username_value, saved_result.username_value);
  EXPECT_EQ(ASCIIToUTF16("some_pass"), saved_result.password_value);
}

// Test that when user selects a password in the bubble, the pending credentials
// are updated accordingly.
TEST_F(PasswordFormManagerTest, TestSelectPasswordMethod) {
  for (bool has_password : {true, false}) {
    for (bool has_new_password : {true, false}) {
      for (bool has_passwords_revealed : {true, false}) {
        if (!has_password && !has_new_password)
          continue;
        SCOPED_TRACE(testing::Message() << "has_password=" << has_password);
        SCOPED_TRACE(testing::Message()
                     << "has_new_password=" << has_new_password);
        SCOPED_TRACE(testing::Message()
                     << "has_passwords_revealed=" << has_passwords_revealed);

        PasswordForm observed(*observed_form());
        // Observe two password fields, between which we must select.
        autofill::FormFieldData field;
        field.name = ASCIIToUTF16("correct_password_element");
        field.form_control_type = "password";
        observed.form_data.fields.push_back(field);
        field.name = ASCIIToUTF16("other_password_element");
        field.form_control_type = "password";
        observed.form_data.fields.push_back(field);

        PasswordFormManager form_manager(
            password_manager(), client(), client()->driver(), observed,
            std::make_unique<NiceMock<MockFormSaver>>(), fake_form_fetcher());
        form_manager.Init(nullptr);
        fake_form_fetcher()->SetNonFederated(std::vector<const PasswordForm*>(),
                                             0u);

        // User enters credential in the form. We autodetect the wrong password
        // field.
        PasswordForm credential(observed);
        if (has_password) {
          credential.password_value = ASCIIToUTF16("not-a-password");
          credential.password_element = ASCIIToUTF16("other_password_element");
        }
        if (has_new_password) {
          credential.new_password_value = ASCIIToUTF16("not-a-password");
          credential.new_password_element =
              ASCIIToUTF16("other_password_element");
        }
        credential.all_possible_passwords = {
            {ASCIIToUTF16("p4ssword"),
             ASCIIToUTF16("correct_password_element")},
            {ASCIIToUTF16("not-a-password"),
             ASCIIToUTF16("other_password_element")}};
        form_manager.ProvisionallySave(credential);

        // Pending credentials have the wrong values.
        EXPECT_EQ(form_manager.GetPendingCredentials().password_value,
                  ASCIIToUTF16("not-a-password"));
        EXPECT_EQ(form_manager.GetPendingCredentials().password_element,
                  ASCIIToUTF16("other_password_element"));
        // User selects another password in a prompt.
        if (has_passwords_revealed)
          form_manager.OnPasswordsRevealed();
        form_manager.UpdatePasswordValue(ASCIIToUTF16("p4ssword"));
        // Pending credentials are also corrected.
        EXPECT_EQ(form_manager.GetPendingCredentials().password_value,
                  ASCIIToUTF16("p4ssword"));
        EXPECT_EQ(form_manager.GetPendingCredentials().password_element,
                  ASCIIToUTF16("correct_password_element"));
        EXPECT_TRUE(form_manager.IsNewLogin());

        // User clicks save, selected password is saved.
        PasswordForm saved_result;
        EXPECT_CALL(MockFormSaver::Get(&form_manager), Save(_, IsEmpty()))
            .WillOnce(SaveArg<0>(&saved_result));
        // Expect a password edited vote.
        FieldTypeMap expected_types;
        expected_types[ASCIIToUTF16("correct_password_element")] =
            autofill::PASSWORD;
        expected_types[ASCIIToUTF16("other_password_element")] =
            autofill::UNKNOWN_TYPE;
        EXPECT_CALL(*client()->mock_driver()->mock_autofill_download_manager(),
                    StartUploadRequest(
                        AllOf(SignatureIsSameAs(observed),
                              UploadedAutofillTypesAre(expected_types),
                              HasGenerationVote(false),
                              PasswordsWereRevealed(has_passwords_revealed)),
                        _, Contains(autofill::PASSWORD), _, _));
        form_manager.Save();

        EXPECT_EQ(ASCIIToUTF16("p4ssword"), saved_result.password_value);
        EXPECT_EQ(ASCIIToUTF16("correct_password_element"),
                  saved_result.password_element);
        EXPECT_EQ(base::string16(), saved_result.new_password_value);
        EXPECT_EQ(base::string16(), saved_result.new_password_element);
      }
    }
  }
}

// Test that if WipeStoreCopyIfOutdated is called before password store
// callback, the UMA is signalled accordingly.
TEST_F(PasswordFormManagerTest, WipeStoreCopyIfOutdated_BeforeStoreCallback) {
  PasswordForm form(*saved_match());
  form.password_value = ASCIIToUTF16("nonempty-password");

  FakeFormFetcher fetcher;
  fetcher.Fetch();
  PasswordFormManager form_manager(password_manager(), client(),
                                   client()->driver(), form,
                                   std::make_unique<MockFormSaver>(), &fetcher);
  form_manager.Init(nullptr);
  // The creation of |fetcher| keeps it waiting for store results. This test
  // keeps the fetcher waiting on purpose.

  PasswordForm submitted_form(form);
  submitted_form.password_value += ASCIIToUTF16("add stuff, make it different");
  form_manager.ProvisionallySave(submitted_form);

  base::HistogramTester histogram_tester;
  EXPECT_CALL(MockFormSaver::Get(&form_manager),
              WipeOutdatedCopies(form_manager.GetPendingCredentials(), _, _));
  form_manager.WipeStoreCopyIfOutdated();
  histogram_tester.ExpectUniqueSample("PasswordManager.StoreReadyWhenWiping", 0,
                                      1);
}

TEST_F(PasswordFormManagerTest, GenerationStatusChangedWithPassword) {
  PasswordForm generated_form = *observed_form();
  generated_form.type = PasswordForm::TYPE_GENERATED;
  generated_form.username_value = ASCIIToUTF16("username");
  generated_form.password_value = ASCIIToUTF16("password2");
  generated_form.preferred = true;

  PasswordForm submitted_form(generated_form);
  submitted_form.password_value = ASCIIToUTF16("password3");

  fake_form_fetcher()->SetNonFederated({&generated_form}, 0u);

  form_manager()->ProvisionallySave(submitted_form);

  PasswordForm new_credentials;
  EXPECT_CALL(MockFormSaver::Get(form_manager()), Update(_, _, _, nullptr))
      .WillOnce(testing::SaveArg<0>(&new_credentials));
  form_manager()->Save();

  EXPECT_EQ(PasswordForm::TYPE_MANUAL, new_credentials.type);
}

TEST_F(PasswordFormManagerTest, GenerationStatusNotUpdatedIfPasswordUnchanged) {
  base::HistogramTester histogram_tester;

  PasswordForm generated_form = *observed_form();
  generated_form.type = PasswordForm::TYPE_GENERATED;
  generated_form.username_value = ASCIIToUTF16("username");
  generated_form.password_value = ASCIIToUTF16("password2");
  generated_form.preferred = true;

  PasswordForm submitted_form(generated_form);

  fake_form_fetcher()->SetNonFederated({&generated_form}, 0u);

  form_manager()->ProvisionallySave(submitted_form);

  PasswordForm new_credentials;
  EXPECT_CALL(MockFormSaver::Get(form_manager()), Update(_, _, _, nullptr))
      .WillOnce(testing::SaveArg<0>(&new_credentials));
  form_manager()->Save();

  EXPECT_EQ(PasswordForm::TYPE_GENERATED, new_credentials.type);
  histogram_tester.ExpectBucketCount("PasswordGeneration.SubmissionEvent",
                                     metrics_util::PASSWORD_USED, 1);

  // On the second reuse, the metric is not reported.
  generated_form.times_used = 1;
  fake_form_fetcher()->SetNonFederated({&generated_form}, 0u);
  form_manager()->ProvisionallySave(submitted_form);
  EXPECT_CALL(MockFormSaver::Get(form_manager()), Update(_, _, _, _));
  form_manager()->Save();
  histogram_tester.ExpectBucketCount("PasswordGeneration.SubmissionEvent",
                                     metrics_util::PASSWORD_USED, 1);
}

TEST_F(PasswordFormManagerTest, GeneratedPasswordIsOverridden) {
  base::HistogramTester histogram_tester;

  PasswordForm generated_form = *observed_form();
  generated_form.type = PasswordForm::TYPE_GENERATED;
  generated_form.username_value = ASCIIToUTF16("username");
  generated_form.password_value = ASCIIToUTF16("password2");
  generated_form.preferred = true;

  PasswordForm submitted_form(generated_form);
  submitted_form.password_value = ASCIIToUTF16("another_password");

  fake_form_fetcher()->SetNonFederated({&generated_form}, 0u);

  form_manager()->ProvisionallySave(submitted_form);

  PasswordForm new_credentials;
  EXPECT_CALL(MockFormSaver::Get(form_manager()), Update(_, _, _, nullptr))
      .WillOnce(testing::SaveArg<0>(&new_credentials));
  form_manager()->Save();

  EXPECT_EQ(PasswordForm::TYPE_MANUAL, new_credentials.type);
  EXPECT_EQ(ASCIIToUTF16("another_password"), new_credentials.password_value);
  histogram_tester.ExpectBucketCount("PasswordGeneration.SubmissionEvent",
                                     metrics_util::PASSWORD_OVERRIDDEN, 1);

  // On the reuse of the overriden password, the metric is not reported.
  fake_form_fetcher()->SetNonFederated({&new_credentials}, 0u);
  form_manager()->ProvisionallySave(new_credentials);
  EXPECT_CALL(MockFormSaver::Get(form_manager()), Update(_, _, _, _));
  form_manager()->Save();
  histogram_tester.ExpectBucketCount("PasswordGeneration.SubmissionEvent",
                                     metrics_util::PASSWORD_OVERRIDDEN, 1);
  histogram_tester.ExpectBucketCount("PasswordGeneration.SubmissionEvent",
                                     metrics_util::PASSWORD_USED, 0);
}

// Test that ProcessFrame is called on receiving matches from the fetcher,
// resulting in a FillPasswordForm call.
TEST_F(PasswordFormManagerTest, ProcessFrame) {
  EXPECT_CALL(*client()->mock_driver(), FillPasswordForm(_));
  fake_form_fetcher()->SetNonFederated({saved_match()}, 0u);
}

// Test that driver is informed when there are not saved credentials.
TEST_F(PasswordFormManagerTest, InformNoSavedCredentials) {
  EXPECT_CALL(*client()->mock_driver(), InformNoSavedCredentials());
  fake_form_fetcher()->SetNonFederated({}, 0u);
}

// Test that ProcessFrame can also be called directly, resulting in an
// additional FillPasswordForm call.
TEST_F(PasswordFormManagerTest, ProcessFrame_MoreProcessFrameMoreFill) {
  EXPECT_CALL(*client()->mock_driver(), FillPasswordForm(_)).Times(2);
  fake_form_fetcher()->SetNonFederated({saved_match()}, 0u);
  form_manager()->ProcessFrame(client()->mock_driver()->AsWeakPtr());
}

// Test that Chrome stops autofilling if triggered too many times.
TEST_F(PasswordFormManagerTest, ProcessFrame_MaxTimes) {
  constexpr int kMaxAutofills = PasswordFormManager::kMaxTimesAutofill;
  constexpr int kExtraProcessRequests = 3;
  // Expect one call for each ProcessFrame() and one for SetNonFederated().
  EXPECT_CALL(*client()->mock_driver(), FillPasswordForm(_))
      .Times(kMaxAutofills + 1);
  fake_form_fetcher()->SetNonFederated({saved_match()}, 0u);
  // Process more times to exceed the limit.
  for (int i = 0; i < kMaxAutofills + kExtraProcessRequests; i++) {
    form_manager()->ProcessFrame(client()->mock_driver()->AsWeakPtr());
  }
}

// Test that when ProcessFrame is called on a driver added after receiving
// matches, such driver is still told to call FillPasswordForm.
TEST_F(PasswordFormManagerTest, ProcessFrame_TwoDrivers) {
  NiceMock<MockPasswordManagerDriver> second_driver;

  EXPECT_CALL(*client()->mock_driver(), FillPasswordForm(_));
  EXPECT_CALL(second_driver, FillPasswordForm(_));
  fake_form_fetcher()->SetNonFederated({saved_match()}, 0u);
  form_manager()->ProcessFrame(second_driver.AsWeakPtr());
}

// Test that a second driver is added before receiving matches, such driver is
// also told to call FillPasswordForm once the matches arrive.
TEST_F(PasswordFormManagerTest, ProcessFrame_DriverBeforeMatching) {
  NiceMock<MockPasswordManagerDriver> second_driver;
  form_manager()->ProcessFrame(second_driver.AsWeakPtr());

  EXPECT_CALL(*client()->mock_driver(), FillPasswordForm(_));
  EXPECT_CALL(second_driver, FillPasswordForm(_));
  fake_form_fetcher()->SetNonFederated({saved_match()}, 0u);
}

// Test that if the fetcher updates the information about stored matches,
// autofill is re-triggered.
TEST_F(PasswordFormManagerTest, ProcessFrame_StoreUpdatesCausesAutofill) {
  EXPECT_CALL(*client()->mock_driver(), FillPasswordForm(_)).Times(2);
  std::vector<const PasswordForm*> matches = {saved_match()};
  fake_form_fetcher()->SetNonFederated(matches, 0u);
  fake_form_fetcher()->Fetch();
  fake_form_fetcher()->SetNonFederated(matches, 0u);
}

// TODO(crbug.com/639786): Restore the following test:
// when PasswordFormManager::Save or PasswordFormManager::Update is called, then
// PasswordFormManager also calls PasswordManager::UpdateFormManagers.

TEST_F(PasswordFormManagerTest, UploadChangePasswordForm) {
  autofill::ServerFieldType kChangePasswordVotes[] = {
      autofill::NEW_PASSWORD, autofill::PROBABLY_NEW_PASSWORD,
      autofill::NOT_NEW_PASSWORD};
  bool kFalseTrue[] = {false, true};
  for (autofill::ServerFieldType vote : kChangePasswordVotes) {
    for (bool has_confirmation_field : kFalseTrue)
      ChangePasswordUploadTest(vote, has_confirmation_field);
  }
}

TEST_F(PasswordFormManagerTest, TestUpdatePSLMatchedCredentials) {
  FakeFormFetcher fetcher;
  fetcher.Fetch();
  PasswordFormManager form_manager(password_manager(), client(),
                                   client()->driver(), *observed_form(),
                                   std::make_unique<MockFormSaver>(), &fetcher);
  form_manager.Init(nullptr);
  fetcher.SetNonFederated({saved_match(), psl_saved_match()}, 0u);

  // User submits a credentials with an old username and a new password.
  PasswordForm credentials(*observed_form());
  credentials.username_value = saved_match()->username_value;
  credentials.password_value = ASCIIToUTF16("new_password");
  credentials.preferred = true;
  form_manager.ProvisionallySave(credentials);

  // Successful login. The PasswordManager would instruct PasswordFormManager
  // to save, and since this is an update, it should know not to save as a new
  // login.
  EXPECT_FALSE(form_manager.IsNewLogin());

  // Trigger saving to exercise some special case handling during updating.
  PasswordForm new_credentials;
  std::vector<autofill::PasswordForm> credentials_to_update;
  EXPECT_CALL(MockFormSaver::Get(&form_manager), Update(_, _, _, nullptr))
      .WillOnce(testing::DoAll(SaveArg<0>(&new_credentials),
                               SaveArgPointee<2>(&credentials_to_update)));
  EXPECT_CALL(*client()->mock_driver()->mock_autofill_download_manager(),
              StartUploadRequest(_, false, _, _, true));

  form_manager.Save();

  // No meta-information should be updated, only the password.
  EXPECT_EQ(credentials.password_value, new_credentials.password_value);
  EXPECT_EQ(saved_match()->username_value, new_credentials.username_value);
  EXPECT_EQ(saved_match()->username_element, new_credentials.username_element);
  EXPECT_EQ(saved_match()->password_element, new_credentials.password_element);
  EXPECT_EQ(saved_match()->origin, new_credentials.origin);

  ASSERT_EQ(1u, credentials_to_update.size());
  EXPECT_EQ(credentials.password_value,
            credentials_to_update[0].password_value);
  EXPECT_EQ(psl_saved_match()->username_element,
            credentials_to_update[0].username_element);
  EXPECT_EQ(psl_saved_match()->username_element,
            credentials_to_update[0].username_element);
  EXPECT_EQ(psl_saved_match()->password_element,
            credentials_to_update[0].password_element);
  EXPECT_EQ(psl_saved_match()->origin, credentials_to_update[0].origin);
}

TEST_F(PasswordFormManagerTest,
       TestNotUpdatePSLMatchedCredentialsWithAnotherUsername) {
  FakeFormFetcher fetcher;
  fetcher.Fetch();
  PasswordFormManager form_manager(password_manager(), client(),
                                   client()->driver(), *observed_form(),
                                   std::make_unique<MockFormSaver>(), &fetcher);
  form_manager.Init(nullptr);
  psl_saved_match()->username_value += ASCIIToUTF16("1");
  fetcher.SetNonFederated({saved_match(), psl_saved_match()}, 0u);

  // User submits a credentials with an old username and a new password.
  PasswordForm credentials(*observed_form());
  credentials.username_value = saved_match()->username_value;
  credentials.password_value = ASCIIToUTF16("new_password");
  credentials.preferred = true;
  form_manager.ProvisionallySave(credentials);

  // Successful login. The PasswordManager would instruct PasswordFormManager
  // to save, and since this is an update, it should know not to save as a new
  // login.
  EXPECT_FALSE(form_manager.IsNewLogin());

  // Trigger saving to exercise some special case handling during updating.
  PasswordForm new_credentials;
  EXPECT_CALL(MockFormSaver::Get(&form_manager),
              Update(_, _, Pointee(IsEmpty()), nullptr))
      .WillOnce(testing::SaveArg<0>(&new_credentials));
  EXPECT_CALL(*client()->mock_driver()->mock_autofill_download_manager(),
              StartUploadRequest(_, false, _, _, true));

  form_manager.Save();

  // No meta-information should be updated, only the password.
  EXPECT_EQ(credentials.password_value, new_credentials.password_value);
  EXPECT_EQ(saved_match()->username_value, new_credentials.username_value);
  EXPECT_EQ(saved_match()->password_element, new_credentials.password_element);
  EXPECT_EQ(saved_match()->username_element, new_credentials.username_element);
  EXPECT_EQ(saved_match()->origin, new_credentials.origin);
}

TEST_F(PasswordFormManagerTest,
       TestNotUpdatePSLMatchedCredentialsWithAnotherPassword) {
  FakeFormFetcher fetcher;
  fetcher.Fetch();
  PasswordFormManager form_manager(password_manager(), client(),
                                   client()->driver(), *observed_form(),
                                   std::make_unique<MockFormSaver>(), &fetcher);
  form_manager.Init(nullptr);
  psl_saved_match()->password_value += ASCIIToUTF16("1");
  fetcher.SetNonFederated({saved_match(), psl_saved_match()}, 0u);

  // User submits a credentials with an old username and a new password.
  PasswordForm credentials(*observed_form());
  credentials.username_value = saved_match()->username_value;
  credentials.password_value = ASCIIToUTF16("new_password");
  credentials.preferred = true;
  form_manager.ProvisionallySave(credentials);

  // Successful login. The PasswordManager would instruct PasswordFormManager
  // to save, and since this is an update, it should know not to save as a new
  // login.
  EXPECT_FALSE(form_manager.IsNewLogin());

  // Trigger saving to exercise some special case handling during updating.
  PasswordForm new_credentials;
  EXPECT_CALL(MockFormSaver::Get(&form_manager),
              Update(_, _, Pointee(IsEmpty()), nullptr))
      .WillOnce(testing::SaveArg<0>(&new_credentials));
  EXPECT_CALL(*client()->mock_driver()->mock_autofill_download_manager(),
              StartUploadRequest(_, false, _, _, true));

  form_manager.Save();

  // No meta-information should be updated, only the password.
  EXPECT_EQ(credentials.password_value, new_credentials.password_value);
  EXPECT_EQ(saved_match()->username_value, new_credentials.username_value);
  EXPECT_EQ(saved_match()->password_element, new_credentials.password_element);
  EXPECT_EQ(saved_match()->username_element, new_credentials.username_element);
  EXPECT_EQ(saved_match()->origin, new_credentials.origin);
}

TEST_F(PasswordFormManagerTest, TestNotUpdateWhenOnlyPslMatched) {
  FakeFormFetcher fetcher;
  fetcher.Fetch();
  PasswordFormManager form_manager(password_manager(), client(),
                                   client()->driver(), *observed_form(),
                                   std::make_unique<MockFormSaver>(), &fetcher);
  form_manager.Init(nullptr);
  fetcher.SetNonFederated({psl_saved_match()}, 0u);

  // User submits a credentials with an old username and a new password.
  PasswordForm credentials(*observed_form());
  credentials.username_value = saved_match()->username_value;
  credentials.password_value = ASCIIToUTF16("new_password");
  credentials.preferred = true;
  form_manager.ProvisionallySave(credentials);

  EXPECT_TRUE(form_manager.IsNewLogin());

  // PSL matched credential should not be updated, since we are not sure that
  // this is the same credential as submitted one.
  PasswordForm new_credentials;
  EXPECT_CALL(MockFormSaver::Get(&form_manager), Save(_, _))
      .WillOnce(testing::SaveArg<0>(&new_credentials));
  // As the username is re-used, expect a username vote.
  EXPECT_CALL(*client()->mock_driver()->mock_autofill_download_manager(),
              StartUploadRequest(_, _, Contains(autofill::USERNAME), _, _));
  form_manager.Save();

  EXPECT_EQ(credentials.password_value, new_credentials.password_value);
  EXPECT_EQ(credentials.username_value, new_credentials.username_value);
  EXPECT_EQ(credentials.password_element, new_credentials.password_element);
  EXPECT_EQ(credentials.username_element, new_credentials.username_element);
  EXPECT_EQ(credentials.origin, new_credentials.origin);
}

TEST_F(PasswordFormManagerTest,
       TestSavingOnChangePasswordFormGenerationNoStoredForms) {
  fake_form_fetcher()->SetNonFederated(std::vector<const PasswordForm*>(), 0u);

  // User submits change password form and there is no stored credentials.
  PasswordForm credentials = *observed_form();
  credentials.username_element.clear();
  credentials.password_value = saved_match()->password_value;
  credentials.new_password_element = ASCIIToUTF16("NewPasswd");
  credentials.new_password_value = ASCIIToUTF16("new_password");
  credentials.preferred = true;
  form_manager()->PresaveGeneratedPassword(credentials);
  form_manager()->ProvisionallySave(credentials);

  // Successful login. The PasswordManager would instruct PasswordFormManager
  // to save, which should know this is a new login.
  EXPECT_TRUE(form_manager()->IsNewLogin());
  // Make sure the credentials that would be submitted on successful login
  // are going to match submitted form.
  EXPECT_EQ(observed_form()->origin.spec(),
            form_manager()->GetPendingCredentials().origin.spec());
  EXPECT_EQ(observed_form()->signon_realm,
            form_manager()->GetPendingCredentials().signon_realm);
  EXPECT_EQ(observed_form()->action,
            form_manager()->GetPendingCredentials().action);
  EXPECT_TRUE(form_manager()->GetPendingCredentials().preferred);
  EXPECT_EQ(ASCIIToUTF16("new_password"),
            form_manager()->GetPendingCredentials().password_value);
  EXPECT_EQ(base::string16(),
            form_manager()->GetPendingCredentials().username_value);
  EXPECT_TRUE(
      form_manager()->GetPendingCredentials().new_password_element.empty());
  EXPECT_TRUE(
      form_manager()->GetPendingCredentials().new_password_value.empty());
}

TEST_F(PasswordFormManagerTest, TestUpdatingOnChangePasswordFormGeneration) {
  fake_form_fetcher()->SetNonFederated({saved_match()}, 0u);

  // User submits credentials for the change password form, and old password is
  // coincide with password from an existing credentials, so stored credentials
  // should be updated.
  PasswordForm credentials = *observed_form();
  credentials.username_element.clear();
  credentials.password_value = saved_match()->password_value;
  credentials.new_password_element = ASCIIToUTF16("NewPasswd");
  credentials.new_password_value = ASCIIToUTF16("new_password");
  credentials.preferred = true;
  form_manager()->PresaveGeneratedPassword(credentials);
  form_manager()->ProvisionallySave(credentials);

  EXPECT_FALSE(form_manager()->IsNewLogin());
  // Make sure the credentials that would be submitted on successful login
  // are going to match the stored entry in the db.
  EXPECT_EQ(saved_match()->origin.spec(),
            form_manager()->GetPendingCredentials().origin.spec());
  EXPECT_EQ(saved_match()->signon_realm,
            form_manager()->GetPendingCredentials().signon_realm);
  EXPECT_EQ(observed_form()->action,
            form_manager()->GetPendingCredentials().action);
  EXPECT_TRUE(form_manager()->GetPendingCredentials().preferred);
  EXPECT_EQ(ASCIIToUTF16("new_password"),
            form_manager()->GetPendingCredentials().password_value);
  EXPECT_EQ(saved_match()->username_value,
            form_manager()->GetPendingCredentials().username_value);
  EXPECT_TRUE(
      form_manager()->GetPendingCredentials().new_password_element.empty());
  EXPECT_TRUE(
      form_manager()->GetPendingCredentials().new_password_value.empty());
}

TEST_F(PasswordFormManagerTest,
       TestSavingOnChangePasswordFormGenerationNoMatchedForms) {
  fake_form_fetcher()->SetNonFederated({saved_match()}, 0u);

  // User submits credentials for the change password form, and old password is
  // not coincide with password from existing credentials, so new credentials
  // should be saved.
  PasswordForm credentials = *observed_form();
  credentials.username_element.clear();
  credentials.password_value =
      saved_match()->password_value + ASCIIToUTF16("1");
  credentials.new_password_element = ASCIIToUTF16("NewPasswd");
  credentials.new_password_value = ASCIIToUTF16("new_password");
  credentials.preferred = true;
  form_manager()->PresaveGeneratedPassword(credentials);
  form_manager()->ProvisionallySave(credentials);

  EXPECT_TRUE(form_manager()->IsNewLogin());
  // Make sure the credentials that would be submitted on successful login
  // are going to match submitted form.
  EXPECT_EQ(observed_form()->origin.spec(),
            form_manager()->GetPendingCredentials().origin.spec());
  EXPECT_EQ(observed_form()->signon_realm,
            form_manager()->GetPendingCredentials().signon_realm);
  EXPECT_EQ(observed_form()->action,
            form_manager()->GetPendingCredentials().action);
  EXPECT_TRUE(form_manager()->GetPendingCredentials().preferred);
  EXPECT_EQ(ASCIIToUTF16("new_password"),
            form_manager()->GetPendingCredentials().password_value);
  EXPECT_EQ(base::string16(),
            form_manager()->GetPendingCredentials().username_value);
  EXPECT_TRUE(
      form_manager()->GetPendingCredentials().new_password_element.empty());
  EXPECT_TRUE(
      form_manager()->GetPendingCredentials().new_password_value.empty());
}

TEST_F(PasswordFormManagerTest,
       TestUploadVotesForPasswordChangeFormsWithTwoFields) {
  // Turn |observed_form_| into change password form with only 2 fields: an old
  // password and a new password.
  observed_form()->username_element.clear();
  observed_form()->new_password_element = ASCIIToUTF16("NewPasswd");
  autofill::FormFieldData field;
  field.label = ASCIIToUTF16("password");
  field.name = ASCIIToUTF16("Passwd");
  field.form_control_type = "password";
  observed_form()->form_data.fields.push_back(field);

  field.label = ASCIIToUTF16("new password");
  field.name = ASCIIToUTF16("NewPasswd");
  observed_form()->form_data.fields.push_back(field);

  FakeFormFetcher fetcher;
  fetcher.Fetch();
  PasswordFormManager form_manager(password_manager(), client(),
                                   client()->driver(), *observed_form(),
                                   std::make_unique<MockFormSaver>(), &fetcher);
  form_manager.Init(nullptr);
  fetcher.SetNonFederated({saved_match()}, 0u);

  // User submits current and new credentials to the observed form.
  PasswordForm submitted_form(*observed_form());
  submitted_form.password_value = saved_match()->password_value;
  submitted_form.new_password_value = ASCIIToUTF16("test2");
  submitted_form.preferred = true;
  form_manager.ProvisionallySave(submitted_form);

  // Successful login. The PasswordManager would instruct PasswordFormManager
  // to update.
  EXPECT_FALSE(form_manager.IsNewLogin());
  EXPECT_TRUE(form_manager.is_possible_change_password_form_without_username());

  // By now, the PasswordFormManager should have promoted the new password
  // value already to be the current password, and should no longer maintain
  // any info about the new password value.
  EXPECT_EQ(submitted_form.new_password_value,
            form_manager.GetPendingCredentials().password_value);
  EXPECT_TRUE(form_manager.GetPendingCredentials().new_password_value.empty());

  std::map<base::string16, autofill::ServerFieldType> expected_types;
  expected_types[observed_form()->password_element] = autofill::PASSWORD;
  expected_types[observed_form()->new_password_element] =
      autofill::NEW_PASSWORD;

  autofill::ServerFieldTypeSet expected_available_field_types;
  expected_available_field_types.insert(autofill::PASSWORD);
  expected_available_field_types.insert(autofill::NEW_PASSWORD);

  std::string expected_login_signature =
      autofill::FormStructure(saved_match()->form_data).FormSignatureAsStr();

  // First login vote.
  EXPECT_CALL(
      *client()->mock_driver()->mock_autofill_download_manager(),
      StartUploadRequest(SignatureIsSameAs(submitted_form), _, _, _, _));
  // Password change vote.
  EXPECT_CALL(*client()->mock_driver()->mock_autofill_download_manager(),
              StartUploadRequest(AllOf(UploadedAutofillTypesAre(expected_types),
                                       HasGenerationVote(false),
                                       SignatureIsSameAs(*observed_form())),
                                 false, expected_available_field_types,
                                 expected_login_signature, true));

  EXPECT_CALL(MockFormSaver::Get(&form_manager), Update(_, _, _, _));
  form_manager.Update(*saved_match());
}

// Checks uploading a vote about the usage of the password generation popup.
TEST_F(PasswordFormManagerTest, GeneratedVoteUpload) {
  bool kFalseTrue[] = {false, true};
  SavePromptInteraction kSavePromptInterations[] = {SAVE, NEVER,
                                                    NO_INTERACTION};
  for (bool is_manual_generation : kFalseTrue) {
    for (bool is_change_password_form : kFalseTrue) {
      for (bool has_generated_password : kFalseTrue) {
        for (bool generated_password_changed : kFalseTrue) {
          for (SavePromptInteraction interaction : kSavePromptInterations) {
            GeneratedVoteUploadTest(is_manual_generation,
                                    is_change_password_form,
                                    has_generated_password,
                                    generated_password_changed, interaction);
          }
        }
      }
    }
  }
}

TEST_F(PasswordFormManagerTest, GeneratedPasswordUkm) {
  bool kFalseTrue[] = {false, true};
  SavePromptInteraction kSavePromptInterations[] = {SAVE, NEVER,
                                                    NO_INTERACTION};
  for (bool is_manual_generation : kFalseTrue) {
    for (bool is_change_password_form : kFalseTrue) {
      for (bool has_generated_password : kFalseTrue) {
        for (bool generated_password_changed : kFalseTrue) {
          for (SavePromptInteraction interaction : kSavePromptInterations) {
            GeneratedPasswordUkmTest(is_manual_generation,
                                     is_change_password_form,
                                     has_generated_password,
                                     generated_password_changed, interaction);
          }
        }
      }
    }
  }
}

TEST_F(PasswordFormManagerTest, PresaveGeneratedPasswordAndRemoveIt) {
  PasswordForm credentials = *observed_form();

  // Simulate the user accepted a generated password.
  EXPECT_CALL(MockFormSaver::Get(form_manager()),
              PresaveGeneratedPassword(credentials));
  form_manager()->PresaveGeneratedPassword(credentials);
  EXPECT_TRUE(form_manager()->has_generated_password());
  EXPECT_FALSE(form_manager()->generated_password_changed());

  // Simulate the user changed the presaved password.
  credentials.password_value = ASCIIToUTF16("changed_password");
  EXPECT_CALL(MockFormSaver::Get(form_manager()),
              PresaveGeneratedPassword(credentials));
  form_manager()->PresaveGeneratedPassword(credentials);
  EXPECT_TRUE(form_manager()->has_generated_password());
  EXPECT_TRUE(form_manager()->generated_password_changed());

  // Simulate the user removed the presaved password.
  EXPECT_CALL(MockFormSaver::Get(form_manager()), RemovePresavedPassword());
  form_manager()->PasswordNoLongerGenerated();
}

TEST_F(PasswordFormManagerTest, FieldPropertiesMasksUpload) {
  PasswordForm form(*observed_form());
  form.form_data = saved_match()->form_data;

  // Create submitted form.
  PasswordForm submitted_form(form);
  submitted_form.preferred = true;
  submitted_form.username_value = saved_match()->username_value;
  submitted_form.password_value = saved_match()->password_value;

  FakeFormFetcher fetcher;
  fetcher.Fetch();
  PasswordFormManager form_manager(
      password_manager(), client(), client()->driver(), form,
      std::make_unique<NiceMock<MockFormSaver>>(), &fetcher);
  form_manager.Init(nullptr);
  fetcher.SetNonFederated(std::vector<const PasswordForm*>(), 0u);

  DCHECK_EQ(3U, form.form_data.fields.size());
  submitted_form.form_data.fields[1].properties_mask =
      FieldPropertiesFlags::USER_TYPED;
  submitted_form.form_data.fields[2].properties_mask =
      FieldPropertiesFlags::USER_TYPED;

  std::map<base::string16, autofill::FieldPropertiesMask>
      expected_field_properties;
  for (const autofill::FormFieldData& field : submitted_form.form_data.fields)
    if (field.properties_mask)
      expected_field_properties[field.name] = field.properties_mask;

  EXPECT_CALL(*client()->mock_driver()->mock_autofill_download_manager(),
              StartUploadRequest(
                  UploadedFieldPropertiesMasksAre(expected_field_properties),
                  false, _, _, true));
  form_manager.ProvisionallySave(submitted_form);
  form_manager.Save();
}

TEST_F(PasswordFormManagerTest, TestSavingAPIFormsWithSamePassword) {
  // Turn |observed_form| and |saved_match| to API created forms.
  observed_form()->username_element.clear();
  observed_form()->type = autofill::PasswordForm::TYPE_API;
  saved_match()->username_element.clear();
  saved_match()->type = autofill::PasswordForm::TYPE_API;

  FakeFormFetcher fetcher;
  fetcher.Fetch();
  PasswordFormManager form_manager(password_manager(), client(),
                                   client()->driver(), *observed_form(),
                                   std::make_unique<MockFormSaver>(), &fetcher);
  form_manager.Init(nullptr);
  fetcher.SetNonFederated({saved_match()}, 0u);

  // User submits new credentials with the same password as in already saved
  // one.
  PasswordForm credentials(*observed_form());
  credentials.username_value =
      saved_match()->username_value + ASCIIToUTF16("1");
  credentials.password_value = saved_match()->password_value;
  credentials.preferred = true;

  form_manager.ProvisionallySave(credentials);

  EXPECT_TRUE(form_manager.IsNewLogin());

  PasswordForm new_credentials;
  EXPECT_CALL(MockFormSaver::Get(&form_manager), Save(_, _))
      .WillOnce(SaveArg<0>(&new_credentials));

  form_manager.Save();

  EXPECT_EQ(saved_match()->username_value + ASCIIToUTF16("1"),
            new_credentials.username_value);
  EXPECT_EQ(saved_match()->password_value, new_credentials.password_value);
  EXPECT_EQ(base::string16(), new_credentials.username_element);
  EXPECT_EQ(autofill::PasswordForm::TYPE_API, new_credentials.type);
}

TEST_F(PasswordFormManagerTest, SkipZeroClickIntact) {
  saved_match()->skip_zero_click = true;
  psl_saved_match()->skip_zero_click = true;
  fake_form_fetcher()->SetNonFederated({saved_match(), psl_saved_match()}, 0u);
  EXPECT_EQ(1u, form_manager()->GetBestMatches().size());

  // User submits a credentials with an old username and a new password.
  PasswordForm credentials(*observed_form());
  credentials.username_value = saved_match()->username_value;
  credentials.password_value = ASCIIToUTF16("new_password");
  credentials.preferred = true;
  form_manager()->ProvisionallySave(credentials);

  // Trigger saving to exercise some special case handling during updating.
  PasswordForm new_credentials;
  std::vector<autofill::PasswordForm> credentials_to_update;
  EXPECT_CALL(MockFormSaver::Get(form_manager()), Update(_, _, _, nullptr))
      .WillOnce(testing::DoAll(SaveArg<0>(&new_credentials),
                               SaveArgPointee<2>(&credentials_to_update)));
  EXPECT_CALL(*client()->mock_driver()->mock_autofill_download_manager(),
              StartUploadRequest(_, false, _, _, true));
  form_manager()->Save();

  EXPECT_TRUE(new_credentials.skip_zero_click);
  ASSERT_EQ(1u, credentials_to_update.size());
  EXPECT_TRUE(credentials_to_update[0].skip_zero_click);
}

TEST_F(PasswordFormManagerFillOnAccountSelectTest, ProcessFrame) {
  EXPECT_CALL(*client()->mock_driver(),
              ShowInitialPasswordAccountSuggestions(_));
  fake_form_fetcher()->SetNonFederated({saved_match()}, 0u);
}

// Check that PasswordFormManager records
// PasswordManager_LoginFollowingAutofill as part of processing a credential
// update.
TEST_F(PasswordFormManagerTest, ReportProcessingUpdate) {
  fake_form_fetcher()->SetNonFederated({saved_match()}, 0u);
  PasswordForm pending = *observed_form();
  pending.username_value = saved_match()->username_value;
  pending.password_value = saved_match()->password_value;
  form_manager()->ProvisionallySave(pending);

  EXPECT_FALSE(form_manager()->IsNewLogin());
  EXPECT_CALL(*client()->mock_driver()->mock_autofill_download_manager(),
              StartUploadRequest(_, false, _, _, true));

  base::UserActionTester tester;
  EXPECT_EQ(0, tester.GetActionCount("PasswordManager_LoginFollowingAutofill"));
  form_manager()->Update(*saved_match());
  EXPECT_EQ(1, tester.GetActionCount("PasswordManager_LoginFollowingAutofill"));
}

// Sanity check for calling ProcessMatches with empty vector. Should not crash
// or make sanitizers scream.
TEST_F(PasswordFormManagerTest, ProcessMatches_Empty) {
  fake_form_fetcher()->SetNonFederated({}, 0u);
}

// For all combinations of PasswordForm schemes, test that ProcessMatches
// filters out forms with schemes not matching the observed form.
TEST_F(PasswordFormManagerTest, RemoveResultsWithWrongScheme_ObservingHTML) {
  for (int correct = 0; correct <= PasswordForm::SCHEME_LAST; ++correct) {
    for (int wrong = 0; wrong <= PasswordForm::SCHEME_LAST; ++wrong) {
      if (correct == wrong)
        continue;

      const PasswordForm::Scheme kCorrectScheme =
          static_cast<PasswordForm::Scheme>(correct);
      const PasswordForm::Scheme kWrongScheme =
          static_cast<PasswordForm::Scheme>(wrong);
      SCOPED_TRACE(testing::Message() << "Correct scheme = " << kCorrectScheme
                                      << ", wrong scheme = " << kWrongScheme);

      PasswordForm observed = *observed_form();
      observed.scheme = kCorrectScheme;
      FakeFormFetcher fetcher;
      fetcher.Fetch();
      PasswordFormManager form_manager(
          password_manager(), client(),
          (kCorrectScheme == PasswordForm::SCHEME_HTML ? client()->driver()
                                                       : nullptr),
          observed, std::make_unique<NiceMock<MockFormSaver>>(), &fetcher);
      form_manager.Init(nullptr);

      PasswordForm match = *saved_match();
      match.scheme = kCorrectScheme;

      PasswordForm non_match = match;
      non_match.scheme = kWrongScheme;

      // First try putting the correct scheme first in returned matches.
      fetcher.SetNonFederated({&match, &non_match}, 0);

      EXPECT_EQ(1u, form_manager.GetBestMatches().size());
      EXPECT_EQ(kCorrectScheme,
                form_manager.GetBestMatches().begin()->second->scheme);

      // Now try putting the correct scheme last in returned matches.
      fetcher.SetNonFederated({&non_match, &match}, 0);

      EXPECT_EQ(1u, form_manager.GetBestMatches().size());
      EXPECT_EQ(kCorrectScheme,
                form_manager.GetBestMatches().begin()->second->scheme);
    }
  }
}

// Ensure that DoesManage takes into consideration drivers when origins are
// different.
TEST_F(PasswordFormManagerTest, DoesManageDifferentOrigins) {
  for (bool same_drivers : {false, true}) {
    PasswordForm submitted_form(*observed_form());
    observed_form()->origin = GURL("http://accounts.google.com/a/Login");
    submitted_form.origin = GURL("http://accounts.google.com/signin");

    EXPECT_NE(observed_form()->origin, submitted_form.origin);

    NiceMock<MockPasswordManagerDriver> driver;
    EXPECT_EQ(
        same_drivers ? PasswordFormManager::RESULT_COMPLETE_MATCH
                     : PasswordFormManager::RESULT_NO_MATCH,
        form_manager()->DoesManage(
            submitted_form, same_drivers ? client()->driver().get() : &driver));
  }
}

// Ensure that DoesManage returns No match when signon realms are different.
TEST_F(PasswordFormManagerTest, DoesManageDifferentSignonRealmSameDrivers) {
  PasswordForm submitted_form(*observed_form());
  observed_form()->signon_realm = "http://accounts.google.com";
  submitted_form.signon_realm = "http://facebook.com";

  EXPECT_EQ(
      PasswordFormManager::RESULT_NO_MATCH,
      form_manager()->DoesManage(submitted_form, client()->driver().get()));
}

TEST_F(PasswordFormManagerTest, UploadUsernameCorrectionVote) {
  // TODO(rogerm,kolos): Fix this test so that it works correctly when the
  // enforcement of the minimum number of required for fields is upload is
  // relaxed.
  base::test::ScopedFeatureList features;
  features.InitAndEnableFeature(kAutofillEnforceMinRequiredFieldsForUpload);
  for (bool is_pending_credential_psl_match : {false, true}) {
    for (bool is_form_with_2_fields : {false, true}) {
      SCOPED_TRACE(testing::Message()
                   << "is_form_with_2_fields=" << is_form_with_2_fields);
      // Observed and saved forms have the same password, but different
      // usernames.
      PasswordForm new_login(*observed_form());
      autofill::FormFieldData field;
      if (!is_form_with_2_fields) {
        field.label = ASCIIToUTF16("Full name");
        field.name = ASCIIToUTF16("full_name");
        field.form_control_type = "text";
        new_login.form_data.fields.push_back(field);
      }
      field.label = ASCIIToUTF16("Email");
      field.name = ASCIIToUTF16("observed-username-field");
      field.form_control_type = "text";
      new_login.form_data.fields.push_back(field);

      field.label = ASCIIToUTF16("Password");
      field.name = ASCIIToUTF16("Passwd");
      field.form_control_type = "password";
      new_login.form_data.fields.push_back(field);

      const PasswordForm* saved_credential =
          is_pending_credential_psl_match ? psl_saved_match() : saved_match();

      new_login.username_value =
          saved_credential->other_possible_usernames[0].first;
      new_login.password_value = saved_credential->password_value;

      PasswordFormManager form_manager(
          password_manager(), client(), client()->driver(), new_login,
          std::make_unique<NiceMock<MockFormSaver>>(), fake_form_fetcher());
      form_manager.Init(nullptr);

      base::HistogramTester histogram_tester;
      fake_form_fetcher()->SetNonFederated({saved_credential}, 0u);
      form_manager.ProvisionallySave(new_login);
      histogram_tester.ExpectUniqueSample(
          "PasswordManager.UsernameCorrectionFound", 1, 1);
      // No match found (because usernames are different).
      EXPECT_TRUE(form_manager.IsNewLogin());

      // Checks the username correction vote is saved.
      PasswordForm expected_username_vote(*saved_credential);
      expected_username_vote.username_element =
          saved_credential->other_possible_usernames[0].second;

      // Checks the upload.
      autofill::ServerFieldTypeSet expected_available_field_types;
      expected_available_field_types.insert(autofill::USERNAME);
      expected_available_field_types.insert(
          autofill::ACCOUNT_CREATION_PASSWORD);

      std::string expected_login_signature =
          FormStructure(form_manager.observed_form().form_data)
              .FormSignatureAsStr();

      std::map<base::string16, autofill::ServerFieldType> expected_types;
      expected_types[expected_username_vote.username_element] =
          autofill::USERNAME;
      expected_types[expected_username_vote.password_element] =
          autofill::ACCOUNT_CREATION_PASSWORD;
      expected_types[ASCIIToUTF16("Email")] = autofill::UNKNOWN_TYPE;

      // Checks the type of the username vote is saved.
      VoteTypeMap expected_vote_types = {
          {expected_username_vote.username_element,
           autofill::AutofillUploadContents::Field::USERNAME_OVERWRITTEN}};

      InSequence s;
      std::unique_ptr<FormStructure> signin_vote_form_structure;
      if (is_form_with_2_fields) {
        // Make signin vote upload synchronous and free |FormStructure| passed
        // for upload.
        auto* mock_autofill_manager =
            client()->mock_driver()->mock_autofill_manager();
        EXPECT_CALL(*mock_autofill_manager,
                    MaybeStartVoteUploadProcessPtr(_, _, true))
            .WillOnce(WithArg<0>(SaveToUniquePtr(&signin_vote_form_structure)));
      } else {
        autofill::ServerFieldTypeSet field_types;
        field_types.insert(autofill::PASSWORD);
        EXPECT_CALL(
            *client()->mock_driver()->mock_autofill_download_manager(),
            StartUploadRequest(_, false, field_types, std::string(), true));
      }

      EXPECT_CALL(
          *client()->mock_driver()->mock_autofill_download_manager(),
          StartUploadRequest(AllOf(SignatureIsSameAs(expected_username_vote),
                                   UploadedAutofillTypesAre(expected_types),
                                   HasGenerationVote(false),
                                   VoteTypesAre(expected_vote_types)),
                             false, expected_available_field_types,
                             expected_login_signature, true));
      form_manager.Save();
    }
  }
}

TEST_F(PasswordFormManagerTest, NoUsernameCorrectionVote) {
  fake_form_fetcher()->SetNonFederated({saved_match()}, 0u);
  PasswordForm new_login = *observed_form();
  // The username is from |saved_match_.other_possible_usernames|, but the
  // password is different. So, no username correction found.
  new_login.username_value = ASCIIToUTF16("test2@gmail.com");
  new_login.password_value = ASCIIToUTF16("newpass");

  base::HistogramTester histogram_tester;
  form_manager()->ProvisionallySave(new_login);
  histogram_tester.ExpectUniqueSample("PasswordManager.UsernameCorrectionFound",
                                      0, 1);

  // Don't expect any vote uploads.
  EXPECT_CALL(*client()->mock_driver()->mock_autofill_download_manager(),
              StartUploadRequest(_, _, _, _, _))
      .Times(0);

  form_manager()->Save();
}

TEST_F(PasswordFormManagerTest,
       UsernameCorrectionVote_PasswordReusedWithoutUsername) {
  for (bool saved_username_is_empty : {false, true}) {
    SCOPED_TRACE(testing::Message()
                 << "saved_username_is_empty=" << saved_username_is_empty);

    if (saved_username_is_empty) {
      saved_match()->username_value.clear();
      // |username_element| must be empty as well, but it may be non-empty in
      // credentials saved in past versions. Let's test there will be not vote
      // for this element even if |username_element| has a non-empty value.
    }

    saved_match()->other_possible_usernames.push_back(
        ValueElementPair(base::string16(), ASCIIToUTF16("empty_field")));
    fake_form_fetcher()->SetNonFederated({saved_match()}, 0u);

    // A user enters the password in the form. The username is absent or not
    // captured, but the user doesn't enter the username in a prompt.
    PasswordForm credential(*saved_match());
    credential.username_value.clear();
    credential.preferred = true;
    form_manager()->ProvisionallySave(credential);
    EXPECT_FALSE(form_manager()->IsNewLogin());

    // Create the expected credential to be saved.
    PasswordForm expected_pending(*saved_match());
    expected_pending.times_used = 1;
    // As a credential is reused, |other_possible_usernames| will be cleared.
    // In fact, the username wasn't reused, only password, but for the sake of
    // simplicity |other_possible_usernames| is cleared even in this case.
    expected_pending.other_possible_usernames.clear();

    EXPECT_CALL(MockFormSaver::Get(form_manager()),
                Update(expected_pending,
                       ElementsAre(Pair(saved_match()->username_value,
                                        Pointee(*saved_match()))),
                       Pointee(IsEmpty()), nullptr));
    EXPECT_CALL(*client()->mock_driver()->mock_autofill_download_manager(),
                StartUploadRequest(_, _, _, _, _));
    EXPECT_CALL(
        *client()->mock_driver()->mock_autofill_download_manager(),
        StartUploadRequest(_, _, Not(Contains(autofill::USERNAME)), _, _));
    form_manager()->Save();
  }
}

// Test that ResetStoredMatches removes references to previously fetched store
// results.
TEST_F(PasswordFormManagerTest, ResetStoredMatches) {
  PasswordForm best_match1 = *observed_form();
  best_match1.username_value = ASCIIToUTF16("user1");
  best_match1.password_value = ASCIIToUTF16("pass");
  best_match1.preferred = true;

  PasswordForm best_match2 = best_match1;
  best_match2.username_value = ASCIIToUTF16("user2");
  best_match2.preferred = false;

  PasswordForm non_best_match = best_match1;
  non_best_match.action = GURL();

  PasswordForm blacklisted = *observed_form();
  blacklisted.blacklisted_by_user = true;
  blacklisted.username_value.clear();

  fake_form_fetcher()->SetNonFederated(
      {&best_match1, &best_match2, &non_best_match, &blacklisted}, 0u);

  EXPECT_EQ(2u, form_manager()->GetBestMatches().size());
  EXPECT_TRUE(form_manager()->GetPreferredMatch());
  EXPECT_EQ(1u, form_manager()->GetBlacklistedMatches().size());

  // Trigger Update to verify that there is a non-best match.
  PasswordForm updated(best_match1);
  updated.password_value = ASCIIToUTF16("updated password");
  form_manager()->ProvisionallySave(updated);
  std::vector<PasswordForm> credentials_to_update;
  EXPECT_CALL(MockFormSaver::Get(form_manager()), Update(_, _, _, nullptr))
      .WillOnce(SaveArgPointee<2>(&credentials_to_update));
  form_manager()->Save();

  PasswordForm updated_non_best = non_best_match;
  updated_non_best.password_value = updated.password_value;
  EXPECT_THAT(credentials_to_update, UnorderedElementsAre(updated_non_best));

  form_manager()->ResetStoredMatches();

  EXPECT_THAT(form_manager()->GetBestMatches(), IsEmpty());
  EXPECT_FALSE(form_manager()->GetPreferredMatch());
  EXPECT_THAT(form_manager()->GetBlacklistedMatches(), IsEmpty());

  // Simulate updating a saved credential again, but this time without non-best
  // matches. Verify that the old non-best matches are no longer present.
  fake_form_fetcher()->Fetch();
  fake_form_fetcher()->SetNonFederated({&best_match1}, 0u);

  form_manager()->ProvisionallySave(updated);
  credentials_to_update.clear();
  EXPECT_CALL(MockFormSaver::Get(form_manager()), Update(_, _, _, nullptr))
      .WillOnce(SaveArgPointee<2>(&credentials_to_update));
  form_manager()->Save();

  EXPECT_THAT(credentials_to_update, IsEmpty());
}

// Check that on changing FormFetcher, the PasswordFormManager removes itself
// from consuming the old one.
TEST_F(PasswordFormManagerTest, DropFetcherOnDestruction) {
  MockFormFetcher fetcher;
  FormFetcher::Consumer* added_consumer = nullptr;
  EXPECT_CALL(fetcher, AddConsumer(_)).WillOnce(SaveArg<0>(&added_consumer));
  auto form_manager = std::make_unique<PasswordFormManager>(
      password_manager(), client(), client()->driver(), *observed_form(),
      std::make_unique<MockFormSaver>(), &fetcher);
  form_manager->Init(nullptr);
  EXPECT_EQ(form_manager.get(), added_consumer);

  EXPECT_CALL(fetcher, RemoveConsumer(form_manager.get()));
  form_manager.reset();
}

// Check that if asked to take ownership of the same FormFetcher which it had
// consumed before, the PasswordFormManager does not add itself as a consumer
// again.
TEST_F(PasswordFormManagerTest, GrabFetcher_Same) {
  auto fetcher = std::make_unique<MockFormFetcher>();
  fetcher->Fetch();
  PasswordFormManager form_manager(
      password_manager(), client(), client()->driver(), *observed_form(),
      std::make_unique<MockFormSaver>(), fetcher.get());
  form_manager.Init(nullptr);

  EXPECT_CALL(*fetcher, AddConsumer(_)).Times(0);
  EXPECT_CALL(*fetcher, RemoveConsumer(_)).Times(0);
  form_manager.GrabFetcher(std::move(fetcher));
  // There will be a RemoveConsumer call as soon as form_manager goes out of
  // scope, but the test needs to ensure that there is none as a result of
  // GrabFetcher.
  Mock::VerifyAndClearExpectations(form_manager.GetFormFetcher());
}

// Check that if asked to take ownership of a different FormFetcher than which
// it had consumed before, the PasswordFormManager adds itself as a consumer
// and replaces the references to the old results.
TEST_F(PasswordFormManagerTest, GrabFetcher_Different) {
  PasswordForm old_match = *observed_form();
  old_match.username_value = ASCIIToUTF16("user1");
  old_match.password_value = ASCIIToUTF16("pass");
  fake_form_fetcher()->SetNonFederated({&old_match}, 0u);
  EXPECT_EQ(1u, form_manager()->GetBestMatches().size());
  EXPECT_EQ(&old_match, form_manager()->GetBestMatches().begin()->second);

  // |form_manager()| uses |fake_form_fetcher()|, which is an instance
  // different from |fetcher| below.
  auto fetcher = std::make_unique<MockFormFetcher>();
  fetcher->Fetch();
  fetcher->SetNonFederated(std::vector<const PasswordForm*>(), 0u);
  EXPECT_CALL(*fetcher, AddConsumer(form_manager()));
  form_manager()->GrabFetcher(std::move(fetcher));

  EXPECT_EQ(0u, form_manager()->GetBestMatches().size());
}

// Check that on changing FormFetcher, the PasswordFormManager removes itself
// from consuming the old one.
TEST_F(PasswordFormManagerTest, GrabFetcher_Remove) {
  MockFormFetcher old_fetcher;
  FormFetcher::Consumer* added_consumer = nullptr;
  EXPECT_CALL(old_fetcher, AddConsumer(_))
      .WillOnce(SaveArg<0>(&added_consumer));
  PasswordFormManager form_manager(
      password_manager(), client(), client()->driver(), *observed_form(),
      std::make_unique<MockFormSaver>(), &old_fetcher);
  form_manager.Init(nullptr);
  EXPECT_EQ(&form_manager, added_consumer);

  auto new_fetcher = std::make_unique<MockFormFetcher>();
  EXPECT_CALL(*new_fetcher, AddConsumer(&form_manager));
  EXPECT_CALL(old_fetcher, RemoveConsumer(&form_manager));
  form_manager.GrabFetcher(std::move(new_fetcher));
}

TEST_F(PasswordFormManagerTest, UploadSignInForm_WithAutofillTypes) {
  // For newly saved passwords on a sign-in form, upload an autofill vote for a
  // username field and a autofill::PASSWORD vote for a password field.
  autofill::FormFieldData field;
  field.name = ASCIIToUTF16("Email");
  field.form_control_type = "text";
  observed_form()->form_data.fields.push_back(field);

  field.name = ASCIIToUTF16("Passwd");
  field.form_control_type = "password";
  observed_form()->form_data.fields.push_back(field);

  FakeFormFetcher fetcher;
  fetcher.Fetch();
  PasswordFormManager form_manager(
      password_manager(), client(), client()->driver(), *observed_form(),
      std::make_unique<NiceMock<MockFormSaver>>(), &fetcher);
  form_manager.Init(nullptr);
  fetcher.SetNonFederated(std::vector<const PasswordForm*>(), 0u);

  PasswordForm form_to_save(*observed_form());
  form_to_save.preferred = true;
  form_to_save.username_value = ASCIIToUTF16("test@gmail.com");
  form_to_save.password_value = ASCIIToUTF16("password");

  std::unique_ptr<FormStructure> uploaded_form_structure;
  auto* mock_autofill_manager =
      client()->mock_driver()->mock_autofill_manager();
  EXPECT_CALL(*mock_autofill_manager,
              MaybeStartVoteUploadProcessPtr(_, _, true))
      .WillOnce(WithArg<0>(SaveToUniquePtr(&uploaded_form_structure)));
  form_manager.ProvisionallySave(form_to_save);
  form_manager.Save();

  ASSERT_EQ(2u, uploaded_form_structure->field_count());
  autofill::ServerFieldTypeSet expected_types = {autofill::PASSWORD};
  EXPECT_EQ(form_to_save.username_value,
            uploaded_form_structure->field(0)->value);
  EXPECT_EQ(expected_types,
            uploaded_form_structure->field(1)->possible_types());
}

// Checks that there is no upload on saving a password on a password form only
// with 1 field.
TEST_F(PasswordFormManagerTest, NoUploadsForSubmittedFormWithOnlyOneField) {
  autofill::FormFieldData field;
  field.name = ASCIIToUTF16("Passwd");
  field.form_control_type = "password";
  observed_form()->form_data.fields.push_back(field);

  FakeFormFetcher fetcher;
  fetcher.Fetch();
  PasswordFormManager form_manager(
      password_manager(), client(), client()->driver(), *observed_form(),
      std::make_unique<NiceMock<MockFormSaver>>(), &fetcher);
  form_manager.Init(nullptr);
  fetcher.SetNonFederated(std::vector<const PasswordForm*>(), 0u);

  PasswordForm form_to_save(*observed_form());
  form_to_save.preferred = true;
  form_to_save.password_value = ASCIIToUTF16("password");

  auto* mock_autofill_manager =
      client()->mock_driver()->mock_autofill_manager();
  EXPECT_CALL(*mock_autofill_manager, MaybeStartVoteUploadProcessPtr(_, _, _))
      .Times(0);
  form_manager.ProvisionallySave(form_to_save);
  form_manager.Save();
}

TEST_F(PasswordFormManagerTest,
       SuppressedHTTPSFormsHistogram_NotRecordedIfStoreWasTooSlow) {
  base::HistogramTester histogram_tester;

  fake_form_fetcher()->set_did_complete_querying_suppressed_forms(false);
  fake_form_fetcher()->Fetch();
  std::unique_ptr<PasswordFormManager> form_manager =
      std::make_unique<PasswordFormManager>(
          password_manager(), client(), client()->driver(), *observed_form(),
          std::make_unique<NiceMock<MockFormSaver>>(), fake_form_fetcher());
  form_manager->Init(nullptr);
  fake_form_fetcher()->SetNonFederated(std::vector<const PasswordForm*>(), 0u);
  form_manager.reset();

  histogram_tester.ExpectUniqueSample(
      "PasswordManager.QueryingSuppressedAccountsFinished", false, 1);
  const auto sample_counts = histogram_tester.GetTotalCountsForPrefix(
      "PasswordManager.SuppressedAccount.");
  EXPECT_THAT(sample_counts, IsEmpty());
}

TEST_F(PasswordFormManagerTest, SuppressedFormsHistograms) {
  static constexpr const struct {
    SuppressedFormType type;
    const char* expected_histogram_suffix;
    void (FakeFormFetcher::*suppressed_forms_setter_func)(
        const std::vector<const autofill::PasswordForm*>&);
  } kSuppressedFormTypeParams[] = {
      {SuppressedFormType::HTTPS, "HTTPSNotHTTP",
       &FakeFormFetcher::set_suppressed_https_forms},
      {SuppressedFormType::PSL_MATCH, "PSLMatching",
       &FakeFormFetcher::set_suppressed_psl_matching_forms},
      {SuppressedFormType::SAME_ORGANIZATION_NAME, "SameOrganizationName",
       &FakeFormFetcher::set_suppressed_same_organization_name_forms}};

  struct SuppressedFormData {
    const char* username_value;
    const char* password_value;
    PasswordForm::Type manual_or_generated;
  };

  static constexpr const char kUsernameAlpha[] = "user-alpha@gmail.com";
  static constexpr const char kPasswordAlpha[] = "password-alpha";
  static constexpr const char kUsernameBeta[] = "user-beta@gmail.com";
  static constexpr const char kPasswordBeta[] = "password-beta";

  static constexpr const SuppressedFormData kSuppressedGeneratedForm = {
      kUsernameAlpha, kPasswordAlpha, PasswordForm::TYPE_GENERATED};
  static constexpr const SuppressedFormData kOtherSuppressedGeneratedForm = {
      kUsernameBeta, kPasswordBeta, PasswordForm::TYPE_GENERATED};
  static constexpr const SuppressedFormData kSuppressedManualForm = {
      kUsernameAlpha, kPasswordBeta, PasswordForm::TYPE_MANUAL};

  const std::vector<const SuppressedFormData*> kSuppressedFormsNone;
  const std::vector<const SuppressedFormData*> kSuppressedFormsOneGenerated = {
      &kSuppressedGeneratedForm};
  const std::vector<const SuppressedFormData*> kSuppressedFormsTwoGenerated = {
      &kSuppressedGeneratedForm, &kOtherSuppressedGeneratedForm};
  const std::vector<const SuppressedFormData*> kSuppressedFormsOneManual = {
      &kSuppressedManualForm};
  const std::vector<const SuppressedFormData*> kSuppressedFormsTwoMixed = {
      &kSuppressedGeneratedForm, &kSuppressedManualForm};

  const struct {
    std::vector<const SuppressedFormData*> simulated_suppressed_forms;
    SimulatedManagerAction simulate_manager_action;
    SimulatedSubmitResult simulate_submit_result;
    const char* filled_username;
    const char* filled_password;
    int expected_histogram_sample_generated;
    int expected_histogram_sample_manual;
    const char* submitted_password;  // nullptr if same as |filled_password|.
  } kTestCases[] = {
      // See PasswordManagerSuppressedAccountCrossActionsTaken in enums.xml.
      //
      // Legend: (SuppressAccountType, SubmitResult, SimulatedManagerAction,
      // UserAction)
      // 24 = (None, Passed, None, OverrideUsernameAndPassword)
      {kSuppressedFormsNone, SimulatedManagerAction::NONE,
       SimulatedSubmitResult::PASSED, kUsernameAlpha, kPasswordAlpha, 24, 24},
      // 5 = (None, NotSubmitted, Autofilled, None)
      {kSuppressedFormsNone, SimulatedManagerAction::AUTOFILLED,
       SimulatedSubmitResult::NONE, kUsernameAlpha, kPasswordAlpha, 5, 5},
      // 15 = (None, Failed, Autofilled, None)
      {kSuppressedFormsNone, SimulatedManagerAction::AUTOFILLED,
       SimulatedSubmitResult::FAILED, kUsernameAlpha, kPasswordAlpha, 15, 15},

      // 35 = (Exists, NotSubmitted, Autofilled, None)
      {kSuppressedFormsOneGenerated, SimulatedManagerAction::AUTOFILLED,
       SimulatedSubmitResult::NONE, kUsernameAlpha, kPasswordAlpha, 35, 5},
      // 145 = (ExistsSameUsernameAndPassword, Passed, Autofilled, None)
      // 25 = (None, Passed, Autofilled, None)
      {kSuppressedFormsOneGenerated, SimulatedManagerAction::AUTOFILLED,
       SimulatedSubmitResult::PASSED, kUsernameAlpha, kPasswordAlpha, 145, 25},
      // 104 = (ExistsSameUsername, Failed, None, OverrideUsernameAndPassword)
      // 14 = (None, Failed, None, OverrideUsernameAndPassword)
      {kSuppressedFormsOneGenerated, SimulatedManagerAction::NONE,
       SimulatedSubmitResult::FAILED, kUsernameAlpha, kPasswordBeta, 104, 14},
      // 84 = (ExistsDifferentUsername, Passed, None,
      //       OverrideUsernameAndPassword)
      {kSuppressedFormsOneGenerated, SimulatedManagerAction::NONE,
       SimulatedSubmitResult::PASSED, kUsernameBeta, kPasswordAlpha, 84, 24},

      // 144 = (ExistsSameUsernameAndPassword, Passed, None,
      //        OverrideUsernameAndPassword)
      {kSuppressedFormsOneManual, SimulatedManagerAction::NONE,
       SimulatedSubmitResult::PASSED, kUsernameAlpha, kPasswordBeta, 24, 144},
      {kSuppressedFormsTwoMixed, SimulatedManagerAction::NONE,
       SimulatedSubmitResult::PASSED, kUsernameBeta, kPasswordAlpha, 84, 84},

      // 115 = (ExistsSameUsername, Passed, Autofilled, None)
      {kSuppressedFormsTwoGenerated, SimulatedManagerAction::AUTOFILLED,
       SimulatedSubmitResult::PASSED, kUsernameAlpha, kPasswordAlpha, 145, 25},
      {kSuppressedFormsTwoGenerated, SimulatedManagerAction::AUTOFILLED,
       SimulatedSubmitResult::PASSED, kUsernameAlpha, kPasswordBeta, 115, 25},
      {kSuppressedFormsTwoGenerated, SimulatedManagerAction::AUTOFILLED,
       SimulatedSubmitResult::PASSED, kUsernameBeta, kPasswordAlpha, 115, 25},
      {kSuppressedFormsTwoGenerated, SimulatedManagerAction::AUTOFILLED,
       SimulatedSubmitResult::PASSED, kUsernameBeta, kPasswordBeta, 145, 25},

      // 86 = (ExistsDifferentUsername, Passed, Autofilled, Choose)
      // 26 = (None, Passed, Autofilled, Choose)
      {kSuppressedFormsOneGenerated, SimulatedManagerAction::OFFERED,
       SimulatedSubmitResult::PASSED, kUsernameBeta, kPasswordAlpha, 86, 26},
      // 72 = (ExistsDifferentUsername, Failed, None, ChoosePSL)
      // 12 = (None, Failed, None, ChoosePSL)
      {kSuppressedFormsOneGenerated, SimulatedManagerAction::OFFERED_PSL,
       SimulatedSubmitResult::FAILED, kUsernameBeta, kPasswordAlpha, 72, 12},
      // 148 = (ExistsSameUsernameAndPassword, Passed, Autofilled,
      //        OverridePassword)
      // 28 = (None, Passed, Autofilled, OverridePassword)
      {kSuppressedFormsTwoGenerated, SimulatedManagerAction::AUTOFILLED,
       SimulatedSubmitResult::PASSED, kUsernameBeta, kPasswordAlpha, 148, 28,
       kPasswordBeta},
  };

  for (const auto& suppression_params : kSuppressedFormTypeParams) {
    for (const auto& test_case : kTestCases) {
      SCOPED_TRACE(suppression_params.expected_histogram_suffix);
      SCOPED_TRACE(test_case.expected_histogram_sample_manual);
      SCOPED_TRACE(test_case.expected_histogram_sample_generated);

      base::HistogramTester histogram_tester;
      ukm::TestAutoSetUkmRecorder test_ukm_recorder;

      std::vector<PasswordForm> suppressed_forms;
      for (const auto* form_data : test_case.simulated_suppressed_forms) {
        suppressed_forms.push_back(CreateSuppressedForm(
            suppression_params.type, form_data->username_value,
            form_data->password_value, form_data->manual_or_generated));
      }

      std::vector<const PasswordForm*> suppressed_forms_ptrs;
      for (const auto& form : suppressed_forms)
        suppressed_forms_ptrs.push_back(&form);

      FakeFormFetcher fetcher;
      fetcher.set_did_complete_querying_suppressed_forms(true);

      (&fetcher->*suppression_params.suppressed_forms_setter_func)(
          suppressed_forms_ptrs);

      SimulateActionsOnHTTPObservedForm(
          &fetcher, test_case.simulate_manager_action,
          test_case.simulate_submit_result, test_case.filled_username,
          test_case.filled_password, test_case.submitted_password);

      histogram_tester.ExpectUniqueSample(
          "PasswordManager.QueryingSuppressedAccountsFinished", true, 1);

      EXPECT_THAT(
          histogram_tester.GetAllSamples(
              "PasswordManager.SuppressedAccount.Generated." +
              std::string(suppression_params.expected_histogram_suffix)),
          ::testing::ElementsAre(
              base::Bucket(test_case.expected_histogram_sample_generated, 1)));
      EXPECT_THAT(
          histogram_tester.GetAllSamples(
              "PasswordManager.SuppressedAccount.Manual." +
              std::string(suppression_params.expected_histogram_suffix)),
          ::testing::ElementsAre(
              base::Bucket(test_case.expected_histogram_sample_manual, 1)));

      auto entries = test_ukm_recorder.GetEntriesByName(
          ukm::builders::PasswordForm::kEntryName);
      EXPECT_EQ(1u, entries.size());
      for (const auto* const entry : entries) {
        test_ukm_recorder.ExpectEntryMetric(
            entry,
            "SuppressedAccount.Generated." +
                std::string(suppression_params.expected_histogram_suffix),
            test_case.expected_histogram_sample_generated /
                PasswordFormMetricsRecorder::kMaxNumActionsTakenNew);
        test_ukm_recorder.ExpectEntryMetric(
            entry,
            "SuppressedAccount.Manual." +
                std::string(suppression_params.expected_histogram_suffix),
            test_case.expected_histogram_sample_manual /
                PasswordFormMetricsRecorder::kMaxNumActionsTakenNew);
      }
    }
  }
}

// If the frame containing the login form is served over HTTPS, no histograms on
// supressed HTTPS forms should be recorded. Everything else should still be.
TEST_F(PasswordFormManagerTest, SuppressedHTTPSFormsHistogram_NotRecordedFor) {
  base::HistogramTester histogram_tester;

  PasswordForm https_observed_form = *observed_form();
  https_observed_form.origin = GURL("https://accounts.google.com/a/LoginAuth");
  https_observed_form.signon_realm = "https://accounts.google.com/";

  // Only the scheme of the frame containing the login form maters, not the
  // scheme of the main frame.
  ASSERT_FALSE(client()->IsMainFrameSecure());

  // Even if there were any suppressed HTTPS forms, they should be are ignored
  // (but there should be none in production in this case).
  FakeFormFetcher fetcher;
  fetcher.set_suppressed_https_forms({saved_match()});
  fetcher.set_did_complete_querying_suppressed_forms(true);
  fetcher.Fetch();

  std::unique_ptr<PasswordFormManager> form_manager =
      std::make_unique<PasswordFormManager>(
          password_manager(), client(), client()->driver(), https_observed_form,
          std::make_unique<NiceMock<MockFormSaver>>(), &fetcher);
  form_manager->Init(nullptr);
  fetcher.SetNonFederated(std::vector<const PasswordForm*>(), 0u);
  form_manager.reset();

  histogram_tester.ExpectUniqueSample(
      "PasswordManager.QueryingSuppressedAccountsFinished", true, 1);
  histogram_tester.ExpectTotalCount(
      "PasswordManager.SuppressedAccount.Generated.HTTPSNotHTTP", 0);
  histogram_tester.ExpectTotalCount(
      "PasswordManager.SuppressedAccount.Manual.HTTPSNotHTTP", 0);
  histogram_tester.ExpectTotalCount(
      "PasswordManager.SuppressedAccount.Generated.PSLMatching", 1);
  histogram_tester.ExpectTotalCount(
      "PasswordManager.SuppressedAccount.Manual.PSLMatching", 1);
  histogram_tester.ExpectTotalCount(
      "PasswordManager.SuppressedAccount.Generated.SameOrganizationName", 1);
  histogram_tester.ExpectTotalCount(
      "PasswordManager.SuppressedAccount.Manual.SameOrganizationName", 1);
}

// Check that a cloned PasswordFormManager reacts correctly to Save.
TEST_F(PasswordFormManagerTest, Clone_OnSave) {
  FakeFormFetcher fetcher;
  auto form_manager = std::make_unique<PasswordFormManager>(
      password_manager(), client(), client()->driver(), *observed_form(),
      std::make_unique<MockFormSaver>(), &fetcher);
  form_manager->Init(nullptr);
  fetcher.SetNonFederated(std::vector<const PasswordForm*>(), 0u);

  PasswordForm saved_login = *observed_form();
  saved_login.username_value = ASCIIToUTF16("newuser");
  saved_login.password_value = ASCIIToUTF16("newpass");
  form_manager->ProvisionallySave(saved_login);

  const PasswordForm pending = form_manager->GetPendingCredentials();

  std::unique_ptr<PasswordFormManager> clone = form_manager->Clone();

  PasswordForm passed;
  EXPECT_CALL(MockFormSaver::Get(clone.get()), Save(_, IsEmpty()))
      .WillOnce(SaveArg<0>(&passed));
  clone->Save();
  // The date is expected to be different. Reset it so that we can easily
  // compare the rest with operator==.
  passed.date_created = pending.date_created;
  EXPECT_EQ(pending, passed);
}

// Check that a cloned PasswordFormManager reacts correctly to OnNeverClicked.
TEST_F(PasswordFormManagerTest, Clone_OnNeverClicked) {
  FakeFormFetcher fetcher;
  auto form_manager = std::make_unique<PasswordFormManager>(
      password_manager(), client(), client()->driver(), *observed_form(),
      std::make_unique<MockFormSaver>(), &fetcher);
  form_manager->Init(nullptr);
  fetcher.SetNonFederated(std::vector<const PasswordForm*>(), 0u);

  PasswordForm saved_login = *observed_form();
  saved_login.username_value = ASCIIToUTF16("newuser");
  saved_login.password_value = ASCIIToUTF16("newpass");
  form_manager->ProvisionallySave(saved_login);

  std::unique_ptr<PasswordFormManager> clone = form_manager->Clone();

  EXPECT_CALL(MockFormSaver::Get(clone.get()),
              PermanentlyBlacklist(Pointee(*observed_form())));
  clone->OnNeverClicked();
}

// Check that a cloned PasswordFormManager works even after the original is
// gone.
TEST_F(PasswordFormManagerTest, Clone_SurvivesOriginal) {
  FakeFormFetcher fetcher;
  auto form_manager = std::make_unique<PasswordFormManager>(
      password_manager(), client(), client()->driver(), *observed_form(),
      std::make_unique<MockFormSaver>(), &fetcher);
  fetcher.SetNonFederated(std::vector<const PasswordForm*>(), 0u);
  form_manager->Init(nullptr);

  PasswordForm saved_login = *observed_form();
  saved_login.username_value = ASCIIToUTF16("newuser");
  saved_login.password_value = ASCIIToUTF16("newpass");
  form_manager->ProvisionallySave(saved_login);

  const PasswordForm pending = form_manager->GetPendingCredentials();

  std::unique_ptr<PasswordFormManager> clone = form_manager->Clone();
  form_manager.reset();

  PasswordForm passed;
  EXPECT_CALL(MockFormSaver::Get(clone.get()), Save(_, IsEmpty()))
      .WillOnce(SaveArg<0>(&passed));
  clone->Save();
  // The date is expected to be different. Reset it so that we can easily
  // compare the rest with operator==.
  passed.date_created = pending.date_created;
  EXPECT_EQ(pending, passed);
}

// Verifies that URL keyed metrics are recorded for the filling of passwords
// into forms and HTTP Basic auth.
TEST_F(PasswordFormManagerTest, TestUkmForFilling) {
  PasswordForm scheme_basic_form = *observed_form();
  scheme_basic_form.scheme = PasswordForm::SCHEME_BASIC;

  const struct {
    // Whether the login is doing HTTP Basic Auth instead of form based login.
    bool is_http_basic_auth;
    // The matching stored credentials, or nullptr if none.
    PasswordForm* fetched_form;
    PasswordFormMetricsRecorder::ManagerAutofillEvent expected_event;
  } kTestCases[] = {
      {false, saved_match(),
       PasswordFormMetricsRecorder::kManagerFillEventAutofilled},
      {false, psl_saved_match(),
       PasswordFormMetricsRecorder::kManagerFillEventBlockedOnInteraction},
      {false, nullptr,
       PasswordFormMetricsRecorder::kManagerFillEventNoCredential},
      {true, &scheme_basic_form,
       PasswordFormMetricsRecorder::kManagerFillEventAutofilled},
      {true, nullptr,
       PasswordFormMetricsRecorder::kManagerFillEventNoCredential},
  };

  for (const auto& test : kTestCases) {
    const PasswordForm& form_to_fill =
        test.is_http_basic_auth ? scheme_basic_form : *observed_form();

    std::vector<const autofill::PasswordForm*> fetched_forms;
    if (test.fetched_form)
      fetched_forms.push_back(test.fetched_form);

    ukm::TestAutoSetUkmRecorder test_ukm_recorder;
    {
      auto metrics_recorder = base::MakeRefCounted<PasswordFormMetricsRecorder>(
          form_to_fill.origin.SchemeIsCryptographic(),
          client()->GetUkmSourceId());
      FakeFormFetcher fetcher;
      PasswordFormManager form_manager(
          password_manager(), client(),
          test.is_http_basic_auth ? nullptr : client()->driver(), form_to_fill,
          std::make_unique<NiceMock<MockFormSaver>>(), &fetcher);
      form_manager.Init(metrics_recorder);
      fetcher.SetNonFederated(fetched_forms, 0u);
    }

    auto entries = test_ukm_recorder.GetEntriesByName(
        ukm::builders::PasswordForm::kEntryName);
    EXPECT_EQ(1u, entries.size());
    for (const auto* const entry : entries) {
      EXPECT_EQ(client()->GetUkmSourceId(), entry->source_id);
      test_ukm_recorder.ExpectEntryMetric(
          entry, ukm::builders::PasswordForm::kManagerFill_ActionName,
          test.expected_event);
    }
  }
}

// Verifies that the form signature of forms is recorded in UKMs.
TEST_F(PasswordFormManagerTest, TestUkmContextMetrics) {
  ukm::TestAutoSetUkmRecorder test_ukm_recorder;
  test_ukm_recorder.UpdateSourceURL(client()->GetUkmSourceId(),
                                    client()->GetMainFrameURL());

  // Register two forms on one page.
  PasswordForm second_observed_form = *observed_form();
  second_observed_form.form_data.action = GURL("https://somewhere-else.com");
  for (PasswordForm* form : {observed_form(), &second_observed_form}) {
    auto metrics_recorder = base::MakeRefCounted<PasswordFormMetricsRecorder>(
        form->origin.SchemeIsCryptographic(), client()->GetUkmSourceId());
    FakeFormFetcher fetcher;
    PasswordFormManager form_manager(
        password_manager(), client(), client()->driver(), *form,
        std::make_unique<NiceMock<MockFormSaver>>(), &fetcher);
    form_manager.Init(metrics_recorder);
  }

  // Verify that a form signatures have been recorded in UKM.
  int64_t form_signature_1 = PasswordFormMetricsRecorder::HashFormSignature(
      CalculateFormSignature(observed_form()->form_data));
  int64_t form_signature_2 = PasswordFormMetricsRecorder::HashFormSignature(
      CalculateFormSignature(second_observed_form.form_data));

  EXPECT_GE(form_signature_1, 0);
  EXPECT_GE(form_signature_2, 0);

  auto entries = test_ukm_recorder.GetEntriesByName(
      ukm::builders::PasswordForm::kEntryName);
  ASSERT_EQ(2u, entries.size());

  const int64_t* metric1 = test_ukm_recorder.GetEntryMetric(
      entries[0], ukm::builders::PasswordForm::kContext_FormSignatureName);
  const int64_t* metric2 = test_ukm_recorder.GetEntryMetric(
      entries[1], ukm::builders::PasswordForm::kContext_FormSignatureName);

  ASSERT_TRUE(metric1);
  ASSERT_TRUE(metric2);

  EXPECT_THAT(
      std::vector<int64_t>({*metric1, *metric2}),
      ::testing::UnorderedElementsAre(form_signature_1, form_signature_2));
}

TEST_F(PasswordFormManagerTest,
       TestNotSendNotBlacklistedMessage_BlacklistedCredentials) {
  // Signing up on a previously visited site. Credentials are found in the
  // password store, but they are blacklisted. AllowPasswordGenerationForForm
  // is not called.
  EXPECT_CALL(*(client()->mock_driver()), AllowPasswordGenerationForForm(_))
      .Times(0);
  PasswordForm simulated_result = CreateSavedMatch(true);
  fake_form_fetcher()->SetNonFederated({&simulated_result}, 0u);
}

TEST_F(PasswordFormManagerTest, FirstLoginVote) {
  PasswordForm old_without_username = *saved_match();
  old_without_username.username_value.clear();
  old_without_username.username_element.clear();
  old_without_username.times_used = 2;
  struct {
    std::vector<const autofill::PasswordForm*> stored_creds;
    std::string description;
  } test_cases[] = {
      {{saved_match()}, "Credential reused"},
      {{psl_saved_match()}, "PSL credential reused"},
      {{&old_without_username},
       "Submitted credential adds a username to a stored credential without "
       "one"},
  };

  for (auto test_case : test_cases) {
    SCOPED_TRACE(testing::Message()
                 << "Stored credentials: " << test_case.description);

    fake_form_fetcher()->SetNonFederated(test_case.stored_creds, 0u);

    PasswordForm submitted_form =
        CreateMinimalCrowdsourcableForm(*observed_form());
    submitted_form.username_value = saved_match()->username_value;
    submitted_form.password_value = saved_match()->password_value;
    submitted_form.form_data.fields[0].value = submitted_form.username_value;
    submitted_form.form_data.fields[1].value = submitted_form.password_value;
    submitted_form.preferred = true;
    EXPECT_TRUE(FormStructure(submitted_form.form_data).ShouldBeUploaded());

    form_manager()->ProvisionallySave(submitted_form);

    // The username and password fields contain stored values. This should be
    // signaled in the vote.
    std::map<base::string16, autofill::FieldPropertiesMask>
        expected_field_properties = {{submitted_form.username_element,
                                      FieldPropertiesFlags::KNOWN_VALUE},
                                     {submitted_form.password_element,
                                      FieldPropertiesFlags::KNOWN_VALUE}};

    // All votes should be FIRST_USE.
    std::map<base::string16, autofill::AutofillUploadContents::Field::VoteType>
        expected_vote_types = {
            {submitted_form.username_element,
             autofill::AutofillUploadContents::Field::FIRST_USE},
            {submitted_form.password_element,
             autofill::AutofillUploadContents::Field::FIRST_USE}};

    // Unrelated vote
    EXPECT_CALL(
        *client()->mock_driver()->mock_autofill_download_manager(),
        StartUploadRequest(SignatureIsSameAs(*test_case.stored_creds.front()),
                           _, _, _, _))
        .Times(AtMost(1));
    // First login vote
    EXPECT_CALL(
        *client()->mock_driver()->mock_autofill_download_manager(),
        StartUploadRequest(
            AllOf(SignatureIsSameAs(submitted_form),
                  UploadedAutofillTypesAre(FieldTypeMap(
                      {{submitted_form.username_element, autofill::USERNAME},
                       {submitted_form.password_element, autofill::PASSWORD},
                       {ASCIIToUTF16("petname"), autofill::UNKNOWN_TYPE}})),
                  UploadedFieldPropertiesMasksAre(expected_field_properties),
                  VoteTypesAre(expected_vote_types)),
            _,
            autofill::ServerFieldTypeSet(
                {autofill::USERNAME, autofill::PASSWORD}),
            _, true));

    form_manager()->Save();

    Mock::VerifyAndClearExpectations(
        client()->mock_driver()->mock_autofill_download_manager());
  }
}

// Tests scenarios where no vote should be uploaded.
TEST_F(PasswordFormManagerTest, FirstLoginVote_NoVote) {
  PasswordForm old_credential(*saved_match());
  old_credential.times_used = 1;

  // A new username means a new credential. We will vote on it the next time it
  // is used, not now.
  PasswordForm different_username(*saved_match());
  different_username.username_value = ASCIIToUTF16("DifferentUsername");

  struct {
    std::vector<const autofill::PasswordForm*> stored_creds;
    std::string description;
  } test_cases[] = {
      {{}, "No credentials stored"},
      {{&old_credential}, "Not first use"},
      {{&different_username}, "Different username"},
  };

  for (auto test_case : test_cases) {
    SCOPED_TRACE(testing::Message()
                 << "Stored credentials: " << test_case.description);

    fake_form_fetcher()->SetNonFederated(test_case.stored_creds, 0u);

    // User submits credentials for the observed form.
    PasswordForm submitted_form =
        CreateMinimalCrowdsourcableForm(*observed_form());
    submitted_form.username_value = saved_match()->username_value;
    submitted_form.password_value = saved_match()->password_value;
    submitted_form.form_data.fields[0].value = submitted_form.username_value;
    submitted_form.form_data.fields[1].value = submitted_form.password_value;
    submitted_form.preferred = true;
    EXPECT_TRUE(FormStructure(submitted_form.form_data).ShouldBeUploaded());

    form_manager()->ProvisionallySave(submitted_form);

    EXPECT_CALL(*client()->mock_driver()->mock_autofill_download_manager(),
                StartUploadRequest(_, _, _, _, _))
        .Times(0);

    form_manager()->Save();

    Mock::VerifyAndClearExpectations(
        client()->mock_driver()->mock_autofill_download_manager());
  }
}

// If we update an existing credential with a new password, only the username is
// a known value.
TEST_F(PasswordFormManagerTest,
       FirstLoginVote_UpdatePasswordVotesOnlyForUsername) {
  PasswordForm different_password(*saved_match());
  different_password.password_value = ASCIIToUTF16("DifferentPassword");
  fake_form_fetcher()->SetNonFederated({&different_password}, 0u);

  PasswordForm submitted_form =
      CreateMinimalCrowdsourcableForm(*observed_form());
  submitted_form.username_value = saved_match()->username_value;
  submitted_form.password_value = saved_match()->password_value;
  submitted_form.form_data.fields[0].value = submitted_form.username_value;
  submitted_form.form_data.fields[1].value = submitted_form.password_value;
  submitted_form.preferred = true;
  EXPECT_TRUE(FormStructure(submitted_form.form_data).ShouldBeUploaded());

  form_manager()->ProvisionallySave(submitted_form);

  // The username and password fields contain stored values. This should be
  // signaled in the vote.
  std::map<base::string16, autofill::FieldPropertiesMask>
      expected_field_properties = {
          {submitted_form.username_element, FieldPropertiesFlags::KNOWN_VALUE},
          {submitted_form.password_element, 0}};

  // All votes should be FIRST_USE.
  std::map<base::string16, autofill::AutofillUploadContents::Field::VoteType>
      expected_vote_types = {
          {submitted_form.username_element,
           autofill::AutofillUploadContents::Field::FIRST_USE}};

  // Unrelated vote
  EXPECT_CALL(
      *client()->mock_driver()->mock_autofill_download_manager(),
      StartUploadRequest(SignatureIsSameAs(different_password), _, _, _, _))
      .Times(AtMost(1));
  // First login vote
  EXPECT_CALL(
      *client()->mock_driver()->mock_autofill_download_manager(),
      StartUploadRequest(
          AllOf(SignatureIsSameAs(submitted_form),
                UploadedAutofillTypesAre(FieldTypeMap(
                    {{submitted_form.username_element, autofill::USERNAME},
                     {submitted_form.password_element, autofill::UNKNOWN_TYPE},
                     {ASCIIToUTF16("petname"), autofill::UNKNOWN_TYPE}})),
                UploadedFieldPropertiesMasksAre(expected_field_properties),
                VoteTypesAre(expected_vote_types)),
          _, autofill::ServerFieldTypeSet({autofill::USERNAME}), _, true));

  form_manager()->Save();
}

// Values on a submitted form should be marked as KNOWN_VALUE only if they match
// values from the credential which was used to log in. Other stored credentials
// are ignored.
TEST_F(PasswordFormManagerTest, FirstLoginVote_MatchOnlySubmittedCredentials) {
  PasswordForm alternative_credential = *saved_match();
  alternative_credential.username_value = ASCIIToUTF16("flatmate");
  alternative_credential.password_value = ASCIIToUTF16("p@ssword");
  fake_form_fetcher()->SetNonFederated({&alternative_credential, saved_match()},
                                       0u);

  // User submits credentials for the observed form.
  PasswordForm submitted_form =
      CreateMinimalCrowdsourcableForm(*observed_form());
  submitted_form.username_value = saved_match()->username_value;
  submitted_form.password_value = saved_match()->password_value;
  submitted_form.form_data.fields[0].value = submitted_form.username_value;
  submitted_form.form_data.fields[1].value = submitted_form.password_value;
  // Use a value from an alternative credential. It should not be voted as a
  // known value.
  submitted_form.form_data.fields[2].value =
      alternative_credential.username_value;
  submitted_form.preferred = true;
  EXPECT_TRUE(FormStructure(submitted_form.form_data).ShouldBeUploaded());

  form_manager()->ProvisionallySave(submitted_form);

  // The username and password fields contain stored values. This should be
  // signaled in the vote.
  std::map<base::string16, autofill::FieldPropertiesMask>
      expected_field_properties = {
          {submitted_form.username_element, FieldPropertiesFlags::KNOWN_VALUE},
          {submitted_form.password_element, FieldPropertiesFlags::KNOWN_VALUE},
          {ASCIIToUTF16("petname"), 0}};

  // All votes should be FIRST_USE.
  std::map<base::string16, autofill::AutofillUploadContents::Field::VoteType>
      expected_vote_types = {
          {submitted_form.username_element,
           autofill::AutofillUploadContents::Field::FIRST_USE},
          {submitted_form.password_element,
           autofill::AutofillUploadContents::Field::FIRST_USE}};

  // Unrelated vote.
  EXPECT_CALL(*client()->mock_driver()->mock_autofill_download_manager(),
              StartUploadRequest(SignatureIsSameAs(*saved_match()), _, _, _, _))
      .Times(1);
  // First login vote.
  EXPECT_CALL(
      *client()->mock_driver()->mock_autofill_download_manager(),
      StartUploadRequest(
          AllOf(SignatureIsSameAs(submitted_form),
                UploadedAutofillTypesAre(FieldTypeMap(
                    {{submitted_form.username_element, autofill::USERNAME},
                     {submitted_form.password_element, autofill::PASSWORD},
                     {ASCIIToUTF16("petname"), autofill::UNKNOWN_TYPE}})),
                UploadedFieldPropertiesMasksAre(expected_field_properties),
                VoteTypesAre(expected_vote_types)),
          _,
          autofill::ServerFieldTypeSet(
              {autofill::USERNAME, autofill::PASSWORD}),
          _, true));

  form_manager()->Save();
}

TEST_F(PasswordFormManagerTest, FirstLoginVote_NoUsernameSaved) {
  // We have a credential without a username saved.
  saved_match()->username_element.clear();
  saved_match()->username_value.clear();
  fake_form_fetcher()->SetNonFederated({saved_match()}, 0u);

  // User submits credentials for the observed form.
  PasswordForm submitted_form =
      CreateMinimalCrowdsourcableForm(*observed_form());
  submitted_form.username_value = saved_match()->username_value;
  submitted_form.password_value = saved_match()->password_value;
  submitted_form.form_data.fields[0].value = submitted_form.username_value;
  submitted_form.form_data.fields[1].value = submitted_form.password_value;
  // An empty field should not be a known username, even if we have no username.
  submitted_form.form_data.fields[2].value.clear();
  submitted_form.preferred = true;
  EXPECT_TRUE(FormStructure(submitted_form.form_data).ShouldBeUploaded());

  form_manager()->ProvisionallySave(submitted_form);

  // The password field contains stored values. This should be signaled in the
  // vote.
  std::map<base::string16, autofill::FieldPropertiesMask>
      expected_field_properties = {
          {submitted_form.username_element, 0},  // Don't match empty values.
          {submitted_form.password_element, FieldPropertiesFlags::KNOWN_VALUE}};

  // All votes should be FIRST_USE.
  std::map<base::string16, autofill::AutofillUploadContents::Field::VoteType>
      expected_vote_types = {
          {submitted_form.username_element,
           autofill::AutofillUploadContents::Field::FIRST_USE},
          {submitted_form.password_element,
           autofill::AutofillUploadContents::Field::FIRST_USE},
          {ASCIIToUTF16("petname"),
           autofill::AutofillUploadContents::Field::NO_INFORMATION}};

  // Unrelated vote.
  EXPECT_CALL(*client()->mock_driver()->mock_autofill_download_manager(),
              StartUploadRequest(SignatureIsSameAs(*saved_match()), _, _, _, _))
      .Times(1);
  // First login vote.
  EXPECT_CALL(
      *client()->mock_driver()->mock_autofill_download_manager(),
      StartUploadRequest(
          AllOf(SignatureIsSameAs(submitted_form),
                UploadedAutofillTypesAre(FieldTypeMap(
                    {{submitted_form.username_element, autofill::USERNAME},
                     {submitted_form.password_element, autofill::PASSWORD},
                     {ASCIIToUTF16("petname"), autofill::UNKNOWN_TYPE}})),
                UploadedFieldPropertiesMasksAre(expected_field_properties),
                VoteTypesAre(expected_vote_types)),
          _,
          autofill::ServerFieldTypeSet(
              {autofill::USERNAME, autofill::PASSWORD}),
          _, true));

  form_manager()->Save();
}

// Upload a first login (i.e. first use) vote when the form has no username
// field.
TEST_F(PasswordFormManagerTest, FirstLoginVote_NoUsernameSubmitted) {
  fake_form_fetcher()->SetNonFederated({saved_match()}, 0u);

  // User submits credentials for the observed form.
  PasswordForm submitted_form = *observed_form();
  autofill::FormFieldData field;
  field.name = ASCIIToUTF16("password1");
  field.form_control_type = "password";
  submitted_form.form_data.fields.push_back(field);
  field.name = ASCIIToUTF16("password2");
  field.form_control_type = "new-password";
  submitted_form.form_data.fields.push_back(field);
  field.name = ASCIIToUTF16("password3");
  field.form_control_type = "new-password";
  submitted_form.form_data.fields.push_back(field);

  submitted_form.username_value.clear();
  submitted_form.username_element.clear();
  submitted_form.password_value = saved_match()->password_value;
  submitted_form.password_element = ASCIIToUTF16("password1");
  submitted_form.form_data.fields[0].value = saved_match()->password_value;
  submitted_form.form_data.fields[1].value = ASCIIToUTF16("newpassword");
  submitted_form.form_data.fields[2].value = ASCIIToUTF16("newpassword");
  submitted_form.preferred = true;
  EXPECT_TRUE(FormStructure(submitted_form.form_data).ShouldBeUploaded());

  form_manager()->ProvisionallySave(submitted_form);

  std::map<base::string16, autofill::FieldPropertiesMask>
      expected_field_properties = {
          {submitted_form.password_element, FieldPropertiesFlags::KNOWN_VALUE}};

  std::map<base::string16, autofill::AutofillUploadContents::Field::VoteType>
      expected_vote_types = {
          {submitted_form.password_element,
           autofill::AutofillUploadContents::Field::FIRST_USE}};

  FieldTypeMap expected_votes = {
      {submitted_form.form_data.fields[0].name, autofill::PASSWORD},
      {submitted_form.form_data.fields[1].name, autofill::UNKNOWN_TYPE},
      {submitted_form.form_data.fields[2].name, autofill::UNKNOWN_TYPE}};

  // Unrelated vote.
  EXPECT_CALL(*client()->mock_driver()->mock_autofill_download_manager(),
              StartUploadRequest(SignatureIsSameAs(*saved_match()), _, _, _, _))
      .Times(1);
  // First login vote.
  EXPECT_CALL(
      *client()->mock_driver()->mock_autofill_download_manager(),
      StartUploadRequest(
          AllOf(SignatureIsSameAs(submitted_form),
                UploadedAutofillTypesAre(expected_votes),
                UploadedFieldPropertiesMasksAre(expected_field_properties),
                VoteTypesAre(expected_vote_types)),
          _, autofill::ServerFieldTypeSet({autofill::PASSWORD}), _, true));

  form_manager()->Save();
}

// All fields with a known value should have the KNOWN_VALUE flag.
TEST_F(PasswordFormManagerTest, FirstLoginVote_KnownValue) {
  fake_form_fetcher()->SetNonFederated({saved_match()}, 0u);

  autofill::FormFieldData field;
  field.name = ASCIIToUTF16("email");
  field.form_control_type = "text";
  observed_form()->form_data.fields.push_back(field);
  field.name = ASCIIToUTF16("petname");
  field.form_control_type = "text";
  observed_form()->form_data.fields.push_back(field);
  field.name = ASCIIToUTF16("pin");
  field.form_control_type = "password";
  observed_form()->form_data.fields.push_back(field);
  field.name = ASCIIToUTF16("password");
  field.form_control_type = "password";
  observed_form()->form_data.fields.push_back(field);
  field.name = ASCIIToUTF16("repeat password");
  field.form_control_type = "password";
  observed_form()->form_data.fields.push_back(field);
  field.name = ASCIIToUTF16("repeat email");
  field.form_control_type = "text";
  observed_form()->form_data.fields.push_back(field);
  field.name = ASCIIToUTF16("empty password");
  field.form_control_type = "password";
  observed_form()->form_data.fields.push_back(field);
  field.name = ASCIIToUTF16("empty text");
  field.form_control_type = "text";
  observed_form()->form_data.fields.push_back(field);
  observed_form()->username_element = ASCIIToUTF16("email");
  observed_form()->password_element = ASCIIToUTF16("password");
  // User submits credentials for the observed form.
  PasswordForm submitted_form = *observed_form();
  submitted_form.username_value = saved_match()->username_value;
  submitted_form.password_value = saved_match()->password_value;
  submitted_form.form_data.fields[0].value = submitted_form.username_value;
  submitted_form.form_data.fields[1].value = ASCIIToUTF16("Snoop");
  submitted_form.form_data.fields[2].value = ASCIIToUTF16("1234");
  submitted_form.form_data.fields[3].value = submitted_form.password_value;
  submitted_form.form_data.fields[4].value = submitted_form.password_value;
  submitted_form.form_data.fields[5].value = submitted_form.username_value;
  submitted_form.form_data.fields[6].value.clear();
  submitted_form.form_data.fields[7].value.clear();
  submitted_form.preferred = true;
  EXPECT_TRUE(FormStructure(submitted_form.form_data).ShouldBeUploaded());

  form_manager()->ProvisionallySave(submitted_form);

  std::map<base::string16, autofill::FieldPropertiesMask>
      expected_field_properties = {
          {submitted_form.form_data.fields[0].name,
           FieldPropertiesFlags::KNOWN_VALUE},
          {submitted_form.form_data.fields[1].name, 0},
          {submitted_form.form_data.fields[2].name, 0},
          {submitted_form.form_data.fields[3].name,
           FieldPropertiesFlags::KNOWN_VALUE},
          {submitted_form.form_data.fields[4].name,
           FieldPropertiesFlags::KNOWN_VALUE},
          {submitted_form.form_data.fields[5].name,
           FieldPropertiesFlags::KNOWN_VALUE},
          {submitted_form.form_data.fields[6].name, 0},
          {submitted_form.form_data.fields[7].name, 0}};

  // Only the detected username_element and password_element fields should have
  // a USERNAME and PASSWORD vote.
  std::map<base::string16, autofill::AutofillUploadContents::Field::VoteType>
      expected_vote_types = {
          {submitted_form.form_data.fields[0].name,
           autofill::AutofillUploadContents::Field::FIRST_USE},
          {submitted_form.form_data.fields[1].name,
           autofill::AutofillUploadContents::Field::NO_INFORMATION},
          {submitted_form.form_data.fields[2].name,
           autofill::AutofillUploadContents::Field::NO_INFORMATION},
          {submitted_form.form_data.fields[3].name,
           autofill::AutofillUploadContents::Field::FIRST_USE},
          {submitted_form.form_data.fields[4].name,
           autofill::AutofillUploadContents::Field::NO_INFORMATION},
          {submitted_form.form_data.fields[5].name,
           autofill::AutofillUploadContents::Field::NO_INFORMATION},
          {submitted_form.form_data.fields[6].name,
           autofill::AutofillUploadContents::Field::NO_INFORMATION},
          {submitted_form.form_data.fields[7].name,
           autofill::AutofillUploadContents::Field::NO_INFORMATION}};

  FieldTypeMap expected_votes = {
      {submitted_form.username_element, autofill::USERNAME},
      {submitted_form.form_data.fields[1].name, autofill::UNKNOWN_TYPE},
      {submitted_form.form_data.fields[2].name, autofill::UNKNOWN_TYPE},
      {submitted_form.password_element, autofill::PASSWORD},
      {submitted_form.form_data.fields[4].name, autofill::UNKNOWN_TYPE},
      {submitted_form.form_data.fields[5].name, autofill::UNKNOWN_TYPE},
      {submitted_form.form_data.fields[6].name, autofill::UNKNOWN_TYPE},
      {submitted_form.form_data.fields[7].name, autofill::UNKNOWN_TYPE}};

  // Unrelated vote.
  EXPECT_CALL(*client()->mock_driver()->mock_autofill_download_manager(),
              StartUploadRequest(SignatureIsSameAs(*saved_match()), _, _, _, _))
      .Times(1);
  // First login vote.
  EXPECT_CALL(
      *client()->mock_driver()->mock_autofill_download_manager(),
      StartUploadRequest(
          AllOf(SignatureIsSameAs(submitted_form),
                UploadedAutofillTypesAre(expected_votes),
                UploadedFieldPropertiesMasksAre(expected_field_properties),
                VoteTypesAre(expected_vote_types)),
          _,
          autofill::ServerFieldTypeSet(
              {autofill::USERNAME, autofill::PASSWORD}),
          _, true));

  form_manager()->Save();
}

TEST_F(PasswordFormManagerTest, UploadPasswordAttributesVote) {
  PasswordForm credentials = *observed_form();
  // Set FormData to enable crowdsourcing.
  credentials.form_data = saved_match()->form_data;
  FakeFormFetcher fetcher;
  PasswordFormManager form_manager(
      password_manager(), client(), client()->driver(), credentials,
      std::make_unique<NiceMock<MockFormSaver>>(), &fetcher);
  form_manager.Init(nullptr);
  fetcher.SetNonFederated(std::vector<const PasswordForm*>(), 0u);

  credentials.username_value = saved_match()->username_value;
  credentials.password_value = ASCIIToUTF16("12345");
  form_manager.ProvisionallySave(credentials);

  EXPECT_CALL(
      *client()->mock_driver()->mock_autofill_download_manager(),
      StartUploadRequest(HasPasswordAttributesVote(true /* is_vote_expected */),
                         _, _, _, _));
  form_manager.Save();
}

TEST_F(PasswordFormManagerTest, PresaveGeneratedPassword_UnknownUsername) {
  // Checks whether the generated password is presaved with the captured
  // username. The username is new, so there will be no credentail override.
  fake_form_fetcher()->SetNonFederated({saved_match()}, 0u);
  PasswordForm credentials = *observed_form();
  credentials.username_value = ASCIIToUTF16("new_user");
  credentials.password_value = ASCIIToUTF16("generatated_password");

  EXPECT_CALL(MockFormSaver::Get(form_manager()),
              PresaveGeneratedPassword(credentials));
  form_manager()->PresaveGeneratedPassword(credentials);
}

TEST_F(PasswordFormManagerTest, PresaveGeneratedPassword_KnownUsername) {
  // Checks whether the generated password is presaved with empty username if
  // there is already an entry with the captured username in the store.
  PasswordForm saved_form_without_username(*saved_match());
  saved_form_without_username.username_value.clear();
  fake_form_fetcher()->SetNonFederated(
      {saved_match(), &saved_form_without_username}, 0u);
  PasswordForm credentials = *observed_form();
  credentials.username_value = saved_match()->username_value;
  credentials.password_value = ASCIIToUTF16("generatated_password");

  PasswordForm credentials_without_username(credentials);
  credentials_without_username.username_value.clear();
  EXPECT_CALL(MockFormSaver::Get(form_manager()),
              PresaveGeneratedPassword(credentials_without_username));
  form_manager()->PresaveGeneratedPassword(credentials);
}

TEST_F(PasswordFormManagerTest, PresaveGeneratedPassword_EmptyUsername) {
  // Checks whether the generated password is presaved even if the captured
  // username is empty.
  PasswordForm saved_form_without_username(*saved_match());
  saved_form_without_username.username_value.clear();
  fake_form_fetcher()->SetNonFederated(
      {saved_match(), &saved_form_without_username}, 0u);
  PasswordForm credentials = *observed_form();
  credentials.username_value.clear();
  credentials.password_value = ASCIIToUTF16("generatated_password");

  EXPECT_CALL(MockFormSaver::Get(form_manager()),
              PresaveGeneratedPassword(credentials));
  form_manager()->PresaveGeneratedPassword(credentials);
}

}  // namespace password_manager
