chromium/chrome/browser/autofill/autofill_interactive_uitest.cc

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

#include <optional>
#include <string>
#include <string_view>
#include <tuple>
#include <utility>

#include "base/base_switches.h"
#include "base/command_line.h"
#include "base/files/file_util.h"
#include "base/functional/bind.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "base/metrics/field_trial.h"
#include "base/rand_util.h"
#include "base/run_loop.h"
#include "base/strings/strcat.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_split.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/bind.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/mock_entropy_provider.h"
#include "base/test/run_until.h"
#include "base/test/scoped_feature_list.h"
#include "base/time/time.h"
#include "build/build_config.h"
#include "build/chromeos_buildflags.h"
#include "chrome/browser/autofill/autofill_flow_test_util.h"
#include "chrome/browser/autofill/autofill_uitest.h"
#include "chrome/browser/autofill/autofill_uitest_util.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/profiles/profile_io_data.h"
#include "chrome/browser/translate/chrome_translate_client.h"
#include "chrome/browser/translate/translate_service.h"
#include "chrome/browser/translate/translate_test_utils.h"
#include "chrome/browser/ui/autofill/autofill_suggestion_controller.h"
#include "chrome/browser/ui/autofill/chrome_autofill_client.h"
#include "chrome/browser/ui/browser_tabstrip.h"
#include "chrome/browser/ui/browser_window.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "chrome/browser/ui/translate/translate_bubble_model.h"
#include "chrome/browser/ui/translate/translate_bubble_test_utils.h"
#include "chrome/common/chrome_features.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/test/base/in_process_browser_test.h"
#include "chrome/test/base/interactive_test_utils.h"
#include "chrome/test/base/test_switches.h"
#include "chrome/test/base/ui_test_utils.h"
#include "components/autofill/content/browser/content_autofill_driver.h"
#include "components/autofill/content/browser/test_autofill_manager_injector.h"
#include "components/autofill/core/browser/autofill_test_utils.h"
#include "components/autofill/core/browser/browser_autofill_manager.h"
#include "components/autofill/core/browser/browser_autofill_manager_test_api.h"
#include "components/autofill/core/browser/browser_autofill_manager_test_delegate.h"
#include "components/autofill/core/browser/data_model/autofill_profile.h"
#include "components/autofill/core/browser/mock_autofill_manager_observer.h"
#include "components/autofill/core/browser/test_autofill_manager_waiter.h"
#include "components/autofill/core/browser/validation.h"
#include "components/autofill/core/common/autofill_constants.h"
#include "components/autofill/core/common/autofill_features.h"
#include "components/autofill/core/common/autofill_util.h"
#include "components/metrics/content/subprocess_metrics_provider.h"
#include "components/network_session_configurator/common/network_switches.h"
#include "components/translate/core/browser/translate_manager.h"
#include "components/translate/core/common/translate_switches.h"
#include "content/public/browser/navigation_controller.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/render_widget_host.h"
#include "content/public/browser/render_widget_host_view.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/content_switches.h"
#include "content/public/test/browser_test.h"
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/content_mock_cert_verifier.h"
#include "content/public/test/fenced_frame_test_util.h"
#include "content/public/test/scoped_accessibility_mode_override.h"
#include "content/public/test/test_renderer_host.h"
#include "content/public/test/test_utils.h"
#include "content/public/test/url_loader_interceptor.h"
#include "net/base/net_errors.h"
#include "net/cert/mock_cert_verifier.h"
#include "net/dns/mock_host_resolver.h"
#include "net/test/embedded_test_server/controllable_http_response.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/common/features.h"
#include "third_party/blink/public/common/switches.h"
#include "third_party/re2/src/re2/re2.h"
#include "ui/events/base_event_utils.h"
#include "ui/events/keycodes/dom/keycode_converter.h"
#include "ui/events/keycodes/dom_us_layout_data.h"
#include "ui/events/keycodes/keyboard_code_conversion.h"
#include "ui/events/keycodes/keyboard_codes.h"

#if BUILDFLAG(IS_CHROMEOS_ASH) && BUILDFLAG(ENABLE_EXTENSIONS)
// Includes for ChromeVox accessibility tests.
#include "chrome/browser/ash/accessibility/accessibility_manager.h"
#include "chrome/browser/ash/accessibility/speech_monitor.h"
#include "chrome/browser/ui/aura/accessibility/automation_manager_aura.h"
#include "extensions/browser/browsertest_util.h"
#include "ui/base/test/ui_controls.h"
#endif  // BUILDFLAG(IS_CHROMEOS_ASH) && BUILDFLAG(ENABLE_EXTENSIONS)

ASCIIToUTF16;
URLLoaderInterceptor;
_;
AllOf;
AssertionFailure;
AssertionResult;
AssertionSuccess;
ElementsAre;
Eq;
Field;
Property;
StartsWith;
UnorderedElementsAreArray;

namespace autofill {

namespace {

constexpr char kTestShippingFormString[] =;

ACTION_P(InvokeClosure, closure) {}

// Version of `kTestShippingFormString` which uses <selectlist> instead of
// <select>.
std::string GenerateTestShippingFormWithSelectList() {}

// Searches all frames of the primary page in |web_contents| and returns one
// called |name|. If there are none, returns null, if there are more, returns
// an arbitrary one.
content::RenderFrameHost* RenderFrameHostForName(
    content::WebContents* web_contents,
    const std::string& name) {}

autofill::ElementExpr GetElementById(const std::string& id) {}

// Represents a field's expected or actual (as extracted from the DOM) id (not
// its name) and value.
struct FieldValue {};

std::ostream& operator<<(std::ostream& os, const FieldValue& field) {}

// Returns the field IDs and values of a collection of fields.
//
// Note that `control_elements` is *not* the ID of a form, but a JavaScript
// expression that evaluates to a collection of form-control elements, such has
// `document.getElementById('myForm').elements`.
std::vector<FieldValue> GetFieldValues(
    const ElementExpr& control_elements,
    content::ToRenderFrameHost execution_target) {}

// Types the characters of `value` after focusing field `e`.
[[nodiscard]] AssertionResult EnterTextIntoField(
    const autofill::ElementExpr& e,
    std::string_view value,
    AutofillUiTest* test,
    content::ToRenderFrameHost execution_target) {}

const std::vector<FieldValue> kEmptyAddress{};

const struct {} kDefaultAddressValues;

const std::vector<FieldValue> kDefaultAddress{};

// Returns a copy of |fields| except that the value of `update.id` is set to
// `update.value`.
[[nodiscard]] std::vector<FieldValue> MergeValue(std::vector<FieldValue> fields,
                                                 const FieldValue& update) {}

// A generic "map" function, intended to lift values `args...` to a matcher
// `fun(args)...`. For example, `ElementsAreArray(Map({x, y, z}, fun))` is
// `ElementsAreArray({fun(x), fun(y), fun(z)})`.
template <typename Arg, typename Fun>
[[nodiscard]] auto Map(const std::vector<Arg>& args, Fun fun) {}

// Matches a container of FieldValues if the `i`th actual FieldValue::value
// matches the `i`th `expected` FieldValue::value.
// As a sanity check, also requires that the `i`th actual FieldValue::id
// starts with the `i`th `expected` FieldValue::id.
[[nodiscard]] auto ValuesAre(const std::vector<FieldValue>& expected) {}

[[nodiscard]] auto FieldsAre(auto matcher) {
  return Property(&FormData::fields, ElementsAreArray(matcher));
}

// An object that waits for an observed form-control element to change its value
// to a non-empty string.
//
// See ListenForValueChange() for details.
class ValueWaiter {};

// Registers observers for a value change of a field `id`. This listener fires
// on the first time *any* object whose ID is `id` changes its value to a
// non-empty string after the global `unblock_variable` has become true.
//
// It is particularly useful for detecting refills.
//
// For example, consider the following chain JavaScript statements:
//
// 1. window.unblock = undefined // or any other value that converts to false;
// 2. document.body.innerHTML += '<input id="id">';
// 3. document.getElementById('id').value = "foo";
// 4. document.getElementById('id').remove();
// 5. document.body.innerHTML += '<input id="id">';
// 6. document.getElementById('id').value = "foo";
// 7. window.unblock = true;
// 8. document.getElementById('id').value = "";
// 9. document.getElementById('id').value = "bar";
//
// Then `ListenForValueChange("id", "unblock", rfh).Wait(base::Seconds(5)) ==
// "bar"`. The ListenForValueChange() call happens any point before Event 9, and
// Event 9 happens no later than 5 seconds after that.
[[nodiscard]] ValueWaiter ListenForValueChange(
    const std::string& id,
    const std::optional<std::string>& unblock_variable,
    content::ToRenderFrameHost execution_target) {}

}  // namespace

// Test fixtures derive from this class. This class hierarchy allows test
// fixtures to have distinct list of test parameters.
//
// TODO(crbug.com/41383133): Parametrize this class to ensure that all tests in
//                         this run with all possible valid combinations of
//                         features and field trials.
class AutofillInteractiveTestBase : public AutofillUiTest {};

const char AutofillInteractiveTestBase::kTestUrlPath[] =;

class AutofillInteractiveTest : public AutofillInteractiveTestBase {};

class AutofillInteractiveTestWithHistogramTester
    : public AutofillInteractiveTest {};

// Test the basic form-fill flow.
IN_PROC_BROWSER_TEST_F(AutofillInteractiveTest, BasicFormFill) {}

// Test that hidden selects get filled. Hidden selects are often used by widgets
// which look like <select>s but are actually constructed out of divs.
IN_PROC_BROWSER_TEST_F(AutofillInteractiveTest, FillHiddenSelect) {}

class AutofillInteractiveTest_PrefillFormAndFill
    : public AutofillInteractiveTest {};

IN_PROC_BROWSER_TEST_F(AutofillInteractiveTest, BasicUndoAutofill) {}

// TODO(crbug.com/40924835) Flaky on Mac.
#if BUILDFLAG(IS_MAC)
#define MAYBE_ModifyTextFieldAndFill
#else
#define MAYBE_ModifyTextFieldAndFill
#endif
IN_PROC_BROWSER_TEST_F(AutofillInteractiveTest,
                       MAYBE_ModifyTextFieldAndFill) {}

IN_PROC_BROWSER_TEST_F(AutofillInteractiveTest, ModifyTextNotifiesObserver) {}

// Same as ModifyTextNotifiesObserver, but for textarea rather than input
// elements.
IN_PROC_BROWSER_TEST_F(AutofillInteractiveTest,
                       ModifyTextAreaNotifiesObserver) {}

void DoModifySelectFieldAndFill(AutofillInteractiveTest* test,
                                bool should_test_selectlist) {}

// Test that autofill doesn't refill a <select> field initially modified by the
// user.
IN_PROC_BROWSER_TEST_F(AutofillInteractiveTest, ModifySelectFieldAndFill) {}

// Test that autofill doesn't refill a <selectlist> field initially modified by
// the user.
IN_PROC_BROWSER_TEST_F(AutofillInteractiveTest, ModifySelectListFieldAndFill) {}

// Test that autofill works when the website prefills the form.
IN_PROC_BROWSER_TEST_F(AutofillInteractiveTest_PrefillFormAndFill,
                       PrefillFormAndFill) {}

// Test that form filling can be initiated by pressing the down arrow.
IN_PROC_BROWSER_TEST_F(AutofillInteractiveTest, AutofillViaDownArrow) {}

IN_PROC_BROWSER_TEST_F(AutofillInteractiveTest, AutofillSelectViaTab) {}

IN_PROC_BROWSER_TEST_F(AutofillInteractiveTest, AutofillViaClick) {}

// Makes sure that the first click does or does not activate the autofill popup
// on the initial click within a fillable field.
IN_PROC_BROWSER_TEST_F(AutofillInteractiveTest, Click) {}

// Makes sure that clicking outside the focused field doesn't activate
// the popup.
IN_PROC_BROWSER_TEST_F(AutofillInteractiveTest, DontAutofillForOutsideClick) {}

// Makes sure that clicking a field while there is no enough height in the
// content area for at least one suggestion, won't show the autofill popup. This
// is a regression test for crbug.com/1108181
IN_PROC_BROWSER_TEST_F(AutofillInteractiveTest,
                       DontAutofillShowPopupWhenNoEnoughHeightInContentArea) {}

// Test that a field is still autofillable after the previously autofilled
// value is deleted.
IN_PROC_BROWSER_TEST_F(AutofillInteractiveTest, OnDeleteValueAfterAutofill) {}

// Test that an input field is not rendered with the blue autofilled
// background color when choosing an option from the datalist suggestion list.
IN_PROC_BROWSER_TEST_F(AutofillInteractiveTest, OnSelectOptionFromDatalist) {}

// Test that an <input> field with a <datalist> has a working drop down even if
// it was dynamically changed to <input type="password"> temporarily. This is a
// regression test for crbug.com/918351.
IN_PROC_BROWSER_TEST_F(
    AutofillInteractiveTest,
    OnSelectOptionFromDatalistTurningToPasswordFieldAndBack) {}

// Test that a JavaScript oninput event is fired after auto-filling a form.
IN_PROC_BROWSER_TEST_F(AutofillInteractiveTest, OnInputAfterAutofill) {}

// Test that a JavaScript onchange event is fired after auto-filling a form.
IN_PROC_BROWSER_TEST_F(AutofillInteractiveTest, OnChangeAfterAutofill) {}

IN_PROC_BROWSER_TEST_F(AutofillInteractiveTest, InputFiresBeforeChange) {}

// Test that we can autofill forms distinguished only by their |id| attribute.
IN_PROC_BROWSER_TEST_F(AutofillInteractiveTest,
                       AutofillFormsDistinguishedById) {}

// Test that we properly autofill forms with repeated fields.
// In the wild, the repeated fields are typically either email fields
// (duplicated for "confirmation"); or variants that are hot-swapped via
// JavaScript, with only one actually visible at any given time.
IN_PROC_BROWSER_TEST_F(AutofillInteractiveTest, AutofillFormWithRepeatedField) {}

// Test that we properly autofill forms with non-autofillable fields.
IN_PROC_BROWSER_TEST_F(AutofillInteractiveTest,
                       AutofillFormWithAutocompleteOffField) {}

// Test that we can Autofill dynamically generated forms.
IN_PROC_BROWSER_TEST_F(AutofillInteractiveTest, DynamicFormFill) {}

// Test that form filling works after reloading the current page.
IN_PROC_BROWSER_TEST_F(AutofillInteractiveTest, AutofillAfterReload) {}

// Test that filling a form sends all the expected events to the different
// fields being filled.
IN_PROC_BROWSER_TEST_F(AutofillInteractiveTest, AutofillEvents) {}

IN_PROC_BROWSER_TEST_F(AutofillInteractiveTest, AutofillAfterTranslate) {}

// Test phone fields parse correctly from a given profile.
// The high level key presses execute the following: Select the first text
// field, invoke the autofill popup list, select the first profile within the
// list, and commit to the profile to populate the form.
IN_PROC_BROWSER_TEST_F(AutofillInteractiveTest, ComparePhoneNumbers) {}

// Test that Autofill does not fill in Company Name if disabled
IN_PROC_BROWSER_TEST_F(AutofillInteractiveTest, NoAutofillForCompanyName) {}

// TODO(crbug.com/40810623): Check back if flakiness is fixed now.
IN_PROC_BROWSER_TEST_F(AutofillInteractiveTest,
                       NoAutofillSuggestionForCompanyName) {}

// Test that Autofill does not fill in read-only fields.
IN_PROC_BROWSER_TEST_F(AutofillInteractiveTest, NoAutofillForReadOnlyFields) {}

// Test form is fillable from a profile after form was reset.
// Steps:
//   1. Fill form using a saved profile.
//   2. Reset the form.
//   3. Fill form using a saved profile.
IN_PROC_BROWSER_TEST_F(AutofillInteractiveTest, FormFillableOnReset) {}

// Test Autofill distinguishes a middle initial in a name.
IN_PROC_BROWSER_TEST_F(AutofillInteractiveTest,
                       DistinguishMiddleInitialWithinName) {}

// Test forms with multiple email addresses are filled properly.
// Entire form should be filled with one user gesture.
IN_PROC_BROWSER_TEST_F(AutofillInteractiveTest,
                       MultipleEmailFilledByOneUserGesture) {}

// Test latency time on form submit with lots of stored Autofill profiles.
// This test verifies when a profile is selected from the Autofill dictionary
// that consists of thousands of profiles, the form does not hang after being
// submitted.
// Flakily times out creating 1500 profiles: http://crbug.com/281527
IN_PROC_BROWSER_TEST_F(AutofillInteractiveTest,
                       DISABLED_FormFillLatencyAfterSubmit) {}

// Test that Chrome doesn't crash when autocomplete is disabled while the user
// is interacting with the form.  This is a regression test for
// http://crbug.com/160476
IN_PROC_BROWSER_TEST_F(AutofillInteractiveTest,
                       DisableAutocompleteWhileFilling) {}

// Test that a page with 2 forms with no name and id containing fields with no
// name or if get filled properly.
IN_PROC_BROWSER_TEST_F(AutofillInteractiveTest,
                       FillFormAndFieldWithNoNameOrId) {}

// The following four tests verify that we can autofill forms with multiple
// nameless forms, and repetitive field names and make sure that the dynamic
// refill would not trigger a wrong refill, regardless of the form.
IN_PROC_BROWSER_TEST_F(AutofillInteractiveTest,
                       Dynamic_MultipleNoNameForms_BadNames_FourthForm) {}

IN_PROC_BROWSER_TEST_F(AutofillInteractiveTest,
                       Dynamic_MultipleNoNameForms_BadNames_ThirdForm) {}

IN_PROC_BROWSER_TEST_F(AutofillInteractiveTest,
                       Dynamic_MultipleNoNameForms_BadNames_SecondForm) {}

IN_PROC_BROWSER_TEST_F(AutofillInteractiveTest,
                       Dynamic_MultipleNoNameForms_BadNames_FirstForm) {}

// Test that we can Autofill forms where some fields name change during the
// fill.
IN_PROC_BROWSER_TEST_F(AutofillInteractiveTest, FieldsChangeName) {}

// Test that credit card autofill works.
IN_PROC_BROWSER_TEST_F(AutofillInteractiveTestBase, FillLocalCreditCard) {}

// Test that we do not fill formless non-checkout forms when we enable the
// formless form restrictions.
IN_PROC_BROWSER_TEST_F(AutofillInteractiveTestBase, NoAutocomplete) {}

// Test that we do not fill formless non-checkout forms when we enable the
// formless form restrictions. This test differs from the NoAutocomplete
// version of the the test in that at least one of the fields has an
// autocomplete attribute, so autofill will always be aware of the existence
// of the form.
IN_PROC_BROWSER_TEST_F(AutofillInteractiveTestBase, SomeAutocomplete) {}

// Test that we do not fill formless non-checkout forms when we enable the
// formless form restrictions.
IN_PROC_BROWSER_TEST_F(AutofillInteractiveTestBase, AllAutocomplete) {}

// Test that an 'onchange' event is not fired when a <selectlist> preview
// suggestion is shown or hidden.
IN_PROC_BROWSER_TEST_F(AutofillInteractiveTest,
                       NoEventFiredWhenExitingSelectListPreview) {}

// An extension of the test fixture for tests with site isolation.
class AutofillInteractiveIsolationTest : public AutofillInteractiveTestBase {};

enum class FrameType {};

class AutofillInteractiveFencedFrameTest
    : public AutofillInteractiveIsolationTest,
      public ::testing::WithParamInterface<FrameType> {};

INSTANTIATE_TEST_SUITE_P();

IN_PROC_BROWSER_TEST_P(AutofillInteractiveFencedFrameTest,
                       SimpleCrossSiteFill) {}

// This test verifies that credit card (payment card list) popup works when the
// form is inside an OOPIF/Fenced Frame.
IN_PROC_BROWSER_TEST_P(AutofillInteractiveFencedFrameTest,
                       CrossSitePaymentForms) {}

// Tests that deleting the subframe that has opened the Autofill popup closes
// the popup.
IN_PROC_BROWSER_TEST_P(AutofillInteractiveFencedFrameTest,
                       DeletingFrameClosesPopup) {}

// Tests that when changing the tab while the popup is open, closes the popup.
IN_PROC_BROWSER_TEST_F(AutofillInteractiveTest, ChangingTabClosesPopup) {}

// Test fixture for refill behavior.
//
// BrowserAutofillManager only executes a refill if it happens within the time
// delta `kLimitBeforeRefill` of the original refill. On slow bots, this timeout
// may cause flakiness. Therefore, this fixture increases the limit before
// refill to an unreasonably large time.
class AutofillInteractiveTestDynamicForm : public AutofillInteractiveTest {};

// Test that we can Autofill dynamically generated forms.
IN_PROC_BROWSER_TEST_F(AutofillInteractiveTestDynamicForm,
                       DynamicChangingFormFill) {}

IN_PROC_BROWSER_TEST_F(AutofillInteractiveTestDynamicForm,
                       TwoDynamicChangingFormsFill) {}

// Test that forms that dynamically change a second time do not get filled.
IN_PROC_BROWSER_TEST_F(AutofillInteractiveTestDynamicForm,
                       DynamicChangingFormFill_SecondChange) {}

// Test that forms that dynamically change after the refill limit do not get
// filled.
IN_PROC_BROWSER_TEST_F(AutofillInteractiveTestDynamicForm,
                       DynamicChangingFormFill_AfterDelay) {}

// Test that only field of a type group that was filled initially get refilled.
IN_PROC_BROWSER_TEST_F(AutofillInteractiveTestDynamicForm,
                       DynamicChangingFormFill_AddsNewFieldTypeGroups) {}

// Test that we can autofill forms that dynamically change select fields to text
// fields by changing the visibilities.
IN_PROC_BROWSER_TEST_F(AutofillInteractiveTestDynamicForm,
                       DynamicFormFill_SelectToText) {}

// Test that we can autofill forms that dynamically change the visibility of a
// field after it's autofilled.
IN_PROC_BROWSER_TEST_F(AutofillInteractiveTestDynamicForm,
                       DynamicFormFill_VisibilitySwitch) {}

// Test that we can autofill forms that dynamically change the element that
// has been clicked on.
IN_PROC_BROWSER_TEST_F(AutofillInteractiveTestDynamicForm,
                       DynamicFormFill_FirstElementDisappears) {}

// Test that we can autofill forms that dynamically change the element that
// has been clicked on, even though the form has no name.
IN_PROC_BROWSER_TEST_F(AutofillInteractiveTestDynamicForm,
                       DynamicFormFill_FirstElementDisappearsNoNameForm) {}

// Test that we can autofill forms that dynamically change the element that
// has been clicked on, even though there are multiple forms with identical
// names.
IN_PROC_BROWSER_TEST_F(
    AutofillInteractiveTestDynamicForm,
    DynamicFormFill_FirstElementDisappearsMultipleBadNameForms) {}

// Test that we can autofill forms that dynamically change the element that
// has been clicked on, even though there are multiple forms with identical
// names.
IN_PROC_BROWSER_TEST_F(AutofillInteractiveTestDynamicForm,
                       DynamicFormFill_FirstElementDisappearsBadnameUnowned) {}

// Test that we can autofill forms that dynamically change the element that
// has been clicked on, even though there are multiple forms with no name.
IN_PROC_BROWSER_TEST_F(
    AutofillInteractiveTestDynamicForm,
    DynamicFormFill_FirstElementDisappearsMultipleNoNameForms) {}

// Test that we can autofill forms that dynamically change the element that
// has been clicked on, even though the elements are unowned.
IN_PROC_BROWSER_TEST_F(AutofillInteractiveTestDynamicForm,
                       DynamicFormFill_FirstElementDisappearsUnowned) {}

// Test that credit card fields are re-filled.
IN_PROC_BROWSER_TEST_F(AutofillInteractiveTestDynamicForm,
                       DynamicChangingFormFill_AlsoForCreditCard) {}

void DoDynamicChangingFormFill_SelectUpdated(
    AutofillInteractiveTestDynamicForm* test,
    net::EmbeddedTestServer* test_server,
    bool should_test_selectlist,
    bool should_test_async_update) {}

// Test that we can Autofill dynamically changing selects that have options
// added and removed.
IN_PROC_BROWSER_TEST_F(AutofillInteractiveTestDynamicForm,
                       DynamicChangingFormFill_SelectUpdated) {}

// Test that we can Autofill dynamically changing selectlists that have options
// added and removed.
IN_PROC_BROWSER_TEST_F(AutofillInteractiveTestDynamicForm,
                       DynamicChangingFormFill_SelectListUpdated) {}

// Test that we can Autofill dynamically changing selects that have options
// added and removed, when the updating occurs asynchronously.
IN_PROC_BROWSER_TEST_F(AutofillInteractiveTestDynamicForm,
                       DynamicChangingFormFill_SelectUpdatedAsync) {}

// Test that we can Autofill dynamically changing selectlists that have options
// added and removed, when the updating occurs asynchronously.
IN_PROC_BROWSER_TEST_F(AutofillInteractiveTestDynamicForm,
                       DynamicChangingFormFill_SelectListUpdatedAsync) {}

// Test that we can Autofill dynamically changing selects that have options
// added and removed only once.
IN_PROC_BROWSER_TEST_F(AutofillInteractiveTestDynamicForm,
                       DynamicChangingFormFill_DoubleSelectUpdated) {}

// Test that we can Autofill dynamically generated forms with no name if the
// NameForAutofill of the first field matches.
IN_PROC_BROWSER_TEST_F(AutofillInteractiveTestDynamicForm,
                       DynamicChangingFormFill_FormWithoutName) {}

// Test that we can Autofill dynamically changing selects that have options
// added and removed for forms with no names if the NameForAutofill of the first
// field matches.
IN_PROC_BROWSER_TEST_F(AutofillInteractiveTestDynamicForm,
                       DynamicChangingFormFill_SelectUpdated_FormWithoutName) {}

// Test that we can Autofill dynamically generated synthetic forms if the
// NameForAutofill of the first field matches.
IN_PROC_BROWSER_TEST_F(AutofillInteractiveTestDynamicForm,
                       DynamicChangingFormFill_SyntheticForm) {}

// Test that we can Autofill dynamically synthetic forms when the select options
// change if the NameForAutofill of the first field matches
IN_PROC_BROWSER_TEST_F(AutofillInteractiveTestDynamicForm,
                       DynamicChangingFormFill_SelectUpdated_SyntheticForm) {}

// Some websites have JavaScript handlers that mess with the input of the user
// and autofill. A common problem is that the date "09/2999" gets reformatted
// into "09 / 20" instead of "09 / 99".
// In these tests, the following steps will happen:
// 1) Autofill recognizes an expiration date field with maxlength=7, will infer
//    that it is supposed to fill 09/2999 and will fill that value.
// 2) The website sees the content 09/2999 and reformats it to 09 / 29 because
//    this is what websites do sometimes.
// 3) The AutofillAgent recognizes that it failed to fill 09/2999 and fills
//    09 / 99 instead.
// 4) The promise waits to see 09 / 99 and resolved.
// Flaky on Linux MSAN https://crbug.com/362299091.
IN_PROC_BROWSER_TEST_F(AutofillInteractiveTestDynamicForm,
                       FillCardOnReformattingForm) {}

// Shadow DOM tests consist of two cases:
// - Case 0: the <form> is in the main DOM;
// - Case 1: the <form> is in a shadow DOM.
class AutofillInteractiveTestShadowDom
    : public AutofillInteractiveTest,
      public ::testing::WithParamInterface<size_t> {};

INSTANTIATE_TEST_SUITE_P();

// Tests that in a shadow-DOM-transcending form, Autofill detects labels
// *outside* of the field's shadow DOM.
IN_PROC_BROWSER_TEST_P(AutofillInteractiveTestShadowDom,
                       LabelInHostingDomOfField) {}

// Tests that in a shadow-DOM-transcending form, Autofill detects labels
// *inside* of the field's shadow DOM.
IN_PROC_BROWSER_TEST_P(AutofillInteractiveTestShadowDom,
                       LabelInSameShadowDomAsField) {}

// ChromeVox is only available on ChromeOS.
#if BUILDFLAG(IS_CHROMEOS_ASH) && BUILDFLAG(ENABLE_EXTENSIONS)

class AutofillInteractiveTestChromeVox : public AutofillInteractiveTestBase {
 public:
  AutofillInteractiveTestChromeVox() = default;
  ~AutofillInteractiveTestChromeVox() override = default;

  void TearDownOnMainThread() override {
    // Unload the ChromeVox extension so the browser doesn't try to respond to
    // in-flight requests during test shutdown. https://crbug.com/923090
    ash::AccessibilityManager::Get()->EnableSpokenFeedback(false);
    AutomationManagerAura::GetInstance()->Disable();
    AutofillInteractiveTestBase::TearDownOnMainThread();
  }

  void EnableChromeVox() {
    // Test setup.
    // Enable ChromeVox, disable earcons and wait for key mappings to be
    // fetched.
    ASSERT_FALSE(ash::AccessibilityManager::Get()->IsSpokenFeedbackEnabled());
    // TODO(accessibility): fix console error/warnings and instantiate
    // |console_observer_| here.

    // Load ChromeVox and block until it's fully loaded.
    ash::AccessibilityManager::Get()->EnableSpokenFeedback(true);
    sm_.ExpectSpeechPattern("*");
    sm_.Call([this]() { DisableEarcons(); });
  }

  void DisableEarcons() {
    // Playing earcons from within a test is not only annoying if you're
    // running the test locally, but seems to cause crashes
    // (http://crbug.com/396507). Work around this by just telling
    // ChromeVox to not ever play earcons (prerecorded sound effects).
    extensions::browsertest_util::ExecuteScriptInBackgroundPageNoWait(
        browser()->profile(), extension_misc::kChromeVoxExtensionId,
        "ChromeVox.earcons.playEarcon = function() {};");
  }

  ash::test::SpeechMonitor sm_;
};

// Ensure that autofill suggestions are properly read out via ChromeVox.
// This is a regressions test for crbug.com/1208913.
// TODO(crbug.com/40820453): Flaky on ChromeOS
#if BUILDFLAG(IS_CHROMEOS)
#define MAYBE_TestNotificationOfAutofillDropdown
#else
#define MAYBE_TestNotificationOfAutofillDropdown
#endif
IN_PROC_BROWSER_TEST_F(AutofillInteractiveTestChromeVox,
                       MAYBE_TestNotificationOfAutofillDropdown) {
  CreateTestProfile();
  SetTestUrlResponse(kTestShippingFormString);
  ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), GetTestUrl()));

  EnableChromeVox();
  content::ScopedAccessibilityModeOverride scoped_accessibility_mode(
      web_contents(), ui::kAXModeComplete);

  // The following contains a sequence of calls to
  // sm_.ExpectSpeechPattern() and test_delegate()->Wait(). It is essential
  // to first flush the expected speech patterns, otherwise the two functions
  // start incompatible RunLoops.
  sm_.ExpectSpeechPattern("Web Content");
  sm_.Call([this]() {
    content::WaitForAccessibilityTreeToContainNodeWithName(web_contents(),
                                                           "First name:");
    web_contents()->Focus();
    test_delegate()->SetExpectations({ObservedUiEvents::kSuggestionsShown});
    ASSERT_TRUE(FocusField(GetElementById("firstname"), GetWebContents()));
  });
  sm_.ExpectSpeechPattern("First name:");
  sm_.ExpectSpeechPattern("Edit text");
  sm_.ExpectSpeechPattern("Region");
  // Wait for suggestions popup to show up. This needs to happen before we
  // simulate the cursor down key press.
  sm_.Call([this]() { ASSERT_TRUE(test_delegate()->Wait()); });
  sm_.Call([this]() {
    test_delegate()->SetExpectations({ObservedUiEvents::kPreviewFormData});
    ASSERT_TRUE(
        ui_controls::SendKeyPress(browser()->window()->GetNativeWindow(),
                                  ui::VKEY_DOWN, false, false, false, false));
  });
  sm_.ExpectSpeechPattern("Autofill menu opened");
  sm_.ExpectSpeechPattern("Milton 4120 Freidrich Lane");
  sm_.ExpectSpeechPattern("List item");
  sm_.ExpectSpeechPattern("1 of 2");
  sm_.Call([this]() { ASSERT_TRUE(test_delegate()->Wait()); });
  sm_.Replay();
}

#endif  // BUILDFLAG(IS_CHROMEOS_ASH) && BUILDFLAG(ENABLE_EXTENSIONS)

// These tests are disabled on LaCros because <select> elements don't listen
// to typed characters the same way as other platforms. Sending the characters
// 'W', 'A' while the state selector is focused does not trigger a selection
// of the entry "WA".
#if BUILDFLAG(IS_CHROMEOS_LACROS)
#define MAYBE_AutofillInteractiveFormSubmissionTest
#else
#define MAYBE_AutofillInteractiveFormSubmissionTest
#endif
class MAYBE_AutofillInteractiveFormSubmissionTest
    : public AutofillInteractiveTestBase {};

// Tests that user-triggered submission triggers a submission event in
// BrowserAutofillManager.
IN_PROC_BROWSER_TEST_F(MAYBE_AutofillInteractiveFormSubmissionTest,
                       Submission) {}

// Tests that non-link-click, renderer-initiated navigation triggers a
// submission event in BrowserAutofillManager.
IN_PROC_BROWSER_TEST_F(MAYBE_AutofillInteractiveFormSubmissionTest,
                       ProbableSubmission) {}

// Tests that a same document navigation can trigger a form submission.
IN_PROC_BROWSER_TEST_F(MAYBE_AutofillInteractiveFormSubmissionTest,
                       SameDocumentNavigation) {}

// Tests that an XHR request can indicate a form submission.
IN_PROC_BROWSER_TEST_F(MAYBE_AutofillInteractiveFormSubmissionTest,
                       XhrSucceededAndHideForm) {}

// Tests that an XHR request can indicate a form submission - even if the form
// is deleted from the DOM.
IN_PROC_BROWSER_TEST_F(MAYBE_AutofillInteractiveFormSubmissionTest,
                       XhrSucceededAndDeleteForm) {}

// Tests that a DOM mutation after an XHR can indicate a form submission.
IN_PROC_BROWSER_TEST_F(MAYBE_AutofillInteractiveFormSubmissionTest,
                       DomMutationAfterXhr) {}

// Tests that FormFieldData::user_input has the text that the user typed into
// the field. This is needed in order to show the save-card dialog when the
// page replaces the <input> value with '***'.
IN_PROC_BROWSER_TEST_F(MAYBE_AutofillInteractiveFormSubmissionTest,
                       RememberUserInput) {}

// Tests scenario where in sequence:
// 1) The user types into a form
// 2) The form is cleared via JavaScript
// 3) The user autofills the form
// 4) The user submits the form
// That FormFieldData::user_input is empty and does not contain stale data that
// the user typed into the form.
IN_PROC_BROWSER_TEST_F(MAYBE_AutofillInteractiveFormSubmissionTest,
                       TreatAutofillAsUserInput) {}

#if BUILDFLAG(IS_CHROMEOS_LACROS)
#define MAYBE_AutofillInteractiveFormlessFormSubmissionTest
#else
#define MAYBE_AutofillInteractiveFormlessFormSubmissionTest
#endif
class MAYBE_AutofillInteractiveFormlessFormSubmissionTest
    : public MAYBE_AutofillInteractiveFormSubmissionTest {};

// Tests that a submission is detected when the following steps are done in
// sequence:
// 1) User fills <input>s on page without <form>.
// 2) The page does an XHR
// 3) The page navigates
IN_PROC_BROWSER_TEST_F(MAYBE_AutofillInteractiveFormlessFormSubmissionTest,
                       NavigationAfterXhr) {}

}  // namespace autofill