chromium/components/autofill/content/renderer/form_autofill_util_browsertest.cc

// Copyright 2017 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/form_autofill_util.h"

#include "base/feature_list.h"
#include "base/metrics/field_trial.h"
#include "base/strings/strcat.h"
#include "base/strings/string_number_conversions.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/scoped_feature_list.h"
#include "components/autofill/content/renderer/test_utils.h"
#include "components/autofill/core/common/autofill_constants.h"
#include "components/autofill/core/common/autofill_data_validation.h"
#include "components/autofill/core/common/autofill_features.h"
#include "components/autofill/core/common/field_data_manager.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-shared.h"
#include "components/autofill/core/common/unique_ids.h"
#include "content/public/renderer/render_frame.h"
#include "content/public/test/render_view_test.h"
#include "content/public/test/test_utils.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.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_element.h"
#include "third_party/blink/public/web/web_element_collection.h"
#include "third_party/blink/public/web/web_form_control_element.h"
#include "third_party/blink/public/web/web_form_element.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_remote_frame.h"
#include "third_party/blink/public/web/web_select_element.h"
#include "third_party/blink/public/web/web_view.h"

namespace autofill::form_util {
namespace {

ButtonTitleType;
WebDocument;
WebElement;
WebElementCollection;
WebFormControlElement;
WebFormElement;
WebInputElement;
WebLocalFrame;
WebNode;
WebString;
WebVector;
_;
AllOf;
ElementsAre;
Field;
IsEmpty;
IsFalse;
IsTrue;
Optional;
Pair;
Pointwise;
Property;
Values;

struct AutofillFieldUtilCase {};

// An <input> with a label placed on top of it (usually used as a placeholder
// replacement).
const char* kPoorMansPlaceholderFullOverlap =;

// The <input> element partially overlaps the label (placeholder) but the label
// is not fully contained in the <input> element. This is a common case for
// placeholders that moph into a minified version when the user focuses an
// <input> element.
const char* kPoorMansPlaceholderPartialOverlap =;

// The <input> element touches the next element vertically but does not overlap.
// The label should not be considered a placeholder.
const char* kPoorMansPlaceholderNoOverlap =;

// The <input> element touches the next element horizontally but does not
// overlap. The label should not be considered a placeholder.
const char* kPoorMansPlaceholderNoOverlap2 =;

// The span exceeds the vertical limits of the input element, which is a
// pattern often observed in error messages. Therefore we don't consider the
// span a label.
const char* kPoorMansPlaceholderPossiblyErrorMessage =;

// The span is not horizontally contained in the input element. We don't
// consider this a label because have seen several cases where the actual
// label was on the left of the input field in a <table> structure and the
// text on the right, which just touched the element contained non-label
// data (e.g. instructions like "don't enter symbols").
const char* kPoorMansPlaceholderNoHorizontalContainment =;

void VerifyButtonTitleCache(const WebFormElement& form_target,
                            const ButtonTitleList& expected_button_titles,
                            const ButtonTitlesCache& actual_cache) {}

bool HaveSameFormControlId(const WebFormControlElement& element,
                           const FormFieldData& field) {}

class FormAutofillUtilsTest : public content::RenderViewTest {};

// Tests that WebFormElementToFormData() sets the
// Form[Field]Data::{name,id_attribute,name_attribute} correctly.
TEST_F(FormAutofillUtilsTest, WebFormElementToFormData_IdAndNames) {}

// Tests that form extraction measures its total time, also split by caller.
TEST_F(FormAutofillUtilsTest, ExtractFormDataMeasuresTotalTime) {}

// Tests that form extraction measures how long label extraction took.
TEST_F(FormAutofillUtilsTest,
       ExtractFormDataMeasuresDurationOfLabelExtraction) {}

// Tests that large option values/contents are truncated while building the
// FormData.
TEST_F(FormAutofillUtilsTest, TruncateLargeOptionValuesAndContents) {}

// Tests that the SelectOption::value and SelectOption::text are extracted
// correctly.
TEST_F(FormAutofillUtilsTest, ExtractFormData_SelectOptionValueAndText) {}

TEST_F(FormAutofillUtilsTest, FindChildTextTest) {}

TEST_F(FormAutofillUtilsTest, FindChildTextSkipElementTest) {}

TEST_F(FormAutofillUtilsTest, InferLabelForElementTest) {}

TEST_F(FormAutofillUtilsTest, InferLabelSourceTest) {}

TEST_F(FormAutofillUtilsTest, GetButtonTitles) {}

TEST_F(FormAutofillUtilsTest, GetButtonTitles_TooLongTitle) {}

TEST_F(FormAutofillUtilsTest, GetButtonTitles_NoCache) {}

TEST_F(FormAutofillUtilsTest, GetButtonTitles_NoForm) {}

TEST_F(FormAutofillUtilsTest, IsEnabled) {}

TEST_F(FormAutofillUtilsTest, IsReadonly) {}

TEST_F(FormAutofillUtilsTest, IsFocusable) {}

TEST_F(FormAutofillUtilsTest, FindFormByUniqueId) {}

// Used in ParameterizedGetFormControlByRendererIdTest.
struct FindFormControlTestParam {};

// Tests GetFormControlByRendererId().
class ParameterizedGetFormControlByRendererIdTest
    : public FormAutofillUtilsTest,
      public testing::WithParamInterface<FindFormControlTestParam> {};

TEST_P(ParameterizedGetFormControlByRendererIdTest,
       GetFormControlByRendererId) {}

INSTANTIATE_TEST_SUITE_P();

// Tests the extraction of the aria-label attribute.
TEST_F(FormAutofillUtilsTest, GetAriaLabel) {}

// Tests that aria-labelledby works. Simple case: only one id referenced.
TEST_F(FormAutofillUtilsTest, GetAriaLabelledBySingle) {}

// Tests that aria-labelledby works: Complex case: multiple ids referenced.
TEST_F(FormAutofillUtilsTest, GetAriaLabelledByMulti) {}

// Tests that aria-labelledby takes precedence over aria-label
TEST_F(FormAutofillUtilsTest, GetAriaLabelledByTakesPrecedence) {}

// Tests that an invalid aria-labelledby reference gets ignored (as opposed to
// crashing, for example).
TEST_F(FormAutofillUtilsTest, GetAriaLabelledByInvalid) {}

// Tests that invalid aria-labelledby references fall back to aria-label.
TEST_F(FormAutofillUtilsTest, GetAriaLabelledByFallback) {}

// Tests that aria-describedby works: Simple case: a single id referenced.
TEST_F(FormAutofillUtilsTest, GetAriaDescribedBySingle) {}

// Tests that aria-describedby works: Complex case: multiple ids referenced.
TEST_F(FormAutofillUtilsTest, GetAriaDescribedByMulti) {}

// Tests that invalid aria-describedby returns the empty string.
TEST_F(FormAutofillUtilsTest, GetAriaDescribedByInvalid) {}

// Tests IsOwnedByFrame().
TEST_F(FormAutofillUtilsTest, IsOwnedByFrame) {}

TEST_F(FormAutofillUtilsTest, ExtractFormData_IsActionEmptyFalse) {}

TEST_F(FormAutofillUtilsTest, ExtractFormData_IsActionEmptyTrue) {}

TEST_F(FormAutofillUtilsTest,
       FindFormAndFieldForFormControlElement_ExtractBounds) {}

TEST_F(FormAutofillUtilsTest,
       FindFormAndFieldForFormControlElement_NotExtractBounds) {}

TEST_F(FormAutofillUtilsTest,
       FindFormAndFieldForFormControlElement_ExtractUnownedBounds) {}

TEST_F(FormAutofillUtilsTest,
       FindFormAndFieldForFormControlElement_GetDataListSuggestions) {}

TEST_F(FormAutofillUtilsTest,
       FindFormAndFieldForFormControlElement_GetDataListSuggestionsWithLabels) {}

TEST_F(FormAutofillUtilsTest,
       FindFormAndFieldForFormControlElement_ExtractDataList) {}

TEST_F(FormAutofillUtilsTest,
       FindFormAndFieldForFormControlElement_NotExtractDataList) {}

TEST_F(FormAutofillUtilsTest,
       FindFormAndFieldForFormControlElement_Disconnected) {}

// Tests the visibility detection of iframes.
// This test checks many scenarios. It's intentionally not a parameterized test
// for performance reasons.
// This test is very similar to the IsWebElementVisibleTest test.
TEST_F(FormAutofillUtilsTest, IsVisibleIframeTest) {}

// Tests the visibility detection of fields.
// This test checks many scenarios. It's intentionally not a parameterized test
// for performance reasons.
// This test is very similar to the IsVisibleIframeTest test.
TEST_F(FormAutofillUtilsTest, IsWebElementVisibleTest) {}

// Tests `GetClosestAncestorFormElement(element)`.
TEST_F(FormAutofillUtilsTest, GetClosestAncestorFormElement) {}

// Tests that `IsDOMPredecessor(lhs, rhs, ancestor_hint)` holds iff a DOM
// traversal visits the DOM element with ID `lhs` before the one with ID `rhs`,
// where `ancestor_hint` is the ID of an ancestor DOM node.
//
// For this test, DOM element IDs should be named so that if X as visited
// before Y, then X.id is lexicographically less than Y.id.
TEST_F(FormAutofillUtilsTest, IsDomPredecessorTest) {}

// The DOM ID of an <input> or <iframe>.
struct FieldOrFrame {};

// A FieldFramesTest test case contains HTML code. The form with DOM ID
// |form_id| (nullptr for the synthetic form) shall be extracted and its fields
// and frames shall match |fields_and_frames|.
struct FieldFramesTestParam {};

class FieldFramesTest
    : public FormAutofillUtilsTest,
      public testing::WithParamInterface<FieldFramesTestParam> {};

// Check if the unowned form control elements are properly extracted.
// Form control elements are button, fieldset, input, textarea, output and
// select elements.
TEST_F(FormAutofillUtilsTest, GetFormFieldElements_Unowned) {}

// Tests that FormData::fields and FormData::child_frames are extracted fully
// and in the correct relative order.
TEST_P(FieldFramesTest, ExtractFormData_ExtractFieldsAndFrames) {}

// Creates 32 test cases containing forms which differ in five bits: whether or
// not the form of interest is a synthetic form, and whether the first, second,
// third, and fourth element are a form control field or an iframe. This form is
// additionally surrounded by two other forms before and after itself. An
// example:
//   <body>
//     <!-- Two forms not of interest follow -->
//     <form><input><iframe></iframe></form>
//     <input><iframe></iframe>
//     <!-- The form of interest follows -->
//     <form id='MY_FORM_ID'>
//       <input>
//       <input>
//       <iframe></iframe>
//       <iframe></iframe>
//     </form>
//     <!-- Two forms not of interest follow -->
//     <form><input><iframe></iframe></form>
//     <input><iframe></iframe>
//   </body>
INSTANTIATE_TEST_SUITE_P(
    FormAutofillUtilsTest,
    FieldFramesTest,
    testing::ValuesIn([] {};

TEST_F(FormAutofillUtilsTest, ExtractFormData_WebFormElementToFormData) {}

// Tests that if the number of iframes exceeds kMaxExtractableChildFrames,
// child frames of that form are not extracted.
TEST_F(FormAutofillUtilsTest, ExtractFormData_ExtractNoFramesIfTooManyIframes) {}

// Tests that if the number of fields exceeds |kMaxExtractableFields|, neither
// fields nor child frames of that form are extracted.
TEST_F(FormAutofillUtilsTest, ExtractNoFieldsOrFramesIfTooManyFields) {}

// Verifies that the callback happens even if no sequences of 4 digits are
// found.
TEST_F(FormAutofillUtilsTest, TraverseDomForFourDigitCombinations_NoMatches) {}

// Verifies that the matches correctly returns all four digit combinations.
TEST_F(FormAutofillUtilsTest,
       TraverseDomForFourDigitCombinations_MatchesFound) {}

// Ensure that we don't return duplicate values.
TEST_F(FormAutofillUtilsTest,
       TraverseDomForFourDigitCombinations_MatchesFoundWithDuplicates) {}

// Ensures that we correctly perform checks on the last four digit combinations
// for year values.
TEST_F(FormAutofillUtilsTest,
       TraverseDomForFourDigitCombinations_YearsRemoved) {}

MATCHER(SameNode, "") {}

void PrefixTraverseAndAppend(WebNode node, std::vector<WebNode>& out) {}

// Tests that the appropriate web node is returned when iterating through the
// web DOM in forward direction.
TEST_F(FormAutofillUtilsTest, NextWebNode_Forward) {}

// Tests that the appropriate web node is returned when iterating through the
// web DOM in backwards direction.
TEST_F(FormAutofillUtilsTest, NextWebNode_Backward) {}

// Tests that GetMaxLength() of non-text form controls is 0, and text form
// controls default to the maximum 32 bit integer (and *not* 64 bit integer, so
// that we can still do arithmetic with the maximum length).
TEST_F(FormAutofillUtilsTest, GetMaxLength) {}

TEST_F(FormAutofillUtilsTest, ContentEditableWritingSuggestionsFalseInherited) {}

TEST_F(FormAutofillUtilsTest, ContentEditableWritingSuggestionsFalse) {}

TEST_F(FormAutofillUtilsTest, FindFormForContentEditableSuccess) {}

TEST_F(FormAutofillUtilsTest, FindFormForContentEditableAbridgedSuccess) {}

TEST_F(FormAutofillUtilsTest, FindFormForContentEditableFailures) {}

TEST_F(FormAutofillUtilsTest, ExtractFormData_OwnedForm) {}

TEST_F(FormAutofillUtilsTest, ExtractFormData_UnownedForm) {}

// Tests that the owning form of a form control element in light DOM is its
// associated form (i.e. the form explicitly set via form attribute or its
// closest ancestor).
// Also tests that GetFormControlElements(f) == {t | GetOwningForm(t) == f} for
// every form f that owns some t.
TEST_F(FormAutofillUtilsTest, GetOwningFormInLightDom) {}

// Tests that explicit association overrules DOM ancestry when determining the
// owning form.
// Also tests that GetFormControlElements(f) == {t | GetOwningForm(t) == f} for
// every form f that owns some t.
TEST_F(FormAutofillUtilsTest, GetOwningFormInLightDomWithExplicitAssociation) {}

// Tests that input elements in shadow DOM whose closest ancestor is in the
// light DOM are extracted correctly.
// Also tests that GetFormControlElements(f) == {t | GetOwningForm(t) == f} for
// every form f that owns some t.
TEST_F(FormAutofillUtilsTest, GetOwningFormInShadowDomWithoutFormInShadowDom) {}

// Tests that the owning form of a form control element is the furthest
// shadow-including ancestor form element (in absence of explicit associations).
// Also tests that GetFormControlElements(f) == {t | GetOwningForm(t) == f} for
// every form f that owns some t.
TEST_F(FormAutofillUtilsTest, GetOwningFormInShadowDomWithFormInShadowDom) {}

// Tests that the owning form is returned correctly even if there are multiple
// levels of Shadow DOM.
// Also tests that GetFormControlElements(f) == {t | GetOwningForm(t) == f} for
// every form f that owns some t.
TEST_F(FormAutofillUtilsTest,
       GetOwningFormInShadowDomWithFormInShadowDomWithMultipleLevels) {}

// Tests that the owning form is computed correctly for form control elements
// inside the shadow DOM that have explicit form attributes.
// Also tests that GetFormControlElements(f) == {t | GetOwningForm(t) == f} for
// every form f that owns some t.
TEST_F(FormAutofillUtilsTest,
       GetOwningFormInShadowDomWithFormInShadowDomAndExplicitAssociation) {}

// Tests that the owning form is computed correctly for nested forms.
TEST_F(FormAutofillUtilsTest, GetOwningFormWithNestedFormsInLightDom) {}

// Tests that GetOwnedFormControls() doesn't return disconnected elements.
TEST_F(FormAutofillUtilsTest, GetOwnedFormControlsRequiresConnectedness) {}

}  // namespace
}  // namespace autofill::form_util