chromium/chrome/renderer/autofill/password_autofill_agent_browsertest.cc

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

#include "components/autofill/content/renderer/password_autofill_agent.h"

#include <vector>

#include "base/command_line.h"
#include "base/functional/bind.h"
#include "base/numerics/safe_conversions.h"
#include "base/run_loop.h"
#include "base/strings/strcat.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/mock_callback.h"
#include "base/test/scoped_feature_list.h"
#include "base/test/test_future.h"
#include "build/build_config.h"
#include "chrome/renderer/autofill/fake_mojo_password_manager_driver.h"
#include "chrome/renderer/autofill/fake_password_generation_driver.h"
#include "chrome/renderer/autofill/password_generation_test_utils.h"
#include "chrome/test/base/chrome_render_view_test.h"
#include "components/autofill/content/renderer/autofill_agent.h"
#include "components/autofill/content/renderer/autofill_agent_test_api.h"
#include "components/autofill/content/renderer/form_autofill_util.h"
#include "components/autofill/content/renderer/form_tracker.h"
#include "components/autofill/content/renderer/password_generation_agent.h"
#include "components/autofill/content/renderer/test_password_autofill_agent.h"
#include "components/autofill/core/common/autofill_constants.h"
#include "components/autofill/core/common/autofill_features.h"
#include "components/autofill/core/common/autofill_switches.h"
#include "components/autofill/core/common/form_data.h"
#include "components/autofill/core/common/form_field_data.h"
#include "components/autofill/core/common/mojom/autofill_types.mojom.h"
#include "components/autofill/core/common/password_form_fill_data.h"
#include "components/autofill/core/common/unique_ids.h"
#include "components/password_manager/core/common/password_manager_constants.h"
#include "components/password_manager/core/common/password_manager_features.h"
#include "components/safe_browsing/buildflags.h"
#include "content/public/renderer/render_frame.h"
#include "content/public/test/browser_test_utils.h"
#include "mojo/public/cpp/bindings/pending_associated_receiver.h"
#include "services/service_manager/public/cpp/interface_provider.h"
#include "testing/gtest/include/gtest/gtest-param-test.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h"
#include "third_party/blink/public/common/features.h"
#include "third_party/blink/public/platform/web_string.h"
#include "third_party/blink/public/platform/web_vector.h"
#include "third_party/blink/public/web/web_document.h"
#include "third_party/blink/public/web/web_form_element.h"
#include "third_party/blink/public/web/web_frame_widget.h"
#include "third_party/blink/public/web/web_input_element.h"
#include "third_party/blink/public/web/web_local_frame.h"
#include "third_party/blink/public/web/web_local_frame_client.h"
#include "ui/events/keycodes/keyboard_codes.h"

#if BUILDFLAG(IS_WIN)
#include "third_party/blink/public/web/win/web_font_rendering.h"
#endif

namespace autofill {

namespace {

FormRendererId;
FormTracker;
FocusedFieldType;
SubmissionIndicatorEvent;
ASCIIToUTF16;
UTF16ToUTF8;
WebAutofillState;
WebDocument;
WebElement;
WebFormElement;
WebFrame;
WebInputElement;
WebLocalFrame;
WebString;
_;
AllOf;
AtMost;
Eq;
Field;
Truly;

// The name of the username/password element in the form.
const char kUsernameName[] =;
const char kPasswordName[] =;
const char kSearchField[] =;
const char kSocialMediaTextArea[] =;

const char kAliceUsername[] =;
const char16_t kAliceUsername16[] =;
const char kAlicePassword[] =;
const char16_t kAlicePassword16[] =;
const char kBobUsername[] =;
const char16_t kBobUsername16[] =;
const char kBobPassword[] =;
const char16_t kBobPassword16[] =;
const char16_t kCarolUsername16[] =;
const char kCarolPassword[] =;
const char16_t kCarolPassword16[] =;
const char16_t kCarolAlternateUsername16[] =;

const char kFormHTML[] =;

#if BUILDFLAG(IS_ANDROID)
const char kFormWithUsernameFieldWebauthnHTML[] =
    "<FORM id='LoginTestForm' action='http://www.example.com'>"
    "  <INPUT type='text' id='username' autocomplete='webauthn'/>"
    "  <INPUT type='password' id='password'/>"
    "  <INPUT type='submit' value='Login'/>"
    "</FORM>";

const char kFormWithPasswordFieldWebauthnHTML[] =
    "<FORM id='LoginTestForm' action='http://www.example.com'>"
    "  <INPUT type='text' id='username'/>"
    "  <INPUT type='password' id='password' autocomplete='webauthn'/>"
    "  <INPUT type='submit' value='Login'/>"
    "</FORM>";
#endif  // BUILDFLAG(IS_ANDROID)

const char kSocialNetworkPostFormHTML[] =;

const char kSearchFieldHTML[] =;

const char kWebAutnFieldHTML[] =;

const char kVisibleFormWithNoUsernameHTML[] =;

const char kSingleUsernameFormHTML[] =;

const char kSingleTextInputFormHTML[] =;

const char kEmptyFormHTML[] =;

const char kFormWithoutPasswordsHTML[] =;

const char kNonVisibleFormHTML[] =;

const char kNonDisplayedFormHTML[] =;

const char kSignupFormHTML[] =;

const char kEmptyWebpage[] =;

const char kRedirectionWebpage[] =;

const char kSimpleWebpage[] =;

const char kWebpageWithDynamicContent[] =;

const char kJavaScriptClick[] =;

const char kPasswordChangeFormHTML[] =;

const char kCreditCardFormHTML[] =;

const char kNoFormHTML[] =;

const char kTwoNoUsernameFormsHTML[] =;

const char kDivWrappedFormHTML[] =;

const char kJavaScriptRemoveForm[] =;

const char kFormTagHostsShadowDomInputs[] =;

constexpr std::string_view kUnownedFieldsWithPasswordDisabled =;

// Sets the "readonly" attribute of `element` to the value given by `read_only`.
void SetElementReadOnly(WebInputElement& element, bool read_only) {}

bool FormHasFieldWithValue(const autofill::FormData& form,
                           const std::u16string& value) {}

enum PasswordFormSourceType {};

enum class FieldChangeSource {};

// Returns the expected number of calls to AskForValuesToFill. On Android,
// a redundant call may be made when the focus changes to the field.
//
// Since test cases simulate multiple clicks, some of which lead to focus
// changes while others do not, finding the exact number of expected calls on
// Android is tedious. Using GMock's checkpoint pattern would help with that.
auto NumShowSuggestionsCalls() {}

class PasswordAutofillAgentTest : public ChromeRenderViewTest {};

// Tests that the password login is autocompleted as expected when the browser
// sends back the password info.
TEST_F(PasswordAutofillAgentTest, InitialAutocomplete) {}

// Tests that we correctly fill forms having an empty 'action' attribute.
TEST_F(PasswordAutofillAgentTest, InitialAutocompleteForEmptyAction) {}

// Tests that if a password is marked as readonly, neither field is autofilled
// on page load.
TEST_F(PasswordAutofillAgentTest, NoInitialAutocompleteForReadOnlyPassword) {}

// Can still fill a password field if the username is set to a value that
// matches.
TEST_F(PasswordAutofillAgentTest,
       AutocompletePasswordForReadonlyUsernameMatched) {}

// Fill username and password fields when username field contains a prefilled
// value that matches the list of known possible prefilled values usually used
// as placeholders.
TEST_F(PasswordAutofillAgentTest, AutocompleteForPrefilledUsernameValue) {}

// Tests that if filling is invoked twice for the same autofill agent the
// prefilled username and first filling metrics are only logged once.
TEST_F(PasswordAutofillAgentTest, MetricsOnlyLoggedOnce) {}

// Fill a password field if the stored username is a prefix of username in
// read-only field.
TEST_F(PasswordAutofillAgentTest,
       AutocompletePasswordForReadonlyUsernamePrefixMatched) {}

// Credentials are sent to the renderer even for sign-up forms as these may be
// eligible for filling via manual fall back. In this case, the username_field
// and password_field are not set. This test verifies that no failures are
// recorded in PasswordManager.FirstRendererFillingResult.
TEST_F(PasswordAutofillAgentTest, NoFillingOnSignupForm_NoMetrics) {}

// Do not fill a password field if the stored username is a prefix without @
// of username in read-only field.
TEST_F(PasswordAutofillAgentTest,
       DontAutocompletePasswordForReadonlyUsernamePrefixMatched) {}

// Do not fill a password field if the field isn't readonly despite the stored
// username is a prefix without @ of username in read-only field.
TEST_F(
    PasswordAutofillAgentTest,
    DontAutocompletePasswordForNotReadonlyUsernameFieldEvenWhenPrefixMatched) {}

// If a username field is empty and readonly, don't autofill.
TEST_F(PasswordAutofillAgentTest,
       NoAutocompletePasswordForReadonlyUsernameUnmatched) {}

// Tests that having a non-matching username precludes the autocomplete.
TEST_F(PasswordAutofillAgentTest, NoAutocompleteForFilledFieldUnmatched) {}

// Don't try to complete a prefilled value that is a partial match
// to a username if the prefilled value isn't on the list of known values
// used as placeholders.
TEST_F(PasswordAutofillAgentTest, NoPartialMatchForPrefilledUsername) {}

// Tests that having a matching username precludes the autofill.
TEST_F(PasswordAutofillAgentTest, InitialAutocompleteForMatchingFilledField) {}

TEST_F(PasswordAutofillAgentTest, PasswordNotClearedOnEdit) {}

// Tests that lost focus does not trigger filling when `wait_for_username` is
// true.
TEST_F(PasswordAutofillAgentTest, WaitUsername) {}

TEST_F(PasswordAutofillAgentTest, IsWebElementVisibleTest) {}

TEST_F(PasswordAutofillAgentTest,
       SendPasswordFormsTest_VisibleFormWithNoUsername) {}

TEST_F(PasswordAutofillAgentTest, SendPasswordFormsTest_EmptyForm) {}

TEST_F(PasswordAutofillAgentTest, SendPasswordFormsTest_FormWithoutPasswords) {}

TEST_F(PasswordAutofillAgentTest,
       SendPasswordFormsTest_UndetectedPasswordField) {}

TEST_F(PasswordAutofillAgentTest, SendPasswordFormsTest_NonDisplayedForm) {}

TEST_F(PasswordAutofillAgentTest, SendPasswordFormsTest_NonVisibleForm) {}

TEST_F(PasswordAutofillAgentTest, SendPasswordFormsTest_PasswordChangeForm) {}

TEST_F(PasswordAutofillAgentTest,
       SendPasswordFormsTest_CannotCreatePasswordForm) {}

TEST_F(PasswordAutofillAgentTest, SendPasswordFormsTest_ReloadTab) {}

TEST_F(PasswordAutofillAgentTest, SendPasswordFormsTest_Redirection) {}

// Tests that fields that are not under a <form> tag are only sent to
// PasswordManager if they contain a password field.
TEST_F(PasswordAutofillAgentTest, SendPasswordFormsTest_UnownedtextInputs) {}

// Tests that a password will only be filled as a suggested and will not be
// accessible by the DOM until a user gesture has occurred.
TEST_F(PasswordAutofillAgentTest, GestureRequiredTest) {}

// Verifies that a DOM-activated UI event will not cause an autofill.
TEST_F(PasswordAutofillAgentTest, NoDOMActivationTest) {}

// Verifies that password autofill triggers events in JavaScript for forms that
// are filled on page load.
TEST_F(PasswordAutofillAgentTest,
       PasswordAutofillTriggersOnChangeEventsOnLoad) {}

// Verifies that password autofill triggers events in JavaScript for forms that
// are filled after page load.
TEST_F(PasswordAutofillAgentTest,
       PasswordAutofillTriggersOnChangeEventsWaitForUsername) {}

// Tests that `FillSuggestion` properly fills the username and password on
// focused `username_element_`.
TEST_F(PasswordAutofillAgentTest, FillSuggestionOnUsernameField) {}

// Avoid filling suggestion on username if the password field is disabled and
// there is no <form> tag.
TEST_F(PasswordAutofillAgentTest,
       NoFillSuggestionOnNoFormTagAndPasswordDisabled) {}

// Tests that `FillSuggestion` properly fills the username and password on
// focused `password_element_`.
TEST_F(PasswordAutofillAgentTest, FillSuggestionOnPasswordField) {}

// Tests that `FillSuggestion` properly fills the username and password when the
// username field is created dynamically in JavaScript.
TEST_F(PasswordAutofillAgentTest, FillSuggestionWithDynamicUsernameField) {}

// Tests that `FillSuggestion` doesn't change non-empty non-autofilled username
// when interacting with the password field.
TEST_F(PasswordAutofillAgentTest,
       FillSuggestionFromPasswordFieldWithUsernameManuallyFilled) {}

// Tests that `PreviewSuggestion` properly previews the username and password on
// `username_element_` focus.
TEST_F(PasswordAutofillAgentTest, PreviewSuggestionOnUsernameField) {}

// Tests that `PreviewSuggestion` properly previews the username and password on
// `password_element_` focus.
TEST_F(PasswordAutofillAgentTest, PreviewSuggestionOnPasswordField) {}

// Tests that `PreviewSuggestion` doesn't change non-empty non-autofilled
// username when previewing autofills on interacting with the password field.
TEST_F(PasswordAutofillAgentTest,
       PreviewSuggestionFromPasswordFieldWithUsernameManuallyFilled) {}

// Tests that `PreviewSuggestion` properly sets the username selection range.
TEST_F(PasswordAutofillAgentTest, PreviewSuggestionSelectionRange) {}

// Tests that `ClearPreview` properly clears previewed username and password
// with password being previously autofilled.
TEST_F(PasswordAutofillAgentTest, ClearPreviewWithPasswordAutofilled) {}

// Tests that `ClearPreview` properly clears previewed username and password
// with username being previously autofilled.
TEST_F(PasswordAutofillAgentTest, ClearPreviewWithUsernameAutofilled) {}

// Tests that `PreviewField` correctly previews fields.
TEST_F(PasswordAutofillAgentTest, PreviewField) {}

// Tests that the field state is correctly reset after preview.
TEST_F(PasswordAutofillAgentTest, PreviewField_ClearPreviewedForm) {}

// Tests that `ClearPreview` properly clears previewed username and password
// with username and password being previously autofilled.
TEST_F(PasswordAutofillAgentTest,
       ClearPreviewWithAutofilledUsernameAndPassword) {}

// Test that preview is cleared before the suggestion is filled.
TEST_F(PasswordAutofillAgentTest, ClearPreviewBeforeFillingSuggestion) {}

#if BUILDFLAG(IS_ANDROID)
// Tests that TryToShowKeyboardReplacingSurface() works correctly for fillable
// and non-fillable fields.
TEST_F(PasswordAutofillAgentTest, TryToShowKeyboardReplacingSurfaceUsername) {
  // Initially no fill data is available.
  WebInputElement random_element = GetInputElementByID("random_field");
  EXPECT_FALSE(password_autofill_agent_->TryToShowKeyboardReplacingSurface(
      username_element_));
  EXPECT_FALSE(password_autofill_agent_->TryToShowKeyboardReplacingSurface(
      password_element_));
  EXPECT_FALSE(password_autofill_agent_->TryToShowKeyboardReplacingSurface(
      random_element));
  EXPECT_FALSE(password_autofill_agent_->ShouldSuppressKeyboard());

  // This changes once fill data is simulated. `random_element` continue  to
  // have no fill data, though.
  fill_data_.wait_for_username = true;
  SimulateOnFillPasswordForm(fill_data_);

  EXPECT_TRUE(password_autofill_agent_->TryToShowKeyboardReplacingSurface(
      username_element_));
  EXPECT_TRUE(password_autofill_agent_->ShouldSuppressKeyboard());
  EXPECT_EQ(WebAutofillState::kNotFilled, username_element_.GetAutofillState());
  EXPECT_EQ(WebAutofillState::kNotFilled, password_element_.GetAutofillState());

  EXPECT_CALL(fake_driver_,
              ShowKeyboardReplacingSurface(
                  autofill::mojom::SubmissionReadinessState::kEmptyFields,
                  /*is_webauthn=*/false));
  base::RunLoop().RunUntilIdle();
}

TEST_F(PasswordAutofillAgentTest, TryToShowKeyboardReplacingSurfacePassword) {
  fill_data_.wait_for_username = true;
  SimulateOnFillPasswordForm(fill_data_);

  EXPECT_TRUE(password_autofill_agent_->TryToShowKeyboardReplacingSurface(
      password_element_));
  EXPECT_TRUE(password_autofill_agent_->ShouldSuppressKeyboard());
  EXPECT_EQ(WebAutofillState::kNotFilled, password_element_.GetAutofillState());

  EXPECT_CALL(fake_driver_,
              ShowKeyboardReplacingSurface(
                  autofill::mojom::SubmissionReadinessState::kEmptyFields,
                  /*is_webauthn=*/false));
  base::RunLoop().RunUntilIdle();
}

TEST_F(PasswordAutofillAgentTest,
       TryToShowKeyboardReplacingSurfaceWithWebauthnField) {
  LoadHTML(kFormWithUsernameFieldWebauthnHTML);
  UpdateUrlForHTML(kFormWithUsernameFieldWebauthnHTML);
  UpdateUsernameAndPasswordElements();
  SimulateOnFillPasswordForm(fill_data_);

  EXPECT_TRUE(password_autofill_agent_->TryToShowKeyboardReplacingSurface(
      password_element_));
  EXPECT_TRUE(password_autofill_agent_->ShouldSuppressKeyboard());

  EXPECT_CALL(fake_driver_,
              ShowKeyboardReplacingSurface(_, /*is_webauthn=*/true));
  base::RunLoop().RunUntilIdle();

  LoadHTML(kFormWithPasswordFieldWebauthnHTML);
  UpdateUrlForHTML(kFormWithPasswordFieldWebauthnHTML);
  UpdateUsernameAndPasswordElements();
  SimulateOnFillPasswordForm(fill_data_);

  EXPECT_TRUE(password_autofill_agent_->TryToShowKeyboardReplacingSurface(
      password_element_));
  EXPECT_TRUE(password_autofill_agent_->ShouldSuppressKeyboard());

  EXPECT_CALL(fake_driver_,
              ShowKeyboardReplacingSurface(_, /*is_webauthn=*/true));
  base::RunLoop().RunUntilIdle();
}

TEST_F(PasswordAutofillAgentTest,
       TryToShowKeyboardReplacingSurfaceButDontEnableSubmission) {
  LoadHTML(kPasswordChangeFormHTML);
  UpdateUrlForHTML(kPasswordChangeFormHTML);
  UpdateUsernameAndPasswordElements();
  // Enable filling for the old password field.
  fill_data_.wait_for_username = true;
  SimulateOnFillPasswordForm(fill_data_);

  EXPECT_TRUE(password_autofill_agent_->TryToShowKeyboardReplacingSurface(
      password_element_));
  EXPECT_TRUE(password_autofill_agent_->ShouldSuppressKeyboard());
  EXPECT_EQ(WebAutofillState::kNotFilled, password_element_.GetAutofillState());

  // As there are other input fields, don't enable automatic submission.
  EXPECT_CALL(
      fake_driver_,
      ShowKeyboardReplacingSurface(
          autofill::mojom::SubmissionReadinessState::kFieldAfterPasswordField,
          /*is_webauthn=*/false));
  base::RunLoop().RunUntilIdle();
}

TEST_F(PasswordAutofillAgentTest, KeyboardReplacingSurfaceSuppressesPopups) {
  SimulateOnFillPasswordForm(fill_data_);
  SimulateSuggestionChoice(username_element_);
  EXPECT_CALL(fake_driver_, ShowKeyboardReplacingSurface);
  CheckSuggestionsNotShown();
}

TEST_F(PasswordAutofillAgentTest, KeyboardReplacingSurfaceClosed) {
  fill_data_.wait_for_username = true;
  SimulateOnFillPasswordForm(fill_data_);

  // Touch to fill will be shown multiple times until
  // KeyboardReplacingSurfaceClosed() gets called.
  SimulateElementClick(password_element_);
  EXPECT_TRUE(password_autofill_agent_->ShouldSuppressKeyboard());
  EXPECT_EQ(WebAutofillState::kNotFilled, password_element_.GetAutofillState());

  EXPECT_CALL(fake_driver_, ShowKeyboardReplacingSurface);
  base::RunLoop().RunUntilIdle();

  password_autofill_agent_->KeyboardReplacingSurfaceClosed(true);
  EXPECT_FALSE(password_autofill_agent_->TryToShowKeyboardReplacingSurface(
      password_element_));
  EXPECT_FALSE(password_autofill_agent_->ShouldSuppressKeyboard());
  EXPECT_EQ(WebAutofillState::kNotFilled, password_element_.GetAutofillState());

  // Reload the page and simulate fill.
  LoadHTML(kFormHTML);
  UpdateUrlForHTML(kFormHTML);
  UpdateUsernameAndPasswordElements();
  SimulateOnFillPasswordForm(fill_data_);
  SimulateElementClick(password_element_);

  // After the reload touch to fill is shown again.
  EXPECT_TRUE(password_autofill_agent_->ShouldSuppressKeyboard());
  EXPECT_EQ(WebAutofillState::kNotFilled, password_element_.GetAutofillState());

  EXPECT_CALL(fake_driver_, ShowKeyboardReplacingSurface);
  base::RunLoop().RunUntilIdle();
}

TEST_F(PasswordAutofillAgentTest, SubmissionReadiness_NoUsernameField) {
  LoadHTML(kVisibleFormWithNoUsernameHTML);
  UpdateUrlForHTML(kVisibleFormWithNoUsernameHTML);
  UpdateOnlyPasswordElement();
  SimulateOnFillPasswordForm(fill_data_);

  EXPECT_TRUE(password_autofill_agent_->TryToShowKeyboardReplacingSurface(
      password_element_));

  EXPECT_CALL(fake_driver_,
              ShowKeyboardReplacingSurface(
                  autofill::mojom::SubmissionReadinessState::kNoUsernameField,
                  /*is_webauthn=*/false));
  base::RunLoop().RunUntilIdle();
}

TEST_F(PasswordAutofillAgentTest, SubmissionReadiness_FieldsInBetween) {
  // Parse the "random_field" as username. Then, the "username" field should
  // block a submission.
  WebDocument document = GetMainFrame()->GetDocument();
  WebElement element =
      document.GetElementById(WebString::FromUTF16(u"random_field"));
  ASSERT_TRUE(element);
  username_element_ = element.To<WebInputElement>();
  UpdateRendererIDsInFillData();

  SimulateOnFillPasswordForm(fill_data_);

  EXPECT_TRUE(password_autofill_agent_->TryToShowKeyboardReplacingSurface(
      password_element_));

  EXPECT_CALL(fake_driver_, ShowKeyboardReplacingSurface(
                                autofill::mojom::SubmissionReadinessState::
                                    kFieldBetweenUsernameAndPassword,
                                /*is_webauthn=*/false));
  base::RunLoop().RunUntilIdle();
}

TEST_F(PasswordAutofillAgentTest, SubmissionReadiness_FieldAfterPassword) {
  LoadHTML(kPasswordChangeFormHTML);
  UpdateUrlForHTML(kPasswordChangeFormHTML);
  UpdateUsernameAndPasswordElements();
  SimulateOnFillPasswordForm(fill_data_);

  EXPECT_TRUE(password_autofill_agent_->TryToShowKeyboardReplacingSurface(
      password_element_));

  EXPECT_CALL(
      fake_driver_,
      ShowKeyboardReplacingSurface(
          autofill::mojom::SubmissionReadinessState::kFieldAfterPasswordField,
          /*is_webauthn=*/false));
  base::RunLoop().RunUntilIdle();
}

TEST_F(PasswordAutofillAgentTest, SubmissionReadiness_EmptyFields) {
  SimulateOnFillPasswordForm(fill_data_);

  EXPECT_TRUE(password_autofill_agent_->TryToShowKeyboardReplacingSurface(
      password_element_));

  EXPECT_CALL(fake_driver_,
              ShowKeyboardReplacingSurface(
                  autofill::mojom::SubmissionReadinessState::kEmptyFields,
                  /*is_webauthn=*/false));
  base::RunLoop().RunUntilIdle();
}

TEST_F(PasswordAutofillAgentTest, SubmissionReadiness_MoreThanTwoFields) {
  SimulateOnFillPasswordForm(fill_data_);
  WebInputElement surname_element = GetInputElementByID("random_field");
  ASSERT_TRUE(surname_element);
  SimulateUserInputChangeForElement(&surname_element, "Smith");

  EXPECT_TRUE(password_autofill_agent_->TryToShowKeyboardReplacingSurface(
      password_element_));

  EXPECT_CALL(fake_driver_,
              ShowKeyboardReplacingSurface(
                  autofill::mojom::SubmissionReadinessState::kMoreThanTwoFields,
                  /*is_webauthn=*/false));
  base::RunLoop().RunUntilIdle();
}

TEST_F(PasswordAutofillAgentTest, SubmissionReadiness_TwoFields) {
  LoadHTML(kSimpleWebpage);
  UpdateUrlForHTML(kSimpleWebpage);
  UpdateUsernameAndPasswordElements();

  SimulateOnFillPasswordForm(fill_data_);

  EXPECT_TRUE(password_autofill_agent_->TryToShowKeyboardReplacingSurface(
      password_element_));

  EXPECT_CALL(fake_driver_,
              ShowKeyboardReplacingSurface(
                  autofill::mojom::SubmissionReadinessState::kTwoFields,
                  /*is_webauthn=*/false));
  base::RunLoop().RunUntilIdle();
}

TEST_F(PasswordAutofillAgentTest, SubmissionReadiness_NoPasswordField) {
  LoadHTML(kSingleUsernameFormHTML);
  UpdateUrlForHTML(kSingleUsernameFormHTML);
  UpdateOnlyUsernameElement();
  SimulateOnFillPasswordForm(fill_data_);

  EXPECT_TRUE(password_autofill_agent_->TryToShowKeyboardReplacingSurface(
      username_element_));

  EXPECT_CALL(fake_driver_,
              ShowKeyboardReplacingSurface(
                  autofill::mojom::SubmissionReadinessState::kNoPasswordField,
                  /*is_webauthn=*/false));
  base::RunLoop().RunUntilIdle();
}

TEST_F(PasswordAutofillAgentTest,
       DontTryToShowKeyboardReplacingSurfaceOnReadonlyForm) {
  SetElementReadOnly(username_element_, true);
  SetElementReadOnly(password_element_, true);
  SimulateOnFillPasswordForm(fill_data_);

  EXPECT_FALSE(password_autofill_agent_->TryToShowKeyboardReplacingSurface(
      username_element_));
  EXPECT_FALSE(password_autofill_agent_->TryToShowKeyboardReplacingSurface(
      password_element_));
}

class PasswordAutofillAgentTestReadonlyElementVariationTest
    : public PasswordAutofillAgentTest,
      public testing::WithParamInterface<bool> {};

TEST_P(PasswordAutofillAgentTestReadonlyElementVariationTest,
       DontTryToShowKeyboardReplacingSurfaceOnReadonlyElement) {
  bool is_password_readonly = GetParam();

  WebInputElement readonly_element =
      is_password_readonly ? password_element_ : username_element_;
  WebInputElement editable_element =
      is_password_readonly ? username_element_ : password_element_;
  SetElementReadOnly(readonly_element, true);
  SetElementReadOnly(editable_element, false);
  base::RunLoop().RunUntilIdle();

  SimulateOnFillPasswordForm(fill_data_);

  // Firstly, check that Touch-To-Fill is not shown on the readonly element.
  EXPECT_FALSE(password_autofill_agent_->TryToShowKeyboardReplacingSurface(
      readonly_element));

  // Secondly, check that Touch-To-Fill can be shown on the editable element.
  EXPECT_TRUE(password_autofill_agent_->TryToShowKeyboardReplacingSurface(
      editable_element));
}

INSTANTIATE_TEST_SUITE_P(ReadonlyElementVariation,
                         PasswordAutofillAgentTestReadonlyElementVariationTest,
                         testing::Bool());

// Credentials are sent to the renderer even for sign-up forms as these may be
// eligible for filling via manual fall back. In this case, the username_field
// and password_field are not set. This test verifies that no failures are
// recorded in PasswordManager.FirstRendererFillingResult.
TEST_F(PasswordAutofillAgentTest,
       DontTryToShowKeyboardReplacingSurfaceSignUpForm) {
  LoadHTML(kSignupFormHTML);

  WebDocument document = GetMainFrame()->GetDocument();
  WebElement element =
      document.GetElementById(WebString::FromUTF8("random_info"));
  ASSERT_TRUE(element);
  username_element_ = element.To<WebInputElement>();

  fill_data_.username_element_renderer_id = autofill::FieldRendererId();
  fill_data_.password_element_renderer_id = autofill::FieldRendererId();

  WebFormElement form_element =
      document.GetElementById("LoginTestForm").To<WebFormElement>();
  fill_data_.form_renderer_id = form_util::GetFormRendererId(form_element);

  SimulateOnFillPasswordForm(fill_data_);

  EXPECT_FALSE(password_autofill_agent_->TryToShowKeyboardReplacingSurface(
      password_element_));
}
#endif  // BUILDFLAG(IS_ANDROID)

// Tests that `FillIntoFocusedField` doesn't fill read-only text fields.
TEST_F(PasswordAutofillAgentTest, FillIntoFocusedReadonlyTextField) {}

// Tests that `FillIntoFocusedField` properly fills user-provided credentials.
TEST_F(PasswordAutofillAgentTest, FillIntoFocusedWritableTextField) {}

// Tests that `FillIntoFocusedField` doesn't fill passwords in user fields.
TEST_F(PasswordAutofillAgentTest, FillIntoFocusedFieldOnlyIntoPasswordFields) {}

// Tests that `FillIntoFocusedField` fills last focused, not last clicked field.
TEST_F(PasswordAutofillAgentTest, FillIntoFocusedFieldForNonClickFocus) {}

// Tests that `FillInfoField` doesn't fill read-only text fields.
TEST_F(PasswordAutofillAgentTest, FillIntoReadonlyTextField) {}

// Tests that `FillInfoField` correctly fills the username field.
TEST_F(PasswordAutofillAgentTest, FillIntoUsernameField) {}

// Tests that `FillInfoField` correctly fills the password field.
TEST_F(PasswordAutofillAgentTest, FillIntoPasswordField) {}

// Tests that `FillInfoField` can fill into a random field.
TEST_F(PasswordAutofillAgentTest, FillIntoRandomField) {}

// Tests that `FillInfoField` doesn't fill non-existent fields.
TEST_F(PasswordAutofillAgentTest, FillIntoNonExistingField) {}

// Tests that `ClearPreview` properly clears previewed username and password
// with neither username nor password being previously autofilled.
TEST_F(PasswordAutofillAgentTest,
       ClearPreviewWithNotAutofilledUsernameAndPassword) {}

// Tests that logging is off by default.
TEST_F(PasswordAutofillAgentTest, OnChangeLoggingState_NoMessage) {}

// Test that logging can be turned on by a message.
TEST_F(PasswordAutofillAgentTest, OnChangeLoggingState_Activated) {}

// Test that logging can be turned off by a message.
TEST_F(PasswordAutofillAgentTest, OnChangeLoggingState_Deactivated) {}

// Tests that one user click on a username field is sufficient to bring up a
// credential suggestion popup, and the user can autocomplete the password by
// selecting the credential from the popup.
TEST_F(PasswordAutofillAgentTest, ClickAndSelect) {}

// Tests that password suggestions are prefix matched against typed username.
// TODO(b:322923603): Clean up when the feature is launched.
TEST_F(PasswordAutofillAgentTest, SuggestionsPrefixMatchedByTypedUsername) {}

// Tests that all password suggestiona are shown when suggestion filtering is
// disabled.
TEST_F(PasswordAutofillAgentTest,
       SuggestionsNotPrefixMatchedWhenFeatureEnabled) {}

// Tests that the popup is suppressed when the user selects address or payments
// fallback even when the triggering field that is classified as password.
TEST_F(PasswordAutofillAgentTest,
       NoPopupOnPasswordFieldWhereAddressOrPaymentsManualFallbackWasSelected) {}

TEST_F(PasswordAutofillAgentTest,
       NoPopupOnPasswordFieldWithoutSuggestionsByDefault) {}

// With butter, passwords fields should always trigger the popup so the user can
// unlock account-stored suggestions from there.
TEST_F(PasswordAutofillAgentTest, ShowPopupOnPasswordFieldWithoutSuggestions) {}

// Before butter, passwords fields should never trigger the popup on password
// passwords fields without suggestions since it would not be helpful.
TEST_F(PasswordAutofillAgentTest, NoPopupOnPasswordFieldWithoutSuggestions) {}

// Tests the autosuggestions that are given when the element is clicked.
// Specifically, tests when the user clicks on the username element after page
// load and the element is autofilled, when the user clicks on an element that
// has a matching username.
TEST_F(PasswordAutofillAgentTest, CredentialsOnClick) {}

// Tests that there is an autosuggestion from the password manager when the
// user clicks on the password field.
TEST_F(PasswordAutofillAgentTest, NoCredentialsOnPasswordClick) {}

// The user types in a username and a password, but then just before sending
// the form off, a script clears them. This test checks that
// PasswordAutofillAgent can still remember the username and the password
// typed by the user.
TEST_F(PasswordAutofillAgentTest,
       RememberLastNonEmptyUsernameAndPasswordOnSubmit_ScriptCleared) {}

// Similar to RememberLastNonEmptyPasswordOnSubmit_ScriptCleared, but this time
// it's the user who clears the username and the password. This test checks
// that in that case, the last non-empty username and password are not
// remembered.
TEST_F(PasswordAutofillAgentTest,
       RememberLastNonEmptyUsernameAndPasswordOnSubmit_UserCleared) {}

// Similar to RememberLastNonEmptyPasswordOnSubmit_ScriptCleared, but uses the
// new password instead of the current password.
TEST_F(PasswordAutofillAgentTest,
       RememberLastNonEmptyUsernameAndPasswordOnSubmit_New) {}

// Similar to RememberLastNonEmptyUsernameAndPasswordOnSubmit_New, but uses
// no password fields on single username form
TEST_F(PasswordAutofillAgentTest, RememberLastNonEmptySingleUsername) {}

// The user first accepts a suggestion, but then overwrites the password. This
// test checks that the overwritten password is not reverted back.
TEST_F(PasswordAutofillAgentTest,
       NoopEditingDoesNotOverwriteManuallyEditedPassword) {}

// The user types the username, then accepts a suggestion. This test checks
// that autofilling does not rewrite the username, if the value is already
// there.
TEST_F(PasswordAutofillAgentTest, AcceptingSuggestionDoesntRewriteUsername) {}

// The user types in a username and a password, but then just before sending
// the form off, a script changes them. This test checks that
// PasswordAutofillAgent can still remember the username and the password
// typed by the user.
TEST_F(PasswordAutofillAgentTest,
       RememberLastTypedUsernameAndPasswordOnSubmit_ScriptChanged) {}

TEST_F(PasswordAutofillAgentTest, RememberFieldPropertiesOnSubmit) {}

TEST_F(PasswordAutofillAgentTest, FixEmptyFieldPropertiesOnSubmit) {}

TEST_F(PasswordAutofillAgentTest,
       RememberFieldPropertiesOnSameDocumentNavigation) {}

TEST_F(PasswordAutofillAgentTest,
       RememberFieldPropertiesOnSameDocumentNavigation_2) {}

// The username/password is autofilled by password manager then just before
// sending the form off, a script changes them. This test checks that
// PasswordAutofillAgent can still get the username and the password autofilled.
TEST_F(PasswordAutofillAgentTest,
       RememberLastAutofilledUsernameAndPasswordOnSubmit_ScriptChanged) {}

// The username/password is autofilled by password manager then user types in a
// username and a password. Then just before sending the form off, a script
// changes them. This test checks that PasswordAutofillAgent can still remember
// the username and the password typed by the user.
TEST_F(
    PasswordAutofillAgentTest,
    RememberLastTypedAfterAutofilledUsernameAndPasswordOnSubmit_ScriptChanged) {}

// The user starts typing username then it is autofilled.
// PasswordAutofillAgent should remember the username that was autofilled,
// not last typed.
TEST_F(PasswordAutofillAgentTest, RememberAutofilledUsername) {}

// The user starts typing username then javascript suggests to select another
// username that was generated based on typed field value (e.g. surname field).
// PasswordAutofillAgent should remember the username that was selected,
// not last typed.
TEST_F(PasswordAutofillAgentTest,
       RememberUsernameGeneratedBasingOnTypedFields) {}

// If credentials contain username+password but the form contains only a
// password field, we don't autofill on page load.
TEST_F(PasswordAutofillAgentTest, DontFillFormWithNoUsername) {}

TEST_F(PasswordAutofillAgentTest, ShowPopupOnEmptyPasswordField) {}

TEST_F(PasswordAutofillAgentTest, ShowPopupOnAutofilledPasswordField) {}

TEST_F(PasswordAutofillAgentTest, NotShowPopupPasswordField) {}

// Tests with fill-on-account-select enabled that if the username element is
// read-only and filled with an unknown username, then the password field is not
// highlighted as autofillable (regression test for https://crbug.com/442564).
TEST_F(PasswordAutofillAgentTest,
       FillOnAccountSelectOnlyReadonlyUnknownUsername) {}

// The user types in a username and a password. Then JavaScript changes password
// field to readonly state before submit. PasswordAutofillAgent can correctly
// process readonly password field. This test models behaviour of gmail.com.
TEST_F(PasswordAutofillAgentTest, ReadonlyPasswordFieldOnSubmit) {}

// Verify that typed passwords are saved correctly when autofill and generation
// both trigger. Regression test for https://crbug.com/493455
TEST_F(PasswordAutofillAgentTest, PasswordGenerationTriggered_TypedPassword) {}

// Verify that generated passwords are saved correctly when autofill and
// generation both trigger. Regression test for https://crbug.com/493455.
TEST_F(PasswordAutofillAgentTest,
       PasswordGenerationTriggered_GeneratedPassword) {}

TEST_F(PasswordAutofillAgentTest,
       ResetPasswordGenerationWhenFieldIsAutofilled) {}

// If password generation is enabled for a field, password autofill should not
// show UI.
TEST_F(PasswordAutofillAgentTest, PasswordGenerationSupersedesAutofill) {}

// Tests the following scenario: 1) user triggers manual generation, 2) user
// erases the generated password from the field, 3) password suggestions should
// be displayed when available after the field is focused again.
// Regression test for crbug/1495325.
TEST_F(PasswordAutofillAgentTest, CanShowSuggestionsAfterManualGeneration) {}

// Tests that a password change form is properly filled with the username and
// password.
TEST_F(PasswordAutofillAgentTest, FillSuggestionPasswordChangeForms) {}

// Tests that one user click on a username field is sufficient to bring up a
// credential suggestion popup on a change password form.
TEST_F(PasswordAutofillAgentTest,
       SuggestionsOnUsernameFieldOfChangePasswordForm) {}

// Tests that one user click on a password field is sufficient to bring up a
// credential suggestion popup on a change password form.
TEST_F(PasswordAutofillAgentTest,
       SuggestionsOnPasswordFieldOfChangePasswordForm) {}

// Tests that only the password field is autocompleted when the browser sends
// back data with only one credentials and empty username.
TEST_F(PasswordAutofillAgentTest, NotAutofillNoUsername) {}

// Tests that the username field is not marked as autofilled when fill data has
// the empty username.
TEST_F(PasswordAutofillAgentTest,
       AutofillNoUsernameWhenOtherCredentialsStored) {}

TEST_F(PasswordAutofillAgentTest, NoForm_PromptForAJAXSubmitWithoutNavigation) {}

TEST_F(PasswordAutofillAgentTest,
       NoForm_PromptForAJAXSubmitWithoutNavigation_2) {}

// In this test, a <div> wrapping a form is hidden via display:none after an
// Ajax request. The test verifies that we offer to save the password, as hiding
// the <div> also hiding the <form>.
TEST_F(PasswordAutofillAgentTest, PromptForAJAXSubmitAfterHidingParentElement) {}

// In this test, a <div> wrapping a form is removed from the DOM after an Ajax
// request. The test verifies that we offer to save the password, as removing
// the <div> also removes the <form>.
TEST_F(PasswordAutofillAgentTest,
       PromptForAJAXSubmitAfterDeletingParentElement) {}

TEST_F(PasswordAutofillAgentTest,
       NoForm_NoPromptForAJAXSubmitWithoutNavigationAndElementsVisible) {}

// Tests that no save prompt is shown when an unowned form is changed and AJAX
// completed but the form is still visible.
TEST_F(PasswordAutofillAgentTest,
       NoForm_NoPromptForAJAXSubmitWithoutNavigationAndNewElementAppeared) {}

TEST_F(PasswordAutofillAgentTest,
       NoForm_NoPromptForAJAXSubmitWithoutNavigationAndNewElementAppeared_2) {}

// Tests that no save prompt is shown when a form with empty action URL is
// changed and AJAX completed but the form is still visible.
TEST_F(PasswordAutofillAgentTest,
       NoAction_NoPromptForAJAXSubmitWithoutNavigationAndNewElementAppeared) {}

TEST_F(PasswordAutofillAgentTest,
       NoAction_NoPromptForAJAXSubmitWithoutNavigationAndNewElementAppeared_2) {}

TEST_F(PasswordAutofillAgentTest, DriverIsInformedAboutUnfillableField) {}

TEST_F(PasswordAutofillAgentTest, DriverIsInformedAboutFillableFields) {}

TEST_F(PasswordAutofillAgentTest, DriverIsInformedAboutFillableSearchField) {}

TEST_F(PasswordAutofillAgentTest,
       DriverInformedAboutWebAuthnIfNotPasswordOrUsername) {}

TEST_F(PasswordAutofillAgentTest, DriverIsInformedAboutFillableTextArea) {}

// Tests that credential suggestions are autofilled on a password (and change
// password) forms having either ambiguous or empty name.
TEST_F(PasswordAutofillAgentTest,
       SuggestionsOnFormContainingAmbiguousOrEmptyNames) {}

// The password manager autofills credentials, the user chooses another
// credentials option from a suggestion dropdown and then the user submits a
// form. This test verifies that the browser process receives submitted
// username/password from the renderer process.
TEST_F(PasswordAutofillAgentTest, RememberChosenUsernamePassword) {}

// Tests that we can correctly suggest to autofill two forms without username
// fields.
TEST_F(PasswordAutofillAgentTest, ShowSuggestionForNonUsernameFieldForms) {}

// Tests that password manager sees both autofill assisted and user entered
// data on saving that is triggered by AJAX succeeded.
TEST_F(PasswordAutofillAgentTest,
       UsernameChangedAfterPasswordInput_AJAXSucceeded) {}

TEST_F(PasswordAutofillAgentTest,
       UsernameChangedAfterPasswordInput_AJAXSucceeded_2) {}

// Tests that password manager sees both autofill assisted and user entered
// data on saving that is triggered by form submission.
TEST_F(PasswordAutofillAgentTest,
       UsernameChangedAfterPasswordInput_FormSubmitted) {}

// Tests that a suggestion dropdown is shown on a password field even if a
// username field is present.
TEST_F(PasswordAutofillAgentTest, SuggestPasswordFieldSignInForm) {}

// TODO(crbug.com/40819370): Amend the test to port it on Android if possible.
// Otherwise, remove the TODO and add the reason why it is excluded.
#if !BUILDFLAG(IS_ANDROID)
// Tests that a suggestion dropdown is shown on each password field. But when a
// user chose one of the fields to autofill, a suggestion dropdown will be shown
// only on this field.
TEST_F(PasswordAutofillAgentTest, SuggestMultiplePasswordFields) {}
#endif  // !BUILDFLAG(IS_ANDROID)

TEST_F(PasswordAutofillAgentTest, ShowAutofillSignaturesFlag) {}

// Checks that a same-document navigation form submission could have an empty
// username.
TEST_F(PasswordAutofillAgentTest,
       SameDocumentNavigationSubmissionUsernameIsEmpty) {}

#if BUILDFLAG(SAFE_BROWSING_DB_LOCAL)
// Verify CheckSafeBrowsingReputation() is called when user starts filling
// a password field, and that this function is only called once.
TEST_F(PasswordAutofillAgentTest,
       CheckSafeBrowsingReputationWhenUserStartsFillingUsernamePassword) {}
#endif

// Tests that username/password are autofilled when JavaScript is changing url
// between discovering a form and receiving credentials from the browser
// process.
TEST_F(PasswordAutofillAgentTest, AutocompleteWhenPageUrlIsChanged) {}

// Regression test for https://crbug.com/728028.
TEST_F(PasswordAutofillAgentTest, NoForm_MultipleAJAXEventsWithoutSubmission) {}

TEST_F(PasswordAutofillAgentTest, ManualFallbackForSaving) {}

TEST_F(PasswordAutofillAgentTest, ManualFallbackForSaving_PasswordChangeForm) {}

// Tests that information about Gaia reauthentication form is sent to the
// browser with information that the password should not be saved.
TEST_F(PasswordAutofillAgentTest, GaiaReauthenticationFormIgnored) {}

TEST_F(PasswordAutofillAgentTest,
       UpdateSuggestionsIfNewerCredentialsAreSupplied) {}

TEST_F(PasswordAutofillAgentTest, SuggestLatestCredentials) {}

// Tests that PSL matched password is not autofilled even when there is
// a prefilled username.
TEST_F(PasswordAutofillAgentTest, PSLMatchedPasswordIsNotAutofill) {}

// Tests that the password form is filled as expected on load.
TEST_F(PasswordAutofillAgentTest, FillOnLoadWith) {}

TEST_F(PasswordAutofillAgentTest, FillOnLoadNoForm) {}

TEST_F(PasswordAutofillAgentTest, FillOnLoadNoUsername) {}

TEST_F(PasswordAutofillAgentTest, MayUsePlaceholderNoPlaceholder) {}

TEST_F(PasswordAutofillAgentTest,
       MayUsePlaceholderAndPlaceholderOnFormDisabled) {}

TEST_F(PasswordAutofillAgentTest,
       MayUsePlaceholderAndPlaceholderOnFormEnabled) {}

TEST_F(PasswordAutofillAgentTest, NoMayUsePlaceholderAndPlaceholderOnForm) {}

TEST_F(PasswordAutofillAgentTest, AutofillsAfterUserGesture) {}

TEST_F(PasswordAutofillAgentTest, RestoresAfterJavaScriptModification) {}

TEST_F(PasswordAutofillAgentTest, DoNotRestoreWhenFormStructureWasChanged) {}

// Tests that a single username is filled and is exposed to JavaScript only
// after user gesture.
TEST_F(PasswordAutofillAgentTest, FillOnLoadSingleUsername) {}

// Tests that `PreviewSuggestion` properly previews the single username.
TEST_F(PasswordAutofillAgentTest, SingleUsernamePreviewSuggestion) {}

// Tests that `FillSuggestion` properly fills the single username.
TEST_F(PasswordAutofillAgentTest, SingleUsernameFillSuggestion) {}

// Tests that `ClearPreview` properly clears previewed single username. The
// original selection range should stay untouched.
TEST_F(PasswordAutofillAgentTest, SingleUsernameClearPreview) {}

// Fill on account select for credentials with empty usernames:
// Do not refill usernames if non-empty username is already selected.
TEST_F(PasswordAutofillAgentTest, NoUsernameCredential) {}

// Tests that any fields that have user input are not refilled on the next
// call of FillPasswordForm.
TEST_F(PasswordAutofillAgentTest, NoRefillOfUserInput) {}

// Tests that a JavaScript submission (e.g. via removing the form from a DOM)
// gets registered following a autofill after user trigger.
TEST_F(PasswordAutofillAgentTest, XhrSubmissionAfterFillingSuggestion) {}

// Tests that a JavaScript submission (e.g. via removing the form from a DOM)
// does not get registered following a mere autofill on page load. This is
// necessary, because we potentially fill many forms on pageload, which the user
// likely won't interact with.
TEST_F(PasswordAutofillAgentTest, NoXhrSubmissionAfterFillingOnPageload) {}

// Tests that user modifying the text field value results in notifying the
// browser.
TEST_F(PasswordAutofillAgentTest, ModifyNonPasswordField) {}

// Tests that inputting 1 symbol value into a non-password field does not notify
// the browser.
TEST_F(PasswordAutofillAgentTest, ModifyNonPasswordFieldOneSymbol) {}

// Tests that inputting 101 symbols into a non-password field does not notify
// the browser.
TEST_F(PasswordAutofillAgentTest, ModifyNonPasswordFieldTooManySymbols) {}

// Tests that user modifying a text field with an OTP autocomplete attribute
// results in notifying the browser correspondingly.
TEST_F(PasswordAutofillAgentTest, ModifyNonPasswordFieldOTPAutocomplete) {}

// Tests that user modifying a text field with a name suggesting it's an OTP
// field results in notifying the browser correspondingly.
TEST_F(PasswordAutofillAgentTest, ModifyNonPasswordFieldOTPName) {}

// Tests that user modifying the text field value does not notify the browser if
// the field has name shorter than kMinInputNameLengthForSingleUsername symbols.
TEST_F(PasswordAutofillAgentTest, ModifyNonPasswordFieldShortName) {}

// Tests that user modifying the text field value does not notify the browser if
// the field is labeled as a search field.
TEST_F(PasswordAutofillAgentTest, ModifySearchField) {}

// Tests that user inputs are propagated to the browser properly when a Shadow
// DOM tree starts between the <form> and <input> tags.
TEST_F(PasswordAutofillAgentTest,
       ProvisionalPasswordSavingWhenFormTagHostsShadowDom) {}

// Tests that passwords are filled properly on manual fallback when a Shadow
// DOM tree starts between the <form> and <input> tags.
TEST_F(PasswordAutofillAgentTest,
       PasswordSuggestionFillingWhenFormTagHostsShadowDom) {}

// Tests that password generation works when a Shadow DOM tree starts between
// the <form> and <input> tags.
TEST_F(PasswordAutofillAgentTest, PasswordGenerationWhenFormTagHostsShadowDom) {}

// Test that password manager gets notified about JS inputs in password fields.
TEST_F(PasswordAutofillAgentTest, JSFieldModificationPasswordForm) {}

// Test that password manager is not notified about JS inputs in non
// password related fields.
TEST_F(PasswordAutofillAgentTest, JSFieldModificationUnrelatedField) {}

// Tests that the metric for the number of times form fill data is stored
// for a form is recorded correctly.
TEST_F(PasswordAutofillAgentTest, TimesReceivedFillDataForFormMetric) {}

// Tests that if a password form was focused before parsing happened,
// suggestions are shown to the user once the form is parsed on Desktop,
// but not on Android.
TEST_F(PasswordAutofillAgentTest,
       ShowSuggestionsOnParsingAutofocusedPasswordForm) {}

// Tests that if a password form supporting WebAuthn was focused before parsing
// happened, suggestions are shown to the user once the form is parsed on all
// platforms.
TEST_F(PasswordAutofillAgentTest,
       ShowSuggestionsOnParsingAutofocusedWebAuthnForm) {}

// Tests that if a password form is reparsed, suggestions are not shown
// automatically.
TEST_F(PasswordAutofillAgentTest,
       DoNotShowSuggestionsOnParsingFocusedFormSecondTime) {}

// Tests that if a password form is not focused, suggestions are not shown to
// the user once the form is parsed.
TEST_F(PasswordAutofillAgentTest,
       DoNotShowSuggestionsOnParsingFormWithoutFocus) {}

TEST_F(PasswordAutofillAgentTest, InformingBrowserAboutUsernameTextFields) {}

TEST_F(PasswordAutofillAgentTest, InformingBrowserAboutIrrelevantTextFields) {}

// Tests that fields with banned fields do not show password suggestions.
TEST_F(PasswordAutofillAgentTest, NoFillingFallbackForBannedFields) {}

#if BUILDFLAG(IS_ANDROID)
// If a password field is hidden, the field unlikely has an Enter listener. So,
// trigger a form submission on the username field.
TEST_F(PasswordAutofillAgentTest, TriggerFormSubmission_HiddenPasswordField) {
  const char kUsernameFirstFormHTML[] =
      "<script>"
      "  function on_keypress(event) {"
      "    if (event.which === 13) {"
      "      var field = document.getElementById('password');"
      "      field.parentElement.removeChild(field);"
      "    }"
      "  }"
      "</script>"
      "<INPUT type='text' id='username' onkeypress='on_keypress(event)'/>"
      "<INPUT type='password' id='password' style='display:none'/>";
  LoadHTML(kUsernameFirstFormHTML);
  base::RunLoop().RunUntilIdle();
  UpdateUsernameAndPasswordElements();

  // Simulate the browser sending the login info, but set `wait_for_username`
  // to prevent the form from being immediately filled because the test
  // simulates filling with `FillSuggestion`, the function that
  // KeyboardReplacingSurface uses.
  fill_data_.wait_for_username = true;
  SimulateOnFillPasswordForm(fill_data_);

  // Fill the form.
  SimulateElementClick(username_element_);
  password_autofill_agent_->FillPasswordSuggestion(kAliceUsername16,
                                                   kAlicePassword16);
  base::RunLoop().RunUntilIdle();

  // Trigger a form submission.
  password_autofill_agent_->TriggerFormSubmission();
  base::RunLoop().RunUntilIdle();

  // Verify that the driver actually has seen a submission.
  EXPECT_TRUE(fake_driver_.called_dynamic_form_submission());
}

class PasswordAutofillAgentFormPresenceVariationTest
    : public PasswordAutofillAgentTest,
      public testing::WithParamInterface<bool> {};

TEST_P(PasswordAutofillAgentFormPresenceVariationTest, TriggerFormSubmission) {
  bool has_form_tag = GetParam();

  LoadHTML(has_form_tag ? kFormHTML : kNoFormHTML);
  base::RunLoop().RunUntilIdle();
  UpdateUsernameAndPasswordElements();

  // Simulate the browser sending the login info, but set `wait_for_username`
  // to prevent the form from being immediately filled because the test
  // simulates filling with `FillSuggestion`, the function that
  // KeyboardReplacingSurface uses.
  fill_data_.wait_for_username = true;
  SimulateOnFillPasswordForm(fill_data_);

  // Fill the form.
  SimulateElementClick(username_element_);
  password_autofill_agent_->FillPasswordSuggestion(kAliceUsername16,
                                                   kAlicePassword16);
  base::RunLoop().RunUntilIdle();

  // Trigger a form submission.
  password_autofill_agent_->TriggerFormSubmission();
  base::RunLoop().RunUntilIdle();

  // Verify that the driver actually has seen a submission.
  if (has_form_tag)
    EXPECT_TRUE(fake_driver_.called_password_form_submitted());
  else
    EXPECT_TRUE(fake_driver_.called_dynamic_form_submission());

  fake_driver_.reset_password_forms_calls();
}

INSTANTIATE_TEST_SUITE_P(FormPresenceVariation,
                         PasswordAutofillAgentFormPresenceVariationTest,
                         testing::Bool());

#endif  // BUILDFLAG(IS_ANDROID)

}  // namespace

}  // namespace autofill