| // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include <stddef.h> |
| |
| #include <vector> |
| |
| #include "base/format_macros.h" |
| #include "base/run_loop.h" |
| #include "base/stl_util.h" |
| #include "base/strings/string16.h" |
| #include "base/strings/stringprintf.h" |
| #include "base/strings/utf_string_conversions.h" |
| #include "base/test/scoped_feature_list.h" |
| #include "build/build_config.h" |
| #include "chrome/test/base/chrome_render_view_test.h" |
| #include "components/autofill/content/renderer/form_autofill_util.h" |
| #include "components/autofill/content/renderer/form_cache.h" |
| #include "components/autofill/core/common/autofill_data_validation.h" |
| #include "components/autofill/core/common/autofill_features.h" |
| #include "components/autofill/core/common/form_data.h" |
| #include "components/autofill/core/common/renderer_id.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_script_source.h" |
| #include "third_party/blink/public/web/web_select_element.h" |
| |
| #if defined(OS_WIN) |
| #include "third_party/blink/public/web/win/web_font_rendering.h" |
| #endif |
| |
| using autofill::features::kAutofillEnforceMinRequiredFieldsForHeuristics; |
| using autofill::features::kAutofillEnforceMinRequiredFieldsForQuery; |
| using autofill::features::kAutofillEnforceMinRequiredFieldsForUpload; |
| using base::ASCIIToUTF16; |
| using blink::WebAutofillState; |
| using blink::WebDocument; |
| using blink::WebElement; |
| using blink::WebFormControlElement; |
| using blink::WebFormElement; |
| using blink::WebInputElement; |
| using blink::WebLocalFrame; |
| using blink::WebSelectElement; |
| using blink::WebString; |
| using blink::WebVector; |
| |
| namespace autofill { |
| namespace form_util { |
| |
| namespace { |
| |
| struct AutofillFieldCase { |
| const char* const form_control_type; |
| const char* const id_attribute; |
| const char* const initial_value; |
| const char* const autocomplete_attribute; // The autocomplete attribute of |
| // the element. |
| bool should_be_autofilled; // Whether the filed should be autofilled. |
| const char* const autofill_value; // The value being used to fill the field. |
| const char* const expected_value; // The expected value after Autofill |
| // or Preview. |
| }; |
| |
| struct WebElementDescriptor { |
| enum RetrievalMethod { |
| CSS_SELECTOR, |
| ID, |
| NONE, |
| }; |
| |
| // Information to retrieve element with. |
| std::string descriptor; |
| |
| // Which retrieval method to use. |
| RetrievalMethod retrieval_method = NONE; |
| }; |
| |
| const char kFormHtml[] = |
| "<FORM name='TestForm' action='http://abc.com' method='post'>" |
| " <INPUT type='text' id='firstname'/>" |
| " <INPUT type='text' id='lastname'/>" |
| " <INPUT type='hidden' id='imhidden'/>" |
| " <INPUT type='text' id='notempty' value='Hi'/>" |
| " <INPUT type='text' autocomplete='off' id='noautocomplete'/>" |
| " <INPUT type='text' disabled='disabled' id='notenabled'/>" |
| " <INPUT type='text' readonly id='readonly'/>" |
| " <INPUT type='text' style='visibility: hidden'" |
| " id='invisible'/>" |
| " <INPUT type='text' style='display: none' id='displaynone'/>" |
| " <INPUT type='month' id='month'/>" |
| " <INPUT type='month' id='month-nonempty' value='2011-12'/>" |
| " <SELECT id='select'>" |
| " <OPTION></OPTION>" |
| " <OPTION value='CA'>California</OPTION>" |
| " <OPTION value='TX'>Texas</OPTION>" |
| " </SELECT>" |
| " <SELECT id='select-nonempty'>" |
| " <OPTION value='CA' selected>California</OPTION>" |
| " <OPTION value='TX'>Texas</OPTION>" |
| " </SELECT>" |
| " <SELECT id='select-unchanged'>" |
| " <OPTION value='CA' selected>California</OPTION>" |
| " <OPTION value='TX'>Texas</OPTION>" |
| " </SELECT>" |
| " <SELECT id='select-displaynone' style='display:none'>" |
| " <OPTION value='CA' selected>California</OPTION>" |
| " <OPTION value='TX'>Texas</OPTION>" |
| " </SELECT>" |
| " <TEXTAREA id='textarea'></TEXTAREA>" |
| " <TEXTAREA id='textarea-nonempty'>Go away!</TEXTAREA>" |
| " <INPUT type='submit' name='reply-send' value='Send'/>" |
| "</FORM>"; |
| |
| // This constant uses a mixed-case title tag to be sure that the title match is |
| // not case-sensitive. Other tests in this file use an all-lower title tag. |
| const char kUnownedFormHtml[] = |
| "<HEAD><TITLE>Enter Shipping Info</TITLE></HEAD>" |
| "<INPUT type='text' id='firstname'/>" |
| "<INPUT type='text' id='lastname'/>" |
| "<INPUT type='hidden' id='imhidden'/>" |
| "<INPUT type='text' id='notempty' value='Hi'/>" |
| "<INPUT type='text' autocomplete='off' id='noautocomplete'/>" |
| "<INPUT type='text' disabled='disabled' id='notenabled'/>" |
| "<INPUT type='text' readonly id='readonly'/>" |
| "<INPUT type='text' style='visibility: hidden'" |
| " id='invisible'/>" |
| "<INPUT type='text' style='display: none' id='displaynone'/>" |
| "<INPUT type='month' id='month'/>" |
| "<INPUT type='month' id='month-nonempty' value='2011-12'/>" |
| "<SELECT id='select'>" |
| " <OPTION></OPTION>" |
| " <OPTION value='CA'>California</OPTION>" |
| " <OPTION value='TX'>Texas</OPTION>" |
| "</SELECT>" |
| "<SELECT id='select-nonempty'>" |
| " <OPTION value='CA' selected>California</OPTION>" |
| " <OPTION value='TX'>Texas</OPTION>" |
| "</SELECT>" |
| "<SELECT id='select-unchanged'>" |
| " <OPTION value='CA' selected>California</OPTION>" |
| " <OPTION value='TX'>Texas</OPTION>" |
| "</SELECT>" |
| "<SELECT id='select-displaynone' style='display:none'>" |
| " <OPTION value='CA' selected>California</OPTION>" |
| " <OPTION value='TX'>Texas</OPTION>" |
| "</SELECT>" |
| "<TEXTAREA id='textarea'></TEXTAREA>" |
| "<TEXTAREA id='textarea-nonempty'>Go away!</TEXTAREA>" |
| "<INPUT type='submit' name='reply-send' value='Send'/>"; |
| |
| // This constant has no title tag, and should be passed to |
| // LoadHTMLWithURLOverride to test the detection of unowned forms by URL. |
| const char kUnownedUntitledFormHtml[] = |
| "<INPUT type='text' id='firstname'/>" |
| "<INPUT type='text' id='lastname'/>" |
| "<INPUT type='hidden' id='imhidden'/>" |
| "<INPUT type='text' id='notempty' value='Hi'/>" |
| "<INPUT type='text' autocomplete='off' id='noautocomplete'/>" |
| "<INPUT type='text' disabled='disabled' id='notenabled'/>" |
| "<INPUT type='text' readonly id='readonly'/>" |
| "<INPUT type='text' style='visibility: hidden'" |
| " id='invisible'/>" |
| "<INPUT type='text' style='display: none' id='displaynone'/>" |
| "<INPUT type='month' id='month'/>" |
| "<INPUT type='month' id='month-nonempty' value='2011-12'/>" |
| "<SELECT id='select'>" |
| " <OPTION></OPTION>" |
| " <OPTION value='CA'>California</OPTION>" |
| " <OPTION value='TX'>Texas</OPTION>" |
| "</SELECT>" |
| "<SELECT id='select-nonempty'>" |
| " <OPTION value='CA' selected>California</OPTION>" |
| " <OPTION value='TX'>Texas</OPTION>" |
| "</SELECT>" |
| "<SELECT id='select-unchanged'>" |
| " <OPTION value='CA' selected>California</OPTION>" |
| " <OPTION value='TX'>Texas</OPTION>" |
| "</SELECT>" |
| "<SELECT id='select-displaynone' style='display:none'>" |
| " <OPTION value='CA' selected>California</OPTION>" |
| " <OPTION value='TX'>Texas</OPTION>" |
| "</SELECT>" |
| "<TEXTAREA id='textarea'></TEXTAREA>" |
| "<TEXTAREA id='textarea-nonempty'>Go away!</TEXTAREA>" |
| "<INPUT type='submit' name='reply-send' value='Send'/>"; |
| |
| // This constant does not have a title tag, but should match an unowned form |
| // anyway because it is not English. |
| const char kUnownedNonEnglishFormHtml[] = |
| "<HTML LANG='fr'>" |
| "<INPUT type='text' id='firstname'/>" |
| "<INPUT type='text' id='lastname'/>" |
| "<INPUT type='hidden' id='imhidden'/>" |
| "<INPUT type='text' id='notempty' value='Hi'/>" |
| "<INPUT type='text' autocomplete='off' id='noautocomplete'/>" |
| "<INPUT type='text' disabled='disabled' id='notenabled'/>" |
| "<INPUT type='text' readonly id='readonly'/>" |
| "<INPUT type='text' style='visibility: hidden'" |
| " id='invisible'/>" |
| "<INPUT type='text' style='display: none' id='displaynone'/>" |
| "<INPUT type='month' id='month'/>" |
| "<INPUT type='month' id='month-nonempty' value='2011-12'/>" |
| "<SELECT id='select'>" |
| " <OPTION></OPTION>" |
| " <OPTION value='CA'>California</OPTION>" |
| " <OPTION value='TX'>Texas</OPTION>" |
| "</SELECT>" |
| "<SELECT id='select-nonempty'>" |
| " <OPTION value='CA' selected>California</OPTION>" |
| " <OPTION value='TX'>Texas</OPTION>" |
| "</SELECT>" |
| "<SELECT id='select-unchanged'>" |
| " <OPTION value='CA' selected>California</OPTION>" |
| " <OPTION value='TX'>Texas</OPTION>" |
| "</SELECT>" |
| "<SELECT id='select-displaynone' style='display:none'>" |
| " <OPTION value='CA' selected>California</OPTION>" |
| " <OPTION value='TX'>Texas</OPTION>" |
| "</SELECT>" |
| "<TEXTAREA id='textarea'></TEXTAREA>" |
| "<TEXTAREA id='textarea-nonempty'>Go away!</TEXTAREA>" |
| "<INPUT type='submit' name='reply-send' value='Send'/>" |
| "</HTML>"; |
| |
| std::string RetrievalMethodToString( |
| const WebElementDescriptor::RetrievalMethod& method) { |
| switch (method) { |
| case WebElementDescriptor::CSS_SELECTOR: |
| return "CSS_SELECTOR"; |
| case WebElementDescriptor::ID: |
| return "ID"; |
| case WebElementDescriptor::NONE: |
| return "NONE"; |
| } |
| NOTREACHED(); |
| return "UNKNOWN"; |
| } |
| |
| bool ClickElement(const WebDocument& document, |
| const WebElementDescriptor& element_descriptor) { |
| WebString web_descriptor = WebString::FromUTF8(element_descriptor.descriptor); |
| blink::WebElement element; |
| |
| switch (element_descriptor.retrieval_method) { |
| case WebElementDescriptor::CSS_SELECTOR: { |
| element = document.QuerySelector(web_descriptor); |
| break; |
| } |
| case WebElementDescriptor::ID: |
| element = document.GetElementById(web_descriptor); |
| break; |
| case WebElementDescriptor::NONE: |
| return true; |
| } |
| |
| if (element.IsNull()) { |
| DVLOG(1) << "Could not find " |
| << element_descriptor.descriptor |
| << " by " |
| << RetrievalMethodToString(element_descriptor.retrieval_method) |
| << "."; |
| return false; |
| } |
| |
| element.SimulateClick(); |
| return true; |
| } |
| |
| } // namespace |
| |
| class FormAutofillTest : public ChromeRenderViewTest { |
| public: |
| FormAutofillTest() : ChromeRenderViewTest() { |
| scoped_feature_list_.InitAndEnableFeature( |
| features::kAutofillRestrictUnownedFieldsToFormlessCheckout); |
| } |
| ~FormAutofillTest() override {} |
| |
| #if defined(OS_WIN) |
| void SetUp() override { |
| ChromeRenderViewTest::SetUp(); |
| |
| // Autofill uses the system font to render suggestion previews. On Windows |
| // an extra step is required to ensure that the system font is configured. |
| blink::WebFontRendering::SetMenuFontMetrics( |
| base::ASCIIToUTF16("Arial").c_str(), 12); |
| } |
| #endif |
| |
| void ExpectLabels(const char* html, |
| const std::vector<base::string16>& id_attributes, |
| const std::vector<base::string16>& name_attributes, |
| const std::vector<base::string16>& labels, |
| const std::vector<base::string16>& names, |
| const std::vector<base::string16>& values) { |
| ASSERT_EQ(labels.size(), id_attributes.size()); |
| ASSERT_EQ(labels.size(), name_attributes.size()); |
| ASSERT_EQ(labels.size(), names.size()); |
| ASSERT_EQ(labels.size(), values.size()); |
| |
| std::vector<FormFieldData> fields; |
| for (size_t i = 0; i < labels.size(); ++i) { |
| FormFieldData expected; |
| expected.id_attribute = id_attributes[i]; |
| expected.name_attribute = name_attributes[i]; |
| expected.label = labels[i]; |
| expected.name = names[i]; |
| expected.value = values[i]; |
| expected.form_control_type = "text"; |
| expected.max_length = WebInputElement::DefaultMaxLength(); |
| fields.push_back(expected); |
| } |
| ExpectLabelsAndTypes(html, fields); |
| } |
| |
| void ExpectLabelsAndTypes(const char* html, |
| const std::vector<FormFieldData>& fields) { |
| LoadHTML(html); |
| |
| WebLocalFrame* web_frame = GetMainFrame(); |
| ASSERT_NE(nullptr, web_frame); |
| |
| FormCache form_cache(web_frame); |
| std::vector<FormData> forms = form_cache.ExtractNewForms(nullptr); |
| ASSERT_EQ(1U, forms.size()); |
| |
| const FormData& form = forms[0]; |
| EXPECT_EQ(ASCIIToUTF16("TestForm"), form.name); |
| EXPECT_EQ(GetCanonicalOriginForDocument(web_frame->GetDocument()), |
| form.url); |
| EXPECT_EQ(GURL("http://cnn.com"), form.action); |
| ASSERT_EQ(fields.size(), form.fields.size()); |
| |
| for (size_t i = 0; i < fields.size(); ++i) { |
| SCOPED_TRACE(base::StringPrintf("i: %" PRIuS, i)); |
| EXPECT_FORM_FIELD_DATA_EQUALS(fields[i], form.fields[i]); |
| } |
| } |
| |
| // Use this validator when the test HTML uses the id attribute instead of |
| // the name attribute to identify the input fields. Otherwise, this is the |
| // same text structure as ExpectJohnSmithLabelsAndNameAttributes(). |
| void ExpectJohnSmithLabelsAndIdAttributes(const char* html) { |
| std::vector<base::string16> id_attributes, name_attributes, labels, names, |
| values; |
| |
| id_attributes.push_back(ASCIIToUTF16("firstname")); |
| name_attributes.push_back(base::string16()); |
| labels.push_back(ASCIIToUTF16("First name:")); |
| names.push_back(id_attributes.back()); |
| values.push_back(ASCIIToUTF16("John")); |
| |
| id_attributes.push_back(ASCIIToUTF16("lastname")); |
| name_attributes.push_back(base::string16()); |
| labels.push_back(ASCIIToUTF16("Last name:")); |
| names.push_back(id_attributes.back()); |
| values.push_back(ASCIIToUTF16("Smith")); |
| |
| id_attributes.push_back(ASCIIToUTF16("email")); |
| name_attributes.push_back(base::string16()); |
| labels.push_back(ASCIIToUTF16("Email:")); |
| names.push_back(id_attributes.back()); |
| values.push_back(ASCIIToUTF16("john@example.com")); |
| |
| ExpectLabels(html, id_attributes, name_attributes, labels, names, values); |
| } |
| |
| // Use this validator when the test HTML uses the name attribute instead of |
| // the id attribute to identify the input fields. Otherwise, this is the same |
| // text structure as ExpectJohnSmithLabelsAndIdAttributes(). |
| void ExpectJohnSmithLabelsAndNameAttributes(const char* html) { |
| std::vector<base::string16> id_attributes, name_attributes, labels, names, |
| values; |
| id_attributes.push_back(base::string16()); |
| name_attributes.push_back(ASCIIToUTF16("firstname")); |
| labels.push_back(ASCIIToUTF16("First name:")); |
| names.push_back(name_attributes.back()); |
| values.push_back(ASCIIToUTF16("John")); |
| |
| id_attributes.push_back(base::string16()); |
| name_attributes.push_back(ASCIIToUTF16("lastname")); |
| labels.push_back(ASCIIToUTF16("Last name:")); |
| names.push_back(name_attributes.back()); |
| values.push_back(ASCIIToUTF16("Smith")); |
| |
| id_attributes.push_back(base::string16()); |
| name_attributes.push_back(ASCIIToUTF16("email")); |
| labels.push_back(ASCIIToUTF16("Email:")); |
| names.push_back(name_attributes.back()); |
| values.push_back(ASCIIToUTF16("john@example.com")); |
| ExpectLabels(html, id_attributes, name_attributes, labels, names, values); |
| } |
| |
| typedef void (*FillFormFunction)(const FormData& form, |
| const WebFormControlElement& element); |
| |
| typedef WebString (*GetValueFunction)(WebFormControlElement element); |
| |
| // Test FormFillxxx functions. |
| void TestFormFillFunctions(const char* html, |
| bool unowned, |
| const char* url_override, |
| const AutofillFieldCase* field_cases, |
| size_t number_of_field_cases, |
| FillFormFunction fill_form_function, |
| GetValueFunction get_value_function) { |
| if (url_override) |
| LoadHTMLWithUrlOverride(html, url_override); |
| else |
| LoadHTML(html); |
| |
| WebLocalFrame* web_frame = GetMainFrame(); |
| ASSERT_NE(nullptr, web_frame); |
| |
| FormCache form_cache(web_frame); |
| std::vector<FormData> forms = form_cache.ExtractNewForms(nullptr); |
| ASSERT_EQ(1U, forms.size()); |
| |
| // Get the input element we want to find. |
| WebInputElement input_element = GetInputElementById("firstname"); |
| |
| // Find the form that contains the input element. |
| FormData form_data; |
| FormFieldData field; |
| EXPECT_TRUE(FindFormAndFieldForFormControlElement(input_element, nullptr, |
| &form_data, &field)); |
| if (!unowned) { |
| EXPECT_EQ(ASCIIToUTF16("TestForm"), form_data.name); |
| EXPECT_EQ(GURL("http://abc.com"), form_data.action); |
| } |
| |
| const std::vector<FormFieldData>& fields = form_data.fields; |
| ASSERT_EQ(number_of_field_cases, fields.size()); |
| |
| FormFieldData expected; |
| // Verify field's initial value. |
| for (size_t i = 0; i < number_of_field_cases; ++i) { |
| SCOPED_TRACE(base::StringPrintf("Verify initial value for field %s", |
| field_cases[i].id_attribute)); |
| expected.form_control_type = field_cases[i].form_control_type; |
| expected.max_length = expected.form_control_type == "text" |
| ? WebInputElement::DefaultMaxLength() |
| : 0; |
| expected.id_attribute = ASCIIToUTF16(field_cases[i].id_attribute); |
| expected.name = expected.id_attribute; |
| expected.value = ASCIIToUTF16(field_cases[i].initial_value); |
| if (expected.form_control_type == "text" || |
| expected.form_control_type == "month") { |
| expected.label = ASCIIToUTF16(field_cases[i].initial_value); |
| } else { |
| expected.label.clear(); |
| } |
| expected.autocomplete_attribute = field_cases[i].autocomplete_attribute; |
| EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[i]); |
| // Fill the form_data for the field. |
| form_data.fields[i].value = ASCIIToUTF16(field_cases[i].autofill_value); |
| // Set the is_autofilled property for the field. |
| form_data.fields[i].is_autofilled = field_cases[i].should_be_autofilled; |
| } |
| |
| // Autofill the form using the given fill form function. |
| fill_form_function(form_data, input_element); |
| |
| // Validate Autofill or Preview results. |
| for (size_t i = 0; i < number_of_field_cases; ++i) { |
| ValidateFilledField(field_cases[i], get_value_function); |
| } |
| } |
| |
| // Validate an Autofilled field. |
| void ValidateFilledField(const AutofillFieldCase& field_case, |
| GetValueFunction get_value_function) { |
| SCOPED_TRACE(base::StringPrintf("Verify autofilled value for field %s", |
| field_case.id_attribute)); |
| WebString value; |
| WebFormControlElement element = GetFormControlElementById( |
| WebString::FromASCII(field_case.id_attribute)); |
| if ((element.FormControlType() == "select-one") || |
| (element.FormControlType() == "textarea")) { |
| value = get_value_function(element); |
| } else { |
| ASSERT_TRUE(element.FormControlType() == "text" || |
| element.FormControlType() == "month"); |
| value = get_value_function(element); |
| } |
| |
| const WebString expected_value = |
| WebString::FromASCII(field_case.expected_value); |
| if (expected_value.IsEmpty()) |
| EXPECT_TRUE(value.IsEmpty()); |
| else |
| EXPECT_EQ(expected_value.Utf8(), value.Utf8()); |
| |
| EXPECT_EQ(field_case.should_be_autofilled, element.IsAutofilled()); |
| } |
| |
| WebFormControlElement GetFormControlElementById(const WebString& id) { |
| return GetMainFrame() |
| ->GetDocument() |
| .GetElementById(id) |
| .To<WebFormControlElement>(); |
| } |
| |
| WebInputElement GetInputElementById(const WebString& id) { |
| return GetMainFrame() |
| ->GetDocument() |
| .GetElementById(id) |
| .To<WebInputElement>(); |
| } |
| |
| void TestFillForm(const char* html, bool unowned, const char* url_override) { |
| static const AutofillFieldCase field_cases[] = { |
| // fields: form_control_type, name, initial_value, autocomplete_attribute, |
| // should_be_autofilled, autofill_value, expected_value |
| |
| // Regular empty fields (firstname & lastname) should be autofilled. |
| {"text", |
| "firstname", |
| "", |
| "", |
| true, |
| "filled firstname", |
| "filled firstname"}, |
| {"text", "lastname", "", "", true, "filled lastname", "filled lastname"}, |
| // hidden fields should not be extracted to form_data. |
| // Non empty fields should not be autofilled. |
| {"text", "notempty", "Hi", "", false, "filled notempty", "Hi"}, |
| {"text", |
| "noautocomplete", |
| "", |
| "off", |
| true, |
| "filled noautocomplete", |
| "filled noautocomplete"}, |
| // Disabled fields should not be autofilled. |
| {"text", "notenabled", "", "", false, "filled notenabled", ""}, |
| // Readonly fields should not be autofilled. |
| {"text", "readonly", "", "", false, "filled readonly", ""}, |
| // Fields with "visibility: hidden" should not be autofilled. |
| {"text", "invisible", "", "", false, "filled invisible", ""}, |
| // Fields with "display:none" should not be autofilled. |
| {"text", "displaynone", "", "", false, "filled displaynone", ""}, |
| // Regular <input type="month"> should be autofilled. |
| {"month", "month", "", "", true, "2017-11", "2017-11"}, |
| // Non-empty <input type="month"> should not be autofilled. |
| {"month", "month-nonempty", "2011-12", "", false, "2017-11", "2011-12"}, |
| // Regular select fields should be autofilled. |
| {"select-one", "select", "", "", true, "TX", "TX"}, |
| // Select fields should be autofilled even if they already have a |
| // non-empty value. |
| {"select-one", "select-nonempty", "CA", "", true, "TX", "TX"}, |
| // Select fields should not be autofilled if no new value is passed from |
| // autofill profile. The existing value should not be overriden. |
| {"select-one", "select-unchanged", "CA", "", false, "CA", "CA"}, |
| // Select fields that are not focusable should always be filled. |
| {"select-one", "select-displaynone", "CA", "", true, "CA", "CA"}, |
| // Regular textarea elements should be autofilled. |
| {"textarea", |
| "textarea", |
| "", |
| "", |
| true, |
| "some multi-\nline value", |
| "some multi-\nline value"}, |
| // Non-empty textarea elements should not be autofilled. |
| {"textarea", |
| "textarea-nonempty", |
| "Go\naway!", |
| "", |
| false, |
| "some multi-\nline value", |
| "Go\naway!"}, |
| }; |
| TestFormFillFunctions(html, unowned, url_override, field_cases, |
| base::size(field_cases), FillForm, &GetValueWrapper); |
| // Verify preview selection. |
| WebInputElement firstname = GetInputElementById("firstname"); |
| EXPECT_EQ(16, firstname.SelectionStart()); |
| EXPECT_EQ(16, firstname.SelectionEnd()); |
| } |
| |
| void TestPreviewForm(const char* html, bool unowned, |
| const char* url_override) { |
| static const AutofillFieldCase field_cases[] = { |
| // Normal empty fields should be previewed. |
| {"text", |
| "firstname", |
| "", |
| "", |
| true, |
| "suggested firstname", |
| "suggested firstname"}, |
| {"text", |
| "lastname", |
| "", |
| "", |
| true, |
| "suggested lastname", |
| "suggested lastname"}, |
| // Hidden fields should not be extracted to form_data. |
| // Non empty fields should not be previewed. |
| {"text", "notempty", "Hi", "", false, "suggested notempty", ""}, |
| {"text", |
| "noautocomplete", |
| "", |
| "off", |
| true, |
| "filled noautocomplete", |
| "filled noautocomplete"}, |
| // Disabled fields should not be previewed. |
| {"text", "notenabled", "", "", false, "suggested notenabled", ""}, |
| // Readonly fields should not be previewed. |
| {"text", "readonly", "", "", false, "suggested readonly", ""}, |
| // Fields with "visibility: hidden" should not be previewed. |
| {"text", "invisible", "", "", false, "suggested invisible", ""}, |
| // Fields with "display:none" should not previewed. |
| {"text", "displaynone", "", "", false, "suggested displaynone", ""}, |
| // Regular <input type="month"> should be previewed. |
| {"month", "month", "", "", true, "2017-11", "2017-11"}, |
| // Non-empty <input type="month"> should not be previewed. |
| {"month", "month-nonempty", "2011-12", "", false, "2017-11", ""}, |
| // Regular select fields should be previewed. |
| {"select-one", "select", "", "", true, "TX", "TX"}, |
| // Select fields should be previewed even if they already have a |
| // non-empty value. |
| {"select-one", "select-nonempty", "CA", "", true, "TX", "TX"}, |
| // Select fields should not be previewed if no suggestion is passed from |
| // autofill profile. |
| {"select-one", "select-unchanged", "CA", "", false, "", ""}, |
| // Select fields that are not focusable should always be filled. |
| {"select-one", "select-displaynone", "CA", "", true, "CA", "CA"}, |
| // Normal textarea elements should be previewed. |
| {"textarea", |
| "textarea", |
| "", |
| "", |
| true, |
| "suggested multi-\nline value", |
| "suggested multi-\nline value"}, |
| // Nonempty textarea elements should not be previewed. |
| {"textarea", |
| "textarea-nonempty", |
| "Go\naway!", |
| "", |
| false, |
| "suggested multi-\nline value", |
| ""}, |
| }; |
| TestFormFillFunctions(html, unowned, url_override, field_cases, |
| base::size(field_cases), &PreviewForm, |
| &GetSuggestedValueWrapper); |
| |
| // Verify preview selection. |
| WebInputElement firstname = GetInputElementById("firstname"); |
| // Since the suggestion is previewed as a placeholder, there should be no |
| // selected text. |
| EXPECT_EQ(0, firstname.SelectionStart()); |
| EXPECT_EQ(0, firstname.SelectionEnd()); |
| } |
| |
| void TestUnmatchedUnownedForm(const char* html, const char* url_override) { |
| if (url_override) |
| LoadHTMLWithUrlOverride(html, url_override); |
| else |
| LoadHTML(html); |
| |
| WebLocalFrame* web_frame = GetMainFrame(); |
| ASSERT_NE(nullptr, web_frame); |
| |
| FormCache form_cache(web_frame); |
| std::vector<FormData> forms = form_cache.ExtractNewForms(nullptr); |
| ASSERT_EQ(0U, forms.size()); |
| } |
| |
| void TestFindFormForInputElement(const char* html, bool unowned) { |
| LoadHTML(html); |
| WebLocalFrame* web_frame = GetMainFrame(); |
| ASSERT_NE(nullptr, web_frame); |
| |
| FormCache form_cache(web_frame); |
| std::vector<FormData> forms = form_cache.ExtractNewForms(nullptr); |
| ASSERT_EQ(1U, forms.size()); |
| |
| // Get the input element we want to find. |
| WebInputElement input_element = GetInputElementById("firstname"); |
| |
| // Find the form and verify it's the correct form. |
| FormData form; |
| FormFieldData field; |
| EXPECT_TRUE(FindFormAndFieldForFormControlElement(input_element, nullptr, |
| &form, &field)); |
| EXPECT_EQ(GetCanonicalOriginForDocument(web_frame->GetDocument()), |
| form.url); |
| if (!unowned) { |
| EXPECT_EQ(ASCIIToUTF16("TestForm"), form.name); |
| EXPECT_EQ(GURL("http://abc.com"), form.action); |
| } |
| |
| const std::vector<FormFieldData>& fields = form.fields; |
| ASSERT_EQ(4U, fields.size()); |
| |
| FormFieldData expected; |
| expected.form_control_type = "text"; |
| expected.max_length = WebInputElement::DefaultMaxLength(); |
| |
| expected.id_attribute = ASCIIToUTF16("firstname"); |
| expected.name = expected.id_attribute; |
| expected.value = ASCIIToUTF16("John"); |
| expected.label = ASCIIToUTF16("John"); |
| EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[0]); |
| EXPECT_FORM_FIELD_DATA_EQUALS(expected, field); |
| |
| expected.id_attribute = ASCIIToUTF16("lastname"); |
| expected.name = expected.id_attribute; |
| expected.value = ASCIIToUTF16("Smith"); |
| expected.label = ASCIIToUTF16("Smith"); |
| EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[1]); |
| |
| expected.id_attribute = ASCIIToUTF16("email"); |
| expected.name = expected.id_attribute; |
| expected.value = ASCIIToUTF16("john@example.com"); |
| expected.label = ASCIIToUTF16("john@example.com"); |
| expected.autocomplete_attribute = "off"; |
| EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[2]); |
| expected.autocomplete_attribute.clear(); |
| |
| expected.id_attribute = ASCIIToUTF16("phone"); |
| expected.name = expected.id_attribute; |
| expected.value = ASCIIToUTF16("1.800.555.1234"); |
| expected.label = ASCIIToUTF16("1.800.555.1234"); |
| EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[3]); |
| } |
| |
| void TestFindFormForTextAreaElement(const char* html, bool unowned) { |
| LoadHTML(html); |
| WebLocalFrame* web_frame = GetMainFrame(); |
| ASSERT_NE(nullptr, web_frame); |
| |
| FormCache form_cache(web_frame); |
| std::vector<FormData> forms = form_cache.ExtractNewForms(nullptr); |
| ASSERT_EQ(1U, forms.size()); |
| |
| // Get the textarea element we want to find. |
| WebElement element = |
| web_frame->GetDocument().GetElementById("street-address"); |
| WebFormControlElement textarea_element = |
| element.To<WebFormControlElement>(); |
| |
| // Find the form and verify it's the correct form. |
| FormData form; |
| FormFieldData field; |
| EXPECT_TRUE(FindFormAndFieldForFormControlElement(textarea_element, nullptr, |
| &form, &field)); |
| EXPECT_EQ(GetCanonicalOriginForDocument(web_frame->GetDocument()), |
| form.url); |
| if (!unowned) { |
| EXPECT_EQ(ASCIIToUTF16("TestForm"), form.name); |
| EXPECT_EQ(GURL("http://abc.com"), form.action); |
| } |
| |
| const std::vector<FormFieldData>& fields = form.fields; |
| ASSERT_EQ(4U, fields.size()); |
| |
| FormFieldData expected; |
| |
| expected.id_attribute = ASCIIToUTF16("firstname"); |
| expected.name = expected.id_attribute; |
| expected.value = ASCIIToUTF16("John"); |
| expected.label = ASCIIToUTF16("John"); |
| expected.form_control_type = "text"; |
| expected.max_length = WebInputElement::DefaultMaxLength(); |
| EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[0]); |
| |
| expected.id_attribute = ASCIIToUTF16("lastname"); |
| expected.name = expected.id_attribute; |
| expected.value = ASCIIToUTF16("Smith"); |
| expected.label = ASCIIToUTF16("Smith"); |
| expected.form_control_type = "text"; |
| expected.max_length = WebInputElement::DefaultMaxLength(); |
| EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[1]); |
| |
| expected.id_attribute = ASCIIToUTF16("email"); |
| expected.name = expected.id_attribute; |
| expected.value = ASCIIToUTF16("john@example.com"); |
| expected.label = ASCIIToUTF16("john@example.com"); |
| expected.autocomplete_attribute = "off"; |
| expected.form_control_type = "text"; |
| expected.max_length = WebInputElement::DefaultMaxLength(); |
| EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[2]); |
| expected.autocomplete_attribute.clear(); |
| |
| expected.id_attribute = ASCIIToUTF16("street-address"); |
| expected.name = expected.id_attribute; |
| expected.value = ASCIIToUTF16("123 Fantasy Ln.\nApt. 42"); |
| expected.label.clear(); |
| expected.form_control_type = "textarea"; |
| expected.max_length = 0; |
| EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[3]); |
| EXPECT_FORM_FIELD_DATA_EQUALS(expected, field); |
| } |
| |
| void TestFillFormMaxLength(const char* html, bool unowned) { |
| LoadHTML(html); |
| WebLocalFrame* web_frame = GetMainFrame(); |
| ASSERT_NE(nullptr, web_frame); |
| |
| FormCache form_cache(web_frame); |
| std::vector<FormData> forms = form_cache.ExtractNewForms(nullptr); |
| ASSERT_EQ(1U, forms.size()); |
| |
| // Get the input element we want to find. |
| WebInputElement input_element = GetInputElementById("firstname"); |
| |
| // Find the form that contains the input element. |
| FormData form; |
| FormFieldData field; |
| EXPECT_TRUE(FindFormAndFieldForFormControlElement(input_element, nullptr, |
| &form, &field)); |
| EXPECT_EQ(GetCanonicalOriginForDocument(web_frame->GetDocument()), |
| form.url); |
| if (!unowned) { |
| EXPECT_EQ(ASCIIToUTF16("TestForm"), form.name); |
| EXPECT_EQ(GURL("http://abc.com"), form.action); |
| } |
| |
| const std::vector<FormFieldData>& fields = form.fields; |
| ASSERT_EQ(3U, fields.size()); |
| |
| FormFieldData expected; |
| expected.form_control_type = "text"; |
| |
| expected.id_attribute = ASCIIToUTF16("firstname"); |
| expected.name = expected.id_attribute; |
| expected.max_length = 5; |
| expected.is_autofilled = false; |
| EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[0]); |
| |
| expected.id_attribute = ASCIIToUTF16("lastname"); |
| expected.name = expected.id_attribute; |
| expected.max_length = 7; |
| expected.is_autofilled = false; |
| EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[1]); |
| |
| expected.id_attribute = ASCIIToUTF16("email"); |
| expected.name = expected.id_attribute; |
| expected.max_length = 9; |
| expected.is_autofilled = false; |
| EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[2]); |
| |
| // Fill the form. |
| form.fields[0].value = ASCIIToUTF16("Brother"); |
| form.fields[1].value = ASCIIToUTF16("Jonathan"); |
| form.fields[2].value = ASCIIToUTF16("brotherj@example.com"); |
| form.fields[0].is_autofilled = true; |
| form.fields[1].is_autofilled = true; |
| form.fields[2].is_autofilled = true; |
| FillForm(form, input_element); |
| |
| // Find the newly-filled form that contains the input element. |
| FormData form2; |
| FormFieldData field2; |
| EXPECT_TRUE(FindFormAndFieldForFormControlElement(input_element, nullptr, |
| &form2, &field2)); |
| EXPECT_EQ(GetCanonicalOriginForDocument(web_frame->GetDocument()), |
| form2.url); |
| if (!unowned) { |
| EXPECT_EQ(ASCIIToUTF16("TestForm"), form2.name); |
| EXPECT_EQ(GURL("http://abc.com"), form2.action); |
| } |
| |
| const std::vector<FormFieldData>& fields2 = form2.fields; |
| ASSERT_EQ(3U, fields2.size()); |
| |
| expected.form_control_type = "text"; |
| |
| expected.id_attribute = ASCIIToUTF16("firstname"); |
| expected.name = expected.id_attribute; |
| expected.value = ASCIIToUTF16("Broth"); |
| expected.max_length = 5; |
| expected.is_autofilled = true; |
| EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields2[0]); |
| |
| expected.id_attribute = ASCIIToUTF16("lastname"); |
| expected.name = expected.id_attribute; |
| expected.value = ASCIIToUTF16("Jonatha"); |
| expected.max_length = 7; |
| expected.is_autofilled = true; |
| EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields2[1]); |
| |
| expected.id_attribute = ASCIIToUTF16("email"); |
| expected.name = expected.id_attribute; |
| expected.value = ASCIIToUTF16("brotherj@"); |
| expected.max_length = 9; |
| expected.is_autofilled = true; |
| EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields2[2]); |
| } |
| |
| void TestFillFormNegativeMaxLength(const char* html, bool unowned) { |
| LoadHTML(html); |
| WebLocalFrame* web_frame = GetMainFrame(); |
| ASSERT_NE(nullptr, web_frame); |
| |
| FormCache form_cache(web_frame); |
| std::vector<FormData> forms = form_cache.ExtractNewForms(nullptr); |
| ASSERT_EQ(1U, forms.size()); |
| |
| // Get the input element we want to find. |
| WebInputElement input_element = GetInputElementById("firstname"); |
| |
| // Find the form that contains the input element. |
| FormData form; |
| FormFieldData field; |
| EXPECT_TRUE(FindFormAndFieldForFormControlElement(input_element, nullptr, |
| &form, &field)); |
| EXPECT_EQ(GetCanonicalOriginForDocument(web_frame->GetDocument()), |
| form.url); |
| if (!unowned) { |
| EXPECT_EQ(ASCIIToUTF16("TestForm"), form.name); |
| EXPECT_EQ(GURL("http://abc.com"), form.action); |
| } |
| |
| const std::vector<FormFieldData>& fields = form.fields; |
| ASSERT_EQ(3U, fields.size()); |
| |
| FormFieldData expected; |
| expected.form_control_type = "text"; |
| expected.max_length = WebInputElement::DefaultMaxLength(); |
| |
| expected.id_attribute = ASCIIToUTF16("firstname"); |
| expected.name = expected.id_attribute; |
| EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[0]); |
| |
| expected.id_attribute = ASCIIToUTF16("lastname"); |
| expected.name = expected.id_attribute; |
| EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[1]); |
| |
| expected.id_attribute = ASCIIToUTF16("email"); |
| expected.name = expected.id_attribute; |
| EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[2]); |
| |
| // Fill the form. |
| form.fields[0].value = ASCIIToUTF16("Brother"); |
| form.fields[1].value = ASCIIToUTF16("Jonathan"); |
| form.fields[2].value = ASCIIToUTF16("brotherj@example.com"); |
| FillForm(form, input_element); |
| |
| // Find the newly-filled form that contains the input element. |
| FormData form2; |
| FormFieldData field2; |
| EXPECT_TRUE(FindFormAndFieldForFormControlElement(input_element, nullptr, |
| &form2, &field2)); |
| EXPECT_EQ(GetCanonicalOriginForDocument(web_frame->GetDocument()), |
| form2.url); |
| if (!unowned) { |
| EXPECT_EQ(ASCIIToUTF16("TestForm"), form2.name); |
| EXPECT_EQ(GURL("http://abc.com"), form2.action); |
| } |
| |
| const std::vector<FormFieldData>& fields2 = form2.fields; |
| ASSERT_EQ(3U, fields2.size()); |
| |
| expected.id_attribute = ASCIIToUTF16("firstname"); |
| expected.name = expected.id_attribute; |
| expected.value = ASCIIToUTF16("Brother"); |
| EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[0]); |
| |
| expected.id_attribute = ASCIIToUTF16("lastname"); |
| expected.name = expected.id_attribute; |
| expected.value = ASCIIToUTF16("Jonathan"); |
| EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[1]); |
| |
| expected.id_attribute = ASCIIToUTF16("email"); |
| expected.name = expected.id_attribute; |
| expected.value = ASCIIToUTF16("brotherj@example.com"); |
| EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[2]); |
| } |
| |
| void TestFillFormEmptyName(const char* html, bool unowned) { |
| LoadHTML(html); |
| WebLocalFrame* web_frame = GetMainFrame(); |
| ASSERT_NE(nullptr, web_frame); |
| |
| FormCache form_cache(web_frame); |
| std::vector<FormData> forms = form_cache.ExtractNewForms(nullptr); |
| ASSERT_EQ(1U, forms.size()); |
| |
| // Get the input element we want to find. |
| WebInputElement input_element = GetInputElementById("firstname"); |
| |
| // Find the form that contains the input element. |
| FormData form; |
| FormFieldData field; |
| EXPECT_TRUE(FindFormAndFieldForFormControlElement(input_element, nullptr, |
| &form, &field)); |
| EXPECT_EQ(GetCanonicalOriginForDocument(web_frame->GetDocument()), |
| form.url); |
| if (!unowned) { |
| EXPECT_EQ(ASCIIToUTF16("TestForm"), form.name); |
| EXPECT_EQ(GURL("http://abc.com"), form.action); |
| } |
| |
| const std::vector<FormFieldData>& fields = form.fields; |
| ASSERT_EQ(3U, fields.size()); |
| |
| FormFieldData expected; |
| expected.form_control_type = "text"; |
| expected.max_length = WebInputElement::DefaultMaxLength(); |
| |
| expected.id_attribute = ASCIIToUTF16("firstname"); |
| expected.name = expected.id_attribute; |
| EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[0]); |
| |
| expected.id_attribute = ASCIIToUTF16("lastname"); |
| expected.name = expected.id_attribute; |
| EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[1]); |
| |
| expected.id_attribute = ASCIIToUTF16("email"); |
| expected.name = expected.id_attribute; |
| EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[2]); |
| |
| // Fill the form. |
| form.fields[0].value = ASCIIToUTF16("Wyatt"); |
| form.fields[1].value = ASCIIToUTF16("Earp"); |
| form.fields[2].value = ASCIIToUTF16("wyatt@example.com"); |
| FillForm(form, input_element); |
| |
| // Find the newly-filled form that contains the input element. |
| FormData form2; |
| FormFieldData field2; |
| EXPECT_TRUE(FindFormAndFieldForFormControlElement(input_element, nullptr, |
| &form2, &field2)); |
| EXPECT_EQ(GetCanonicalOriginForDocument(web_frame->GetDocument()), |
| form2.url); |
| if (!unowned) { |
| EXPECT_EQ(ASCIIToUTF16("TestForm"), form2.name); |
| EXPECT_EQ(GURL("http://abc.com"), form2.action); |
| } |
| |
| const std::vector<FormFieldData>& fields2 = form2.fields; |
| ASSERT_EQ(3U, fields2.size()); |
| |
| expected.form_control_type = "text"; |
| expected.max_length = WebInputElement::DefaultMaxLength(); |
| |
| expected.id_attribute = ASCIIToUTF16("firstname"); |
| expected.name = expected.id_attribute; |
| expected.value = ASCIIToUTF16("Wyatt"); |
| EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[0]); |
| |
| expected.id_attribute = ASCIIToUTF16("lastname"); |
| expected.name = expected.id_attribute; |
| expected.value = ASCIIToUTF16("Earp"); |
| EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[1]); |
| |
| expected.id_attribute = ASCIIToUTF16("email"); |
| expected.name = expected.id_attribute; |
| expected.value = ASCIIToUTF16("wyatt@example.com"); |
| EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[2]); |
| } |
| |
| void TestFillFormEmptyFormNames(const char* html, bool unowned) { |
| LoadHTML(html); |
| WebLocalFrame* web_frame = GetMainFrame(); |
| ASSERT_NE(nullptr, web_frame); |
| |
| FormCache form_cache(web_frame); |
| std::vector<FormData> forms = form_cache.ExtractNewForms(nullptr); |
| const size_t expected_size = unowned ? 1 : 2; |
| ASSERT_EQ(expected_size, forms.size()); |
| |
| // Get the input element we want to find. |
| WebInputElement input_element = GetInputElementById("apple"); |
| |
| // Find the form that contains the input element. |
| FormData form; |
| FormFieldData field; |
| EXPECT_TRUE(FindFormAndFieldForFormControlElement(input_element, nullptr, |
| &form, &field)); |
| EXPECT_EQ(GetCanonicalOriginForDocument(web_frame->GetDocument()), |
| form.url); |
| if (!unowned) { |
| EXPECT_TRUE(form.name.empty()); |
| EXPECT_EQ(GURL("http://abc.com"), form.action); |
| } |
| |
| const std::vector<FormFieldData>& fields = form.fields; |
| const size_t unowned_offset = unowned ? 3 : 0; |
| ASSERT_EQ(unowned_offset + 3, fields.size()); |
| |
| FormFieldData expected; |
| expected.form_control_type = "text"; |
| expected.max_length = WebInputElement::DefaultMaxLength(); |
| |
| expected.id_attribute = ASCIIToUTF16("apple"); |
| expected.name = expected.id_attribute; |
| expected.is_autofilled = false; |
| EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[unowned_offset]); |
| |
| expected.id_attribute = ASCIIToUTF16("banana"); |
| expected.name = expected.id_attribute; |
| expected.is_autofilled = false; |
| EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[unowned_offset + 1]); |
| |
| expected.id_attribute = ASCIIToUTF16("cantelope"); |
| expected.name = expected.id_attribute; |
| expected.is_autofilled = false; |
| EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[unowned_offset + 2]); |
| |
| // Fill the form. |
| form.fields[unowned_offset + 0].value = ASCIIToUTF16("Red"); |
| form.fields[unowned_offset + 1].value = ASCIIToUTF16("Yellow"); |
| form.fields[unowned_offset + 2].value = ASCIIToUTF16("Also Yellow"); |
| form.fields[unowned_offset + 0].is_autofilled = true; |
| form.fields[unowned_offset + 1].is_autofilled = true; |
| form.fields[unowned_offset + 2].is_autofilled = true; |
| FillForm(form, input_element); |
| |
| // Find the newly-filled form that contains the input element. |
| FormData form2; |
| FormFieldData field2; |
| EXPECT_TRUE(FindFormAndFieldForFormControlElement(input_element, nullptr, |
| &form2, &field2)); |
| EXPECT_EQ(GetCanonicalOriginForDocument(web_frame->GetDocument()), |
| form2.url); |
| if (!unowned) { |
| EXPECT_TRUE(form2.name.empty()); |
| EXPECT_EQ(GURL("http://abc.com"), form2.action); |
| } |
| |
| const std::vector<FormFieldData>& fields2 = form2.fields; |
| ASSERT_EQ(unowned_offset + 3, fields2.size()); |
| |
| expected.id_attribute = ASCIIToUTF16("apple"); |
| expected.name = expected.id_attribute; |
| expected.value = ASCIIToUTF16("Red"); |
| expected.is_autofilled = true; |
| EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields2[unowned_offset + 0]); |
| |
| expected.id_attribute = ASCIIToUTF16("banana"); |
| expected.name = expected.id_attribute; |
| expected.value = ASCIIToUTF16("Yellow"); |
| expected.is_autofilled = true; |
| EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields2[unowned_offset + 1]); |
| |
| expected.id_attribute = ASCIIToUTF16("cantelope"); |
| expected.name = expected.id_attribute; |
| expected.value = ASCIIToUTF16("Also Yellow"); |
| expected.is_autofilled = true; |
| EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields2[unowned_offset + 2]); |
| } |
| |
| void TestFillFormNonEmptyField(const char* html, |
| bool unowned, |
| const char* initial_lastname, |
| const char* initial_email, |
| const char* placeholder_firstname, |
| const char* placeholder_lastname, |
| const char* placeholder_email) { |
| LoadHTML(html); |
| WebLocalFrame* web_frame = GetMainFrame(); |
| ASSERT_NE(nullptr, web_frame); |
| |
| FormCache form_cache(web_frame); |
| std::vector<FormData> forms = form_cache.ExtractNewForms(nullptr); |
| ASSERT_EQ(1U, forms.size()); |
| |
| // Get the input element we want to find. |
| WebInputElement input_element = GetInputElementById("firstname"); |
| |
| // Simulate typing by modifying the field value. |
| input_element.SetValue(WebString::FromASCII("Wy")); |
| |
| // Find the form that contains the input element. |
| FormData form; |
| FormFieldData field; |
| EXPECT_TRUE(FindFormAndFieldForFormControlElement(input_element, nullptr, |
| &form, &field)); |
| EXPECT_EQ(GetCanonicalOriginForDocument(web_frame->GetDocument()), |
| form.url); |
| if (!unowned) { |
| EXPECT_EQ(ASCIIToUTF16("TestForm"), form.name); |
| EXPECT_EQ(GURL("http://abc.com"), form.action); |
| } |
| |
| const std::vector<FormFieldData>& fields = form.fields; |
| ASSERT_EQ(3U, fields.size()); |
| |
| FormFieldData expected; |
| expected.form_control_type = "text"; |
| expected.max_length = WebInputElement::DefaultMaxLength(); |
| |
| expected.id_attribute = ASCIIToUTF16("firstname"); |
| expected.name = expected.id_attribute; |
| expected.value = ASCIIToUTF16("Wy"); |
| if (placeholder_firstname) { |
| expected.label = ASCIIToUTF16(placeholder_firstname); |
| expected.placeholder = ASCIIToUTF16(placeholder_firstname); |
| } |
| expected.is_autofilled = false; |
| EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[0]); |
| |
| expected.id_attribute = ASCIIToUTF16("lastname"); |
| expected.name = expected.id_attribute; |
| if (initial_lastname) { |
| expected.label = ASCIIToUTF16(initial_lastname); |
| expected.value = ASCIIToUTF16(initial_lastname); |
| } else if (placeholder_lastname) { |
| expected.label = ASCIIToUTF16(placeholder_lastname); |
| expected.placeholder = ASCIIToUTF16(placeholder_lastname); |
| expected.value = ASCIIToUTF16(placeholder_lastname); |
| } else { |
| expected.label.clear(); |
| expected.value.clear(); |
| } |
| expected.is_autofilled = false; |
| EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[1]); |
| |
| expected.id_attribute = ASCIIToUTF16("email"); |
| expected.name = expected.id_attribute; |
| if (initial_email) { |
| expected.label = ASCIIToUTF16(initial_email); |
| expected.value = ASCIIToUTF16(initial_email); |
| } else if (placeholder_email) { |
| expected.label = ASCIIToUTF16(placeholder_email); |
| expected.placeholder = ASCIIToUTF16(placeholder_email); |
| expected.value = ASCIIToUTF16(placeholder_email); |
| } else { |
| expected.label.clear(); |
| expected.value.clear(); |
| } |
| expected.is_autofilled = false; |
| EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[2]); |
| |
| // Preview the form and verify that the cursor position has been updated. |
| form.fields[0].value = ASCIIToUTF16("Wyatt"); |
| form.fields[1].value = ASCIIToUTF16("Earp"); |
| form.fields[2].value = ASCIIToUTF16("wyatt@example.com"); |
| form.fields[0].is_autofilled = true; |
| form.fields[1].is_autofilled = true; |
| form.fields[2].is_autofilled = true; |
| PreviewForm(form, input_element); |
| // The selection should be set after the second character. |
| EXPECT_EQ(2, input_element.SelectionStart()); |
| EXPECT_EQ(2, input_element.SelectionEnd()); |
| |
| // Fill the form. |
| FillForm(form, input_element); |
| |
| // Find the newly-filled form that contains the input element. |
| FormData form2; |
| FormFieldData field2; |
| EXPECT_TRUE(FindFormAndFieldForFormControlElement(input_element, nullptr, |
| &form2, &field2)); |
| EXPECT_EQ(GetCanonicalOriginForDocument(web_frame->GetDocument()), |
| form2.url); |
| if (!unowned) { |
| EXPECT_EQ(ASCIIToUTF16("TestForm"), form2.name); |
| EXPECT_EQ(GURL("http://abc.com"), form2.action); |
| } |
| |
| const std::vector<FormFieldData>& fields2 = form2.fields; |
| ASSERT_EQ(3U, fields2.size()); |
| |
| expected.id_attribute = ASCIIToUTF16("firstname"); |
| expected.name = expected.id_attribute; |
| expected.value = ASCIIToUTF16("Wyatt"); |
| if (placeholder_firstname) { |
| expected.label = ASCIIToUTF16(placeholder_firstname); |
| expected.placeholder = ASCIIToUTF16(placeholder_firstname); |
| } else { |
| expected.label.clear(); |
| expected.placeholder.clear(); |
| } |
| expected.is_autofilled = true; |
| EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields2[0]); |
| |
| expected.id_attribute = ASCIIToUTF16("lastname"); |
| expected.name = expected.id_attribute; |
| expected.value = ASCIIToUTF16("Earp"); |
| if (placeholder_lastname) { |
| expected.label = ASCIIToUTF16(placeholder_lastname); |
| expected.placeholder = ASCIIToUTF16(placeholder_lastname); |
| } else { |
| expected.label.clear(); |
| expected.placeholder.clear(); |
| } |
| expected.is_autofilled = true; |
| EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields2[1]); |
| |
| expected.id_attribute = ASCIIToUTF16("email"); |
| expected.name = expected.id_attribute; |
| expected.value = ASCIIToUTF16("wyatt@example.com"); |
| if (placeholder_email) { |
| expected.label = ASCIIToUTF16(placeholder_email); |
| expected.placeholder = ASCIIToUTF16(placeholder_email); |
| } else { |
| expected.label.clear(); |
| expected.placeholder.clear(); |
| } |
| expected.is_autofilled = true; |
| EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields2[2]); |
| |
| // Verify that the cursor position has been updated. |
| EXPECT_EQ(5, input_element.SelectionStart()); |
| EXPECT_EQ(5, input_element.SelectionEnd()); |
| } |
| |
| void TestFillFormAndModifyValues(const char* html, |
| const char* placeholder_firstname, |
| const char* placeholder_lastname, |
| const char* placeholder_phone, |
| const char* placeholder_creditcard, |
| const char* placeholder_city, |
| const char* placeholder_state) { |
| LoadHTML(html); |
| WebLocalFrame* web_frame = GetMainFrame(); |
| ASSERT_NE(nullptr, web_frame); |
| |
| FormCache form_cache(web_frame); |
| std::vector<FormData> forms = form_cache.ExtractNewForms(nullptr); |
| ASSERT_EQ(1U, forms.size()); |
| |
| // Get the input element we want to find. |
| WebInputElement input_element = GetInputElementById("firstname"); |
| WebFormElement form_element = input_element.Form(); |
| std::vector<WebFormControlElement> control_elements = |
| ExtractAutofillableElementsInForm(form_element); |
| |
| ASSERT_EQ(6U, control_elements.size()); |
| // We now modify the values. |
| // This will be ignored, the string will be sanitized into an empty string. |
| control_elements[0].SetValue(WebString::FromUTF16( |
| base::char16(base::i18n::kLeftToRightMark) + ASCIIToUTF16(" "))); |
| |
| // This will be considered as a value entered by the user. |
| control_elements[1].SetValue(WebString::FromUTF16(ASCIIToUTF16("Earp"))); |
| control_elements[1].SetUserHasEditedTheFieldForTest(); |
| |
| // This will be ignored, the string will be sanitized into an empty string. |
| control_elements[2].SetValue( |
| WebString::FromUTF16(ASCIIToUTF16("(___)-___-____"))); |
| |
| // This will be ignored, the string will be sanitized into an empty string. |
| control_elements[3].SetValue( |
| WebString::FromUTF16(ASCIIToUTF16("____-____-____-____"))); |
| |
| // This will be ignored, because it's injected by the website and not the |
| // user. |
| control_elements[4].SetValue( |
| WebString::FromUTF16(ASCIIToUTF16("Enter your city.."))); |
| |
| control_elements[5].SetValue(WebString::FromUTF16(ASCIIToUTF16("AK"))); |
| control_elements[5].SetUserHasEditedTheFieldForTest(); |
| |
| // Find the form that contains the input element. |
| FormData form; |
| FormFieldData field; |
| EXPECT_TRUE(FindFormAndFieldForFormControlElement(input_element, nullptr, |
| &form, &field)); |
| EXPECT_EQ(GetCanonicalOriginForDocument(web_frame->GetDocument()), |
| form.url); |
| EXPECT_EQ(ASCIIToUTF16("TestForm"), form.name); |
| EXPECT_EQ(GURL("http://abc.com"), form.action); |
| |
| const std::vector<FormFieldData>& fields = form.fields; |
| ASSERT_EQ(6U, fields.size()); |
| |
| // Preview the form and verify that the cursor position has been updated. |
| form.fields[0].value = ASCIIToUTF16("Wyatt"); |
| form.fields[1].value = ASCIIToUTF16("Earpagus"); |
| form.fields[2].value = ASCIIToUTF16("888-123-4567"); |
| form.fields[3].value = ASCIIToUTF16("1111-2222-3333-4444"); |
| form.fields[4].value = ASCIIToUTF16("Montreal"); |
| form.fields[5].value = ASCIIToUTF16("AA"); |
| form.fields[0].is_autofilled = true; |
| form.fields[1].is_autofilled = true; |
| form.fields[2].is_autofilled = true; |
| form.fields[3].is_autofilled = true; |
| form.fields[4].is_autofilled = true; |
| form.fields[5].is_autofilled = true; |
| PreviewForm(form, input_element); |
| // The selection should be set after the fifth character. |
| EXPECT_EQ(5, input_element.SelectionStart()); |
| EXPECT_EQ(5, input_element.SelectionEnd()); |
| |
| // Fill the form. |
| FillForm(form, input_element); |
| |
| // Find the newly-filled form that contains the input element. |
| FormData form2; |
| FormFieldData field2; |
| EXPECT_TRUE(FindFormAndFieldForFormControlElement(input_element, nullptr, |
| &form2, &field2)); |
| EXPECT_EQ(GetCanonicalOriginForDocument(web_frame->GetDocument()), |
| form2.url); |
| EXPECT_EQ(ASCIIToUTF16("TestForm"), form2.name); |
| EXPECT_EQ(GURL("http://abc.com"), form2.action); |
| |
| const std::vector<FormFieldData>& fields2 = form2.fields; |
| ASSERT_EQ(6U, fields2.size()); |
| |
| FormFieldData expected; |
| expected.form_control_type = "text"; |
| expected.max_length = WebInputElement::DefaultMaxLength(); |
| |
| expected.id_attribute = ASCIIToUTF16("firstname"); |
| expected.name = expected.id_attribute; |
| expected.value = ASCIIToUTF16("Wyatt"); |
| if (placeholder_firstname) { |
| expected.label = ASCIIToUTF16(placeholder_firstname); |
| expected.placeholder = ASCIIToUTF16(placeholder_firstname); |
| } else { |
| expected.label.clear(); |
| expected.placeholder.clear(); |
| } |
| expected.is_autofilled = true; |
| EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields2[0]); |
| |
| // The last name field is not filled, because there is a value in it. |
| expected.id_attribute = ASCIIToUTF16("lastname"); |
| expected.name = expected.id_attribute; |
| expected.value = ASCIIToUTF16("Earp"); |
| if (placeholder_lastname) { |
| expected.label = ASCIIToUTF16(placeholder_lastname); |
| expected.placeholder = ASCIIToUTF16(placeholder_lastname); |
| } else { |
| expected.label.clear(); |
| expected.placeholder.clear(); |
| } |
| expected.is_autofilled = false; |
| EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields2[1]); |
| |
| expected.id_attribute = ASCIIToUTF16("phone"); |
| expected.name = expected.id_attribute; |
| expected.value = ASCIIToUTF16("888-123-4567"); |
| if (placeholder_phone) { |
| expected.label = ASCIIToUTF16(placeholder_phone); |
| expected.placeholder = ASCIIToUTF16(placeholder_phone); |
| } else { |
| expected.label.clear(); |
| expected.placeholder.clear(); |
| } |
| expected.is_autofilled = true; |
| EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields2[2]); |
| |
| expected.id_attribute = ASCIIToUTF16("cc"); |
| expected.name = expected.id_attribute; |
| expected.value = ASCIIToUTF16("1111-2222-3333-4444"); |
| if (placeholder_creditcard) { |
| expected.label = ASCIIToUTF16(placeholder_creditcard); |
| expected.placeholder = ASCIIToUTF16(placeholder_creditcard); |
| } else { |
| expected.label.clear(); |
| expected.placeholder.clear(); |
| } |
| expected.is_autofilled = true; |
| EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields2[3]); |
| |
| expected.id_attribute = ASCIIToUTF16("city"); |
| expected.name = expected.id_attribute; |
| expected.value = ASCIIToUTF16("Montreal"); |
| if (placeholder_city) { |
| expected.label = ASCIIToUTF16(placeholder_city); |
| expected.placeholder = ASCIIToUTF16(placeholder_city); |
| } else { |
| expected.label.clear(); |
| expected.placeholder.clear(); |
| } |
| expected.is_autofilled = true; |
| EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields2[4]); |
| |
| expected.form_control_type = "select-one"; |
| expected.id_attribute = ASCIIToUTF16("state"); |
| expected.name_attribute = ASCIIToUTF16("state"); |
| expected.name = expected.name_attribute; |
| expected.value = ASCIIToUTF16("AA"); |
| if (placeholder_state) { |
| expected.label = ASCIIToUTF16(placeholder_state); |
| expected.placeholder = ASCIIToUTF16(placeholder_state); |
| } else { |
| expected.label.clear(); |
| expected.placeholder.clear(); |
| } |
| expected.is_autofilled = true; |
| expected.max_length = 0; |
| EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields2[5]); |
| |
| // Verify that the cursor position has been updated. |
| EXPECT_EQ(5, input_element.SelectionStart()); |
| EXPECT_EQ(5, input_element.SelectionEnd()); |
| } |
| |
| void TestFillFormWithPlaceholderValues(const char* html, |
| const char* placeholder_firstname, |
| const char* placeholder_lastname, |
| const char* placeholder_email) { |
| LoadHTML(html); |
| WebLocalFrame* web_frame = GetMainFrame(); |
| ASSERT_NE(nullptr, web_frame); |
| |
| FormCache form_cache(web_frame); |
| std::vector<FormData> forms = form_cache.ExtractNewForms(nullptr); |
| ASSERT_EQ(1U, forms.size()); |
| |
| // Get the input element we want to find. |
| WebInputElement input_element = GetInputElementById("firstname"); |
| WebFormElement form_element = input_element.Form(); |
| std::vector<WebFormControlElement> control_elements = |
| ExtractAutofillableElementsInForm(form_element); |
| |
| ASSERT_EQ(3U, control_elements.size()); |
| // We now modify the values. |
| // These will be ignored, because it's (case insensitively) equal to the |
| // placeholder. |
| control_elements[0].SetValue( |
| WebString::FromUTF16(base::char16(base::i18n::kLeftToRightMark) + |
| ASCIIToUTF16("first name"))); |
| control_elements[1].SetValue( |
| WebString::FromUTF16(ASCIIToUTF16("LAST NAME"))); |
| // This will be considered. |
| control_elements[2].SetValue( |
| WebString::FromUTF16(ASCIIToUTF16("john@smith.com"))); |
| // Find the form that contains the input element. |
| FormData form; |
| FormFieldData field; |
| EXPECT_TRUE(FindFormAndFieldForFormControlElement(input_element, nullptr, |
| &form, &field)); |
| EXPECT_EQ(GetCanonicalOriginForDocument(web_frame->GetDocument()), |
| form.url); |
| EXPECT_EQ(ASCIIToUTF16("TestForm"), form.name); |
| EXPECT_EQ(GURL("http://abc.com"), form.action); |
| |
| const std::vector<FormFieldData>& fields = form.fields; |
| ASSERT_EQ(3U, fields.size()); |
| |
| // Preview the form and verify that the cursor position has been updated. |
| form.fields[0].value = ASCIIToUTF16("Wyatt"); |
| form.fields[1].value = ASCIIToUTF16("Earpagus"); |
| form.fields[2].value = ASCIIToUTF16("susan@smith.com"); |
| form.fields[0].is_autofilled = true; |
| form.fields[1].is_autofilled = true; |
| form.fields[2].is_autofilled = false; |
| PreviewForm(form, input_element); |
| // The selection should be set after the fifth character. |
| EXPECT_EQ(5, input_element.SelectionStart()); |
| EXPECT_EQ(5, input_element.SelectionEnd()); |
| |
| // Fill the form. |
| FillForm(form, input_element); |
| |
| // Find the newly-filled form that contains the input element. |
| FormData form2; |
| FormFieldData field2; |
| EXPECT_TRUE(FindFormAndFieldForFormControlElement(input_element, nullptr, |
| &form2, &field2)); |
| EXPECT_EQ(GetCanonicalOriginForDocument(web_frame->GetDocument()), |
| form2.url); |
| EXPECT_EQ(ASCIIToUTF16("TestForm"), form2.name); |
| EXPECT_EQ(GURL("http://abc.com"), form2.action); |
| |
| const std::vector<FormFieldData>& fields2 = form2.fields; |
| ASSERT_EQ(3U, fields2.size()); |
| |
| FormFieldData expected; |
| expected.form_control_type = "text"; |
| expected.max_length = WebInputElement::DefaultMaxLength(); |
| |
| expected.id_attribute = ASCIIToUTF16("firstname"); |
| expected.name = expected.id_attribute; |
| expected.value = ASCIIToUTF16("Wyatt"); |
| if (placeholder_firstname) { |
| expected.label = ASCIIToUTF16(placeholder_firstname); |
| expected.placeholder = ASCIIToUTF16(placeholder_firstname); |
| } else { |
| expected.label.clear(); |
| expected.placeholder.clear(); |
| } |
| expected.is_autofilled = true; |
| EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields2[0]); |
| |
| expected.id_attribute = ASCIIToUTF16("lastname"); |
| expected.name = expected.id_attribute; |
| expected.value = ASCIIToUTF16("Earpagus"); |
| if (placeholder_lastname) { |
| expected.label = ASCIIToUTF16(placeholder_lastname); |
| expected.placeholder = ASCIIToUTF16(placeholder_lastname); |
| } else { |
| expected.label.clear(); |
| expected.placeholder.clear(); |
| } |
| expected.is_autofilled = true; |
| EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields2[1]); |
| |
| // The email field is not filled, because there is a value in it. |
| expected.id_attribute = ASCIIToUTF16("email"); |
| expected.name = expected.id_attribute; |
| expected.value = ASCIIToUTF16("john@smith.com"); |
| if (placeholder_email) { |
| expected.label = ASCIIToUTF16(placeholder_email); |
| expected.placeholder = ASCIIToUTF16(placeholder_email); |
| } else { |
| expected.label.clear(); |
| expected.placeholder.clear(); |
| } |
| expected.is_autofilled = false; |
| EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields2[2]); |
| |
| // Verify that the cursor position has been updated. |
| EXPECT_EQ(5, input_element.SelectionStart()); |
| EXPECT_EQ(5, input_element.SelectionEnd()); |
| } |
| |
| void TestFillFormAndModifyInitiatingValue(const char* html, |
| const char* placeholder_creditcard, |
| const char* placeholder_expiration, |
| const char* placeholder_name) { |
| LoadHTML(html); |
| WebLocalFrame* web_frame = GetMainFrame(); |
| ASSERT_NE(nullptr, web_frame); |
| |
| FormCache form_cache(web_frame); |
| std::vector<FormData> forms = form_cache.ExtractNewForms(nullptr); |
| ASSERT_EQ(1U, forms.size()); |
| |
| // Get the input element we want to find. |
| WebInputElement input_element = GetInputElementById("cc"); |
| WebFormElement form_element = input_element.Form(); |
| std::vector<WebFormControlElement> control_elements = |
| ExtractAutofillableElementsInForm(form_element); |
| |
| ASSERT_EQ(3U, control_elements.size()); |
| // We now modify the values. |
| // This will be ignored. |
| control_elements[0].SetValue( |
| WebString::FromUTF16(ASCIIToUTF16("____-____-____-____"))); |
| // This will be ignored. |
| control_elements[1].SetValue(WebString::FromUTF16(ASCIIToUTF16("____/__"))); |
| control_elements[2].SetValue( |
| WebString::FromUTF16(ASCIIToUTF16("John Smith"))); |
| control_elements[2].SetUserHasEditedTheFieldForTest(); |
| |
| // Find the form that contains the input element. |
| FormData form; |
| FormFieldData field; |
| EXPECT_TRUE(FindFormAndFieldForFormControlElement(input_element, nullptr, |
| &form, &field)); |
| EXPECT_EQ(GetCanonicalOriginForDocument(web_frame->GetDocument()), |
| form.url); |
| EXPECT_EQ(ASCIIToUTF16("TestForm"), form.name); |
| EXPECT_EQ(GURL("http://abc.com"), form.action); |
| |
| const std::vector<FormFieldData>& fields = form.fields; |
| ASSERT_EQ(3U, fields.size()); |
| |
| // Preview the form and verify that the cursor position has been updated. |
| form.fields[0].value = ASCIIToUTF16("1111-2222-3333-4444"); |
| form.fields[1].value = ASCIIToUTF16("03/2030"); |
| form.fields[2].value = ASCIIToUTF16("Susan Smith"); |
| form.fields[0].is_autofilled = true; |
| form.fields[1].is_autofilled = true; |
| form.fields[2].is_autofilled = true; |
| PreviewForm(form, input_element); |
| // The selection should be set after the 19th character. |
| EXPECT_EQ(19, input_element.SelectionStart()); |
| EXPECT_EQ(19, input_element.SelectionEnd()); |
| |
| // Fill the form. |
| FillForm(form, input_element); |
| |
| // Find the newly-filled form that contains the input element. |
| FormData form2; |
| FormFieldData field2; |
| EXPECT_TRUE(FindFormAndFieldForFormControlElement(input_element, nullptr, |
| &form2, &field2)); |
| EXPECT_EQ(GetCanonicalOriginForDocument(web_frame->GetDocument()), |
| form2.url); |
| EXPECT_EQ(ASCIIToUTF16("TestForm"), form2.name); |
| EXPECT_EQ(GURL("http://abc.com"), form2.action); |
| |
| const std::vector<FormFieldData>& fields2 = form2.fields; |
| ASSERT_EQ(3U, fields2.size()); |
| |
| FormFieldData expected; |
| expected.form_control_type = "text"; |
| expected.max_length = WebInputElement::DefaultMaxLength(); |
| |
| expected.id_attribute = ASCIIToUTF16("cc"); |
| expected.name = expected.id_attribute; |
| expected.value = ASCIIToUTF16("1111-2222-3333-4444"); |
| if (placeholder_creditcard) { |
| expected.label = ASCIIToUTF16(placeholder_creditcard); |
| expected.placeholder = ASCIIToUTF16(placeholder_creditcard); |
| } else { |
| expected.label.clear(); |
| expected.placeholder.clear(); |
| } |
| expected.is_autofilled = true; |
| EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields2[0]); |
| |
| expected.id_attribute = ASCIIToUTF16("expiration_date"); |
| expected.name = expected.id_attribute; |
| expected.value = ASCIIToUTF16("03/2030"); |
| if (placeholder_expiration) { |
| expected.label = ASCIIToUTF16(placeholder_expiration); |
| expected.placeholder = ASCIIToUTF16(placeholder_expiration); |
| } else { |
| expected.label.clear(); |
| expected.placeholder.clear(); |
| } |
| expected.is_autofilled = true; |
| EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields2[1]); |
| |
| expected.id_attribute = ASCIIToUTF16("name"); |
| expected.name = expected.id_attribute; |
| expected.value = ASCIIToUTF16("John Smith"); |
| if (placeholder_name) { |
| expected.label = ASCIIToUTF16(placeholder_name); |
| expected.placeholder = ASCIIToUTF16(placeholder_name); |
| } else { |
| expected.label.clear(); |
| expected.placeholder.clear(); |
| } |
| expected.is_autofilled = false; |
| EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields2[2]); |
| |
| // Verify that the cursor position has been updated. |
| EXPECT_EQ(19, input_element.SelectionStart()); |
| EXPECT_EQ(19, input_element.SelectionEnd()); |
| } |
| |
| void TestFillFormJSModifiesUserInputValue(const char* html, |
| const char* placeholder_creditcard, |
| const char* placeholder_expiration, |
| const char* placeholder_name) { |
| LoadHTML(html); |
| WebLocalFrame* web_frame = GetMainFrame(); |
| ASSERT_NE(nullptr, web_frame); |
| |
| FormCache form_cache(web_frame); |
| std::vector<FormData> forms = form_cache.ExtractNewForms(nullptr); |
| ASSERT_EQ(1U, forms.size()); |
| |
| // Get the input element we want to find. |
| WebInputElement input_element = GetInputElementById("cc"); |
| WebFormElement form_element = input_element.Form(); |
| std::vector<WebFormControlElement> control_elements = |
| ExtractAutofillableElementsInForm(form_element); |
| |
| ASSERT_EQ(3U, control_elements.size()); |
| // We now modify the values. |
| // This will be ignored. |
| control_elements[0].SetValue( |
| WebString::FromUTF16(ASCIIToUTF16("____-____-____-____"))); |
| // This will be ignored. |
| control_elements[1].SetValue(WebString::FromUTF16(ASCIIToUTF16("____/__"))); |
| control_elements[2].SetValue( |
| WebString::FromUTF16(ASCIIToUTF16("john smith"))); |
| control_elements[2].SetUserHasEditedTheFieldForTest(); |
| |
| // Sometimes the JS modifies the value entered by the user. |
| ExecuteJavaScriptForTests( |
| "document.getElementById('name').value = 'John Smith';"); |
| |
| // Find the form that contains the input element. |
| FormData form; |
| FormFieldData field; |
| EXPECT_TRUE(FindFormAndFieldForFormControlElement(input_element, nullptr, |
| &form, &field)); |
| EXPECT_EQ(GetCanonicalOriginForDocument(web_frame->GetDocument()), |
| form.url); |
| EXPECT_EQ(ASCIIToUTF16("TestForm"), form.name); |
| EXPECT_EQ(GURL("http://abc.com"), form.action); |
| |
| const std::vector<FormFieldData>& fields = form.fields; |
| ASSERT_EQ(3U, fields.size()); |
| |
| // Preview the form and verify that the cursor position has been updated. |
| form.fields[0].value = ASCIIToUTF16("1111-2222-3333-4444"); |
| form.fields[1].value = ASCIIToUTF16("03/2030"); |
| form.fields[2].value = ASCIIToUTF16("Susan Smith"); |
| form.fields[0].is_autofilled = true; |
| form.fields[1].is_autofilled = true; |
| form.fields[2].is_autofilled = true; |
| PreviewForm(form, input_element); |
| // The selection should be set after the 19th character. |
| EXPECT_EQ(19, input_element.SelectionStart()); |
| EXPECT_EQ(19, input_element.SelectionEnd()); |
| |
| // Fill the form. |
| FillForm(form, input_element); |
| |
| // Find the newly-filled form that contains the input element. |
| FormData form2; |
| FormFieldData field2; |
| EXPECT_TRUE(FindFormAndFieldForFormControlElement(input_element, nullptr, |
| &form2, &field2)); |
| EXPECT_EQ(GetCanonicalOriginForDocument(web_frame->GetDocument()), |
| form2.url); |
| EXPECT_EQ(ASCIIToUTF16("TestForm"), form2.name); |
| EXPECT_EQ(GURL("http://abc.com"), form2.action); |
| |
| const std::vector<FormFieldData>& fields2 = form2.fields; |
| ASSERT_EQ(3U, fields2.size()); |
| |
| FormFieldData expected; |
| expected.form_control_type = "text"; |
| expected.max_length = WebInputElement::DefaultMaxLength(); |
| |
| expected.id_attribute = ASCIIToUTF16("cc"); |
| expected.name = expected.id_attribute; |
| expected.value = ASCIIToUTF16("1111-2222-3333-4444"); |
| if (placeholder_creditcard) { |
| expected.label = ASCIIToUTF16(placeholder_creditcard); |
| expected.placeholder = ASCIIToUTF16(placeholder_creditcard); |
| } else { |
| expected.label.clear(); |
| expected.placeholder.clear(); |
| } |
| expected.is_autofilled = true; |
| EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields2[0]); |
| |
| expected.id_attribute = ASCIIToUTF16("expiration_date"); |
| expected.name = expected.id_attribute; |
| expected.value = ASCIIToUTF16("03/2030"); |
| if (placeholder_expiration) { |
| expected.label = ASCIIToUTF16(placeholder_expiration); |
| expected.placeholder = ASCIIToUTF16(placeholder_expiration); |
| } else { |
| expected.label.clear(); |
| expected.placeholder.clear(); |
| } |
| expected.is_autofilled = true; |
| EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields2[1]); |
| |
| expected.id_attribute = ASCIIToUTF16("name"); |
| expected.name = expected.id_attribute; |
| expected.value = ASCIIToUTF16("John Smith"); |
| if (placeholder_name) { |
| expected.label = ASCIIToUTF16(placeholder_name); |
| expected.placeholder = ASCIIToUTF16(placeholder_name); |
| } else { |
| expected.label.clear(); |
| expected.placeholder.clear(); |
| } |
| expected.is_autofilled = false; |
| EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields2[2]); |
| |
| // Verify that the cursor position has been updated. |
| EXPECT_EQ(19, input_element.SelectionStart()); |
| EXPECT_EQ(19, input_element.SelectionEnd()); |
| } |
| |
| void TestClearSectionWithNode(const char* html, bool unowned) { |
| LoadHTML(html); |
| WebLocalFrame* web_frame = GetMainFrame(); |
| ASSERT_NE(nullptr, web_frame); |
| |
| FormCache form_cache(web_frame); |
| std::vector<FormData> forms = form_cache.ExtractNewForms(nullptr); |
| ASSERT_EQ(1U, forms.size()); |
| |
| // Set the auto-filled attribute. |
| WebInputElement firstname = GetInputElementById("firstname"); |
| firstname.SetAutofillState(WebAutofillState::kAutofilled); |
| WebInputElement lastname = GetInputElementById("lastname"); |
| lastname.SetAutofillState(WebAutofillState::kAutofilled); |
| WebInputElement month = GetInputElementById("month"); |
| month.SetAutofillState(WebAutofillState::kAutofilled); |
| WebFormControlElement textarea = GetFormControlElementById("textarea"); |
| textarea.SetAutofillState(WebAutofillState::kAutofilled); |
| |
| // Set the value of the disabled text input element. |
| WebInputElement notenabled = GetInputElementById("notenabled"); |
| notenabled.SetValue(WebString::FromUTF8("no clear")); |
| |
| // Clear the form. |
| EXPECT_TRUE(form_cache.ClearSectionWithElement(firstname)); |
| |
| // Verify that the auto-filled attribute has been turned off. |
| EXPECT_FALSE(firstname.IsAutofilled()); |
| |
| // Verify the form is cleared. |
| FormData form; |
| FormFieldData field; |
| EXPECT_TRUE(FindFormAndFieldForFormControlElement(firstname, nullptr, &form, |
| &field)); |
| EXPECT_EQ(GetCanonicalOriginForDocument(web_frame->GetDocument()), |
| form.url); |
| EXPECT_FALSE(form.url.is_empty()); |
| if (!unowned) { |
| EXPECT_EQ(ASCIIToUTF16("TestForm"), form.name); |
| EXPECT_EQ(GURL("http://abc.com"), form.action); |
| } |
| |
| const std::vector<FormFieldData>& fields = form.fields; |
| ASSERT_EQ(9U, fields.size()); |
| |
| FormFieldData expected; |
| expected.form_control_type = "text"; |
| expected.max_length = WebInputElement::DefaultMaxLength(); |
| |
| expected.id_attribute = ASCIIToUTF16("firstname"); |
| expected.name = expected.id_attribute; |
| expected.value.clear(); |
| EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[0]); |
| |
| expected.id_attribute = ASCIIToUTF16("lastname"); |
| expected.name = expected.id_attribute; |
| expected.value.clear(); |
| EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[1]); |
| |
| expected.id_attribute = ASCIIToUTF16("noAC"); |
| expected.name = expected.id_attribute; |
| expected.value = ASCIIToUTF16("one"); |
| expected.label = ASCIIToUTF16("one"); |
| expected.autocomplete_attribute = "off"; |
| EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[2]); |
| expected.autocomplete_attribute.clear(); |
| |
| expected.id_attribute = ASCIIToUTF16("notenabled"); |
| expected.name = expected.id_attribute; |
| expected.value = ASCIIToUTF16("no clear"); |
| expected.label.clear(); |
| EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[3]); |
| |
| expected.form_control_type = "month"; |
| expected.max_length = 0; |
| expected.id_attribute = ASCIIToUTF16("month"); |
| expected.name = expected.id_attribute; |
| expected.value.clear(); |
| expected.label.clear(); |
| EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[4]); |
| |
| expected.id_attribute = ASCIIToUTF16("month-disabled"); |
| expected.name = expected.id_attribute; |
| expected.value = ASCIIToUTF16("2012-11"); |
| expected.label = ASCIIToUTF16("2012-11"); |
| EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[5]); |
| |
| expected.form_control_type = "textarea"; |
| expected.id_attribute = ASCIIToUTF16("textarea"); |
| expected.name = expected.id_attribute; |
| expected.value.clear(); |
| expected.label.clear(); |
| EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[6]); |
| |
| expected.id_attribute = ASCIIToUTF16("textarea-disabled"); |
| expected.name = expected.id_attribute; |
| expected.value = ASCIIToUTF16(" Banana! "); |
| EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[7]); |
| |
| expected.id_attribute = ASCIIToUTF16("textarea-noAC"); |
| expected.name = expected.id_attribute; |
| expected.value = ASCIIToUTF16("Carrot?"); |
| expected.autocomplete_attribute = "off"; |
| EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[8]); |
| expected.autocomplete_attribute.clear(); |
| |
| // Verify that the cursor position has been updated. |
| EXPECT_EQ(0, firstname.SelectionStart()); |
| EXPECT_EQ(0, firstname.SelectionEnd()); |
| } |
| |
| void TestClearTwoSections(const char* html, bool unowned) { |
| LoadHTML(html); |
| WebLocalFrame* web_frame = GetMainFrame(); |
| ASSERT_NE(nullptr, web_frame); |
| |
| FormCache form_cache(web_frame); |
| std::vector<FormData> forms = form_cache.ExtractNewForms(nullptr); |
| ASSERT_EQ(1U, forms.size()); |
| |
| // Set the autofilled attribute and specify the section attribute. |
| WebInputElement firstname_shipping = |
| GetInputElementById("firstname-shipping"); |
| firstname_shipping.SetAutofillValue("John"); |
| firstname_shipping.SetAutofillState(WebAutofillState::kAutofilled); |
| firstname_shipping.SetAutofillSection("shipping"); |
| |
| WebInputElement lastname_shipping = |
| GetInputElementById("lastname-shipping"); |
| lastname_shipping.SetAutofillValue("Smith"); |
| lastname_shipping.SetAutofillState(WebAutofillState::kAutofilled); |
| lastname_shipping.SetAutofillSection("shipping"); |
| |
| WebInputElement city_shipping = GetInputElementById("city-shipping"); |
| city_shipping.SetAutofillValue("Montreal"); |
| city_shipping.SetAutofillState(WebAutofillState::kAutofilled); |
| city_shipping.SetAutofillSection("shipping"); |
| |
| WebInputElement firstname_billing = |
| GetInputElementById("firstname-billing"); |
| firstname_billing.SetAutofillValue("John"); |
| firstname_billing.SetAutofillState(WebAutofillState::kAutofilled); |
| firstname_billing.SetAutofillSection("billing"); |
| |
| WebInputElement lastname_billing = GetInputElementById("lastname-billing"); |
| lastname_billing.SetAutofillValue("Smith"); |
| lastname_billing.SetAutofillState(WebAutofillState::kAutofilled); |
| lastname_billing.SetAutofillSection("billing"); |
| |
| WebInputElement city_billing = GetInputElementById("city-billing"); |
| city_billing.SetAutofillValue("Paris"); |
| city_billing.SetAutofillState(WebAutofillState::kAutofilled); |
| city_billing.SetAutofillSection("billing"); |
| |
| // Clear the first (shipping) section. |
| EXPECT_TRUE(form_cache.ClearSectionWithElement(firstname_shipping)); |
| |
| // Verify that the autofilled attribute is false only for the shipping |
| // section. |
| EXPECT_FALSE(firstname_shipping.IsAutofilled()); |
| EXPECT_FALSE(lastname_shipping.IsAutofilled()); |
| EXPECT_FALSE(city_shipping.IsAutofilled()); |
| EXPECT_TRUE(firstname_billing.IsAutofilled()); |
| EXPECT_TRUE(lastname_billing.IsAutofilled()); |
| EXPECT_TRUE(city_billing.IsAutofilled()); |
| |
| // Verify that the shipping section is cleared, but not the billing one. |
| FormData form; |
| FormFieldData field; |
| EXPECT_TRUE(FindFormAndFieldForFormControlElement(firstname_shipping, |
| nullptr, &form, &field)); |
| EXPECT_EQ(GetCanonicalOriginForDocument(web_frame->GetDocument()), |
| form.url); |
| EXPECT_FALSE(form.url.is_empty()); |
| if (!unowned) { |
| EXPECT_EQ(ASCIIToUTF16("TestForm"), form.name); |
| EXPECT_EQ(GURL("http://abc.com"), form.action); |
| } |
| |
| const std::vector<FormFieldData>& fields = form.fields; |
| ASSERT_EQ(6U, fields.size()); |
| |
| FormFieldData expected; |
| expected.form_control_type = "text"; |
| expected.max_length = WebInputElement::DefaultMaxLength(); |
| |
| // shipping section |
| expected.is_autofilled = false; |
| expected.id_attribute = ASCIIToUTF16("firstname-shipping"); |
| expected.name = expected.id_attribute; |
| EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[0]); |
| |
| expected.id_attribute = ASCIIToUTF16("lastname-shipping"); |
| expected.name = expected.id_attribute; |
| EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[1]); |
| |
| expected.id_attribute = ASCIIToUTF16("city-shipping"); |
| expected.name = expected.id_attribute; |
| EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[2]); |
| |
| // billing section |
| expected.is_autofilled = true; |
| expected.id_attribute = ASCIIToUTF16("firstname-billing"); |
| expected.name = expected.id_attribute; |
| expected.value = ASCIIToUTF16("John"); |
| EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[3]); |
| |
| expected.id_attribute = ASCIIToUTF16("lastname-billing"); |
| expected.name = expected.id_attribute; |
| expected.value = ASCIIToUTF16("Smith"); |
| EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[4]); |
| |
| expected.id_attribute = ASCIIToUTF16("city-billing"); |
| expected.name = expected.id_attribute; |
| expected.value = ASCIIToUTF16("Paris"); |
| EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[5]); |
| |
| // Verify that the cursor position has been updated. |
| EXPECT_EQ(0, firstname_shipping.SelectionStart()); |
| EXPECT_EQ(0, firstname_shipping.SelectionEnd()); |
| } |
| |
| void TestClearSectionWithNodeContainingSelectOne(const char* html, |
| bool unowned) { |
| LoadHTML(html); |
| WebLocalFrame* web_frame = GetMainFrame(); |
| ASSERT_NE(nullptr, web_frame); |
| |
| FormCache form_cache(web_frame); |
| std::vector<FormData> forms = form_cache.ExtractNewForms(nullptr); |
| ASSERT_EQ(1U, forms.size()); |
| |
| // Set the auto-filled attribute. |
| WebInputElement firstname = GetInputElementById("firstname"); |
| firstname.SetAutofillState(WebAutofillState::kAutofilled); |
| WebInputElement lastname = GetInputElementById("lastname"); |
| lastname.SetAutofillState(WebAutofillState::kAutofilled); |
| |
| // Set the value and auto-filled attribute of the state element. |
| WebSelectElement state = |
| web_frame->GetDocument().GetElementById("state").To<WebSelectElement>(); |
| state.SetValue(WebString::FromUTF8("AK")); |
| state.SetAutofillState(WebAutofillState::kAutofilled); |
| |
| // Clear the form. |
| EXPECT_TRUE(form_cache.ClearSectionWithElement(firstname)); |
| |
| // Verify that the auto-filled attribute has been turned off. |
| EXPECT_FALSE(firstname.IsAutofilled()); |
| |
| // Verify the form is cleared. |
| FormData form; |
| FormFieldData field; |
| EXPECT_TRUE(FindFormAndFieldForFormControlElement(firstname, nullptr, &form, |
| &field)); |
| EXPECT_EQ(GetCanonicalOriginForDocument(web_frame->GetDocument()), |
| form.url); |
| EXPECT_FALSE(form.url.is_empty()); |
| if (!unowned) { |
| EXPECT_EQ(ASCIIToUTF16("TestForm"), form.name); |
| EXPECT_EQ(GURL("http://abc.com"), form.action); |
| } |
| |
| const std::vector<FormFieldData>& fields = form.fields; |
| ASSERT_EQ(3U, fields.size()); |
| |
| FormFieldData expected; |
| |
| expected.id_attribute = ASCIIToUTF16("firstname"); |
| expected.name = expected.id_attribute; |
| expected.value.clear(); |
| expected.form_control_type = "text"; |
| expected.max_length = WebInputElement::DefaultMaxLength(); |
| EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[0]); |
| |
| expected.id_attribute = ASCIIToUTF16("lastname"); |
| expected.name = expected.id_attribute; |
| expected.value.clear(); |
| expected.form_control_type = "text"; |
| expected.max_length = WebInputElement::DefaultMaxLength(); |
| EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[1]); |
| |
| expected.id_attribute = ASCIIToUTF16("state"); |
| expected.name_attribute = ASCIIToUTF16("state"); |
| expected.name = expected.name_attribute; |
| expected.value = ASCIIToUTF16("?"); |
| expected.form_control_type = "select-one"; |
| expected.max_length = 0; |
| EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[2]); |
| |
| // Verify that the cursor position has been updated. |
| EXPECT_EQ(0, firstname.SelectionStart()); |
| EXPECT_EQ(0, firstname.SelectionEnd()); |
| } |
| |
| void TestClearPreviewedFormWithElement(const char* html) { |
| LoadHTML(html); |
| WebLocalFrame* web_frame = GetMainFrame(); |
| ASSERT_NE(nullptr, web_frame); |
| |
| FormCache form_cache(web_frame); |
| std::vector<FormData> forms = form_cache.ExtractNewForms(nullptr); |
| ASSERT_EQ(1U, forms.size()); |
| |
| // Set the auto-filled attribute. |
| WebInputElement firstname = GetInputElementById("firstname"); |
| firstname.SetAutofillState(WebAutofillState::kPreviewed); |
| WebInputElement lastname = GetInputElementById("lastname"); |
| lastname.SetAutofillState(WebAutofillState::kPreviewed); |
| WebInputElement email = GetInputElementById("email"); |
| email.SetAutofillState(WebAutofillState::kPreviewed); |
| WebInputElement email2 = GetInputElementById("email2"); |
| email2.SetAutofillState(WebAutofillState::kPreviewed); |
| WebInputElement phone = GetInputElementById("phone"); |
| phone.SetAutofillState(WebAutofillState::kPreviewed); |
| |
| // Set the suggested values on two of the elements. |
| lastname.SetSuggestedValue(WebString::FromASCII("Earp")); |
| email.SetSuggestedValue(WebString::FromASCII("wyatt@earp.com")); |
| email2.SetSuggestedValue(WebString::FromASCII("wyatt@earp.com")); |
| phone.SetSuggestedValue(WebString::FromASCII("650-777-9999")); |
| |
| // Clear the previewed fields. |
| EXPECT_TRUE( |
| ClearPreviewedFormWithElement(lastname, WebAutofillState::kNotFilled)); |
| |
| // Fields with empty suggestions suggestions are not modified. |
| EXPECT_EQ(ASCIIToUTF16("Wyatt"), firstname.Value().Utf16()); |
| EXPECT_TRUE(firstname.SuggestedValue().IsEmpty()); |
| EXPECT_TRUE(firstname.IsAutofilled()); |
| |
| // Verify the previewed fields are cleared. |
| EXPECT_TRUE(lastname.Value().IsEmpty()); |
| EXPECT_TRUE(lastname.SuggestedValue().IsEmpty()); |
| EXPECT_FALSE(lastname.IsAutofilled()); |
| EXPECT_TRUE(email.Value().IsEmpty()); |
| EXPECT_TRUE(email.SuggestedValue().IsEmpty()); |
| EXPECT_FALSE(email.IsAutofilled()); |
| EXPECT_TRUE(email2.Value().IsEmpty()); |
| EXPECT_TRUE(email2.SuggestedValue().IsEmpty()); |
| EXPECT_FALSE(email2.IsAutofilled()); |
| EXPECT_TRUE(phone.Value().IsEmpty()); |
| EXPECT_TRUE(phone.SuggestedValue().IsEmpty()); |
| EXPECT_FALSE(phone.IsAutofilled()); |
| |
| // Verify that the cursor position has been updated. |
| EXPECT_EQ(0, lastname.SelectionStart()); |
| EXPECT_EQ(0, lastname.SelectionEnd()); |
| } |
| |
| void TestClearPreviewedFormWithNonEmptyInitiatingNode(const char* html) { |
| LoadHTML(html); |
| WebLocalFrame* web_frame = GetMainFrame(); |
| ASSERT_NE(nullptr, web_frame); |
| |
| FormCache form_cache(web_frame); |
| std::vector<FormData> forms = form_cache.ExtractNewForms(nullptr); |
| ASSERT_EQ(1U, forms.size()); |
| |
| // Set the auto-filled attribute. |
| WebInputElement firstname = GetInputElementById("firstname"); |
| firstname.SetAutofillState(WebAutofillState::kPreviewed); |
| WebInputElement lastname = GetInputElementById("lastname"); |
| lastname.SetAutofillState(WebAutofillState::kPreviewed); |
| WebInputElement email = GetInputElementById("email"); |
| email.SetAutofillState(WebAutofillState::kPreviewed); |
| WebInputElement email2 = GetInputElementById("email2"); |
| email2.SetAutofillState(WebAutofillState::kPreviewed); |
| WebInputElement phone = GetInputElementById("phone"); |
| phone.SetAutofillState(WebAutofillState::kPreviewed); |
| |
| // Set the suggested values on all of the elements. |
| firstname.SetSuggestedValue(WebString::FromASCII("Wyatt")); |
| lastname.SetSuggestedValue(WebString::FromASCII("Earp")); |
| email.SetSuggestedValue(WebString::FromASCII("wyatt@earp.com")); |
| email2.SetSuggestedValue(WebString::FromASCII("wyatt@earp.com")); |
| phone.SetSuggestedValue(WebString::FromASCII("650-777-9999")); |
| |
| // Clear the previewed fields. |
| EXPECT_TRUE( |
| ClearPreviewedFormWithElement(firstname, WebAutofillState::kNotFilled)); |
| |
| // Fields with non-empty values are restored. |
| EXPECT_EQ(ASCIIToUTF16("W"), firstname.Value().Utf16()); |
| EXPECT_TRUE(firstname.SuggestedValue().IsEmpty()); |
| EXPECT_FALSE(firstname.IsAutofilled()); |
| EXPECT_EQ(1, firstname.SelectionStart()); |
| EXPECT_EQ(1, firstname.SelectionEnd()); |
| |
| // Verify the previewed fields are cleared. |
| EXPECT_TRUE(lastname.Value().IsEmpty()); |
| EXPECT_TRUE(lastname.SuggestedValue().IsEmpty()); |
| EXPECT_FALSE(lastname.IsAutofilled()); |
| EXPECT_TRUE(email.Value().IsEmpty()); |
| EXPECT_TRUE(email.SuggestedValue().IsEmpty()); |
| EXPECT_FALSE(email.IsAutofilled()); |
| EXPECT_TRUE(email2.Value().IsEmpty()); |
| EXPECT_TRUE(email2.SuggestedValue().IsEmpty()); |
| EXPECT_FALSE(email2.IsAutofilled()); |
| EXPECT_TRUE(phone.Value().IsEmpty()); |
| EXPECT_TRUE(phone.SuggestedValue().IsEmpty()); |
| EXPECT_FALSE(phone.IsAutofilled()); |
| } |
| |
| void TestClearPreviewedFormWithAutofilledInitiatingNode(const char* html) { |
| LoadHTML(html); |
| WebLocalFrame* web_frame = GetMainFrame(); |
| ASSERT_NE(nullptr, web_frame); |
| |
| FormCache form_cache(web_frame); |
| std::vector<FormData> forms = form_cache.ExtractNewForms(nullptr); |
| ASSERT_EQ(1U, forms.size()); |
| |
| // Set the auto-filled attribute. |
| WebInputElement firstname = GetInputElementById("firstname"); |
| firstname.SetAutofillState(WebAutofillState::kPreviewed); |
| WebInputElement lastname = GetInputElementById("lastname"); |
| lastname.SetAutofillState(WebAutofillState::kPreviewed); |
| WebInputElement email = GetInputElementById("email"); |
| email.SetAutofillState(WebAutofillState::kPreviewed); |
| WebInputElement email2 = GetInputElementById("email2"); |
| email2.SetAutofillState(WebAutofillState::kPreviewed); |
| WebInputElement phone = GetInputElementById("phone"); |
| phone.SetAutofillState(WebAutofillState::kPreviewed); |
| |
| // Set the suggested values on all of the elements. |
| firstname.SetSuggestedValue(WebString::FromASCII("Wyatt")); |
| lastname.SetSuggestedValue(WebString::FromASCII("Earp")); |
| email.SetSuggestedValue(WebString::FromASCII("wyatt@earp.com")); |
| email2.SetSuggestedValue(WebString::FromASCII("wyatt@earp.com")); |
| phone.SetSuggestedValue(WebString::FromASCII("650-777-9999")); |
| |
| // Clear the previewed fields. |
| EXPECT_TRUE(ClearPreviewedFormWithElement(firstname, |
| WebAutofillState::kAutofilled)); |
| |
| // Fields with non-empty values are restored. |
| EXPECT_EQ(ASCIIToUTF16("W"), firstname.Value().Utf16()); |
| EXPECT_TRUE(firstname.SuggestedValue().IsEmpty()); |
| EXPECT_TRUE(firstname.IsAutofilled()); |
| EXPECT_EQ(1, firstname.SelectionStart()); |
| EXPECT_EQ(1, firstname.SelectionEnd()); |
| |
| // Verify the previewed fields are cleared. |
| EXPECT_TRUE(lastname.Value().IsEmpty()); |
| EXPECT_TRUE(lastname.SuggestedValue().IsEmpty()); |
| EXPECT_FALSE(lastname.IsAutofilled()); |
| EXPECT_TRUE(email.Value().IsEmpty()); |
| EXPECT_TRUE(email.SuggestedValue().IsEmpty()); |
| EXPECT_FALSE(email.IsAutofilled()); |
| EXPECT_TRUE(email2.Value().IsEmpty()); |
| EXPECT_TRUE(email2.SuggestedValue().IsEmpty()); |
| EXPECT_FALSE(email2.IsAutofilled()); |
| EXPECT_TRUE(phone.Value().IsEmpty()); |
| EXPECT_TRUE(phone.SuggestedValue().IsEmpty()); |
| EXPECT_FALSE(phone.IsAutofilled()); |
| } |
| |
| void TestClearOnlyAutofilledFields(const char* html) { |
| LoadHTML(html); |
| |
| WebLocalFrame* web_frame = GetMainFrame(); |
| ASSERT_NE(nullptr, web_frame); |
| |
| FormCache form_cache(web_frame); |
| std::vector<FormData> forms = form_cache.ExtractNewForms(nullptr); |
| ASSERT_EQ(1U, forms.size()); |
| |
| // Set the autofilled attribute. |
| WebInputElement firstname = GetInputElementById("firstname"); |
| firstname.SetAutofillState(WebAutofillState::kNotFilled); |
| WebInputElement lastname = GetInputElementById("lastname"); |
| lastname.SetAutofillState(WebAutofillState::kAutofilled); |
| WebInputElement email = GetInputElementById("email"); |
| email.SetAutofillState(WebAutofillState::kAutofilled); |
| WebInputElement phone = GetInputElementById("phone"); |
| phone.SetAutofillState(WebAutofillState::kAutofilled); |
| |
| // Clear the fields. |
| EXPECT_TRUE(form_cache.ClearSectionWithElement(firstname)); |
| |
| // Verify only autofilled fields are cleared. |
| EXPECT_EQ(ASCIIToUTF16("Wyatt"), firstname.Value().Utf16()); |
| EXPECT_TRUE(firstname.SuggestedValue().IsEmpty()); |
| EXPECT_FALSE(firstname.IsAutofilled()); |
| EXPECT_TRUE(lastname.Value().IsEmpty()); |
| EXPECT_TRUE(lastname.SuggestedValue().IsEmpty()); |
| EXPECT_FALSE(lastname.IsAutofilled()); |
| EXPECT_TRUE(email.Value().IsEmpty()); |
| EXPECT_TRUE(email.SuggestedValue().IsEmpty()); |
| EXPECT_FALSE(email.IsAutofilled()); |
| EXPECT_TRUE(phone.Value().IsEmpty()); |
| EXPECT_TRUE(phone.SuggestedValue().IsEmpty()); |
| EXPECT_FALSE(phone.IsAutofilled()); |
| } |
| |
| static WebString GetValueWrapper(WebFormControlElement element) { |
| if (element.FormControlType() == "textarea") |
| return element.To<WebFormControlElement>().Value(); |
| |
| if (element.FormControlType() == "select-one") |
| return element.To<WebSelectElement>().Value(); |
| |
| return element.To<WebInputElement>().Value(); |
| } |
| |
| static WebString GetSuggestedValueWrapper(WebFormControlElement element) { |
| if (element.FormControlType() == "textarea") |
| return element.To<WebFormControlElement>().SuggestedValue(); |
| |
| if (element.FormControlType() == "select-one") |
| return element.To<WebSelectElement>().SuggestedValue(); |
| |
| return element.To<WebInputElement>().SuggestedValue(); |
| } |
| |
| private: |
| base::test::ScopedFeatureList scoped_feature_list_; |
| DISALLOW_COPY_AND_ASSIGN(FormAutofillTest); |
| }; |
| |
| // We should be able to extract a normal text field. |
| TEST_F(FormAutofillTest, WebFormControlElementToFormField) { |
| LoadHTML("<INPUT type='text' id='element' value='value'/>"); |
| |
| WebLocalFrame* frame = GetMainFrame(); |
| ASSERT_NE(nullptr, frame); |
| |
| WebFormControlElement element = GetFormControlElementById("element"); |
| FormFieldData result1; |
| WebFormControlElementToFormField(element, nullptr, EXTRACT_NONE, &result1); |
| |
| FormFieldData expected; |
| expected.form_control_type = "text"; |
| expected.max_length = WebInputElement::DefaultMaxLength(); |
| |
| expected.id_attribute = ASCIIToUTF16("element"); |
| expected.name = expected.id_attribute; |
| expected.value.clear(); |
| EXPECT_FORM_FIELD_DATA_EQUALS(expected, result1); |
| |
| FormFieldData result2; |
| WebFormControlElementToFormField(element, nullptr, EXTRACT_VALUE, &result2); |
| |
| expected.id_attribute = ASCIIToUTF16("element"); |
| expected.name = expected.id_attribute; |
| expected.value = ASCIIToUTF16("value"); |
| EXPECT_FORM_FIELD_DATA_EQUALS(expected, result2); |
| } |
| |
| // We should be able to extract a text field with autocomplete="off". |
| TEST_F(FormAutofillTest, WebFormControlElementToFormFieldAutocompleteOff) { |
| LoadHTML("<INPUT type='text' id='element' value='value'" |
| " autocomplete='off'/>"); |
| |
| WebLocalFrame* frame = GetMainFrame(); |
| ASSERT_NE(nullptr, frame); |
| |
| WebFormControlElement element = GetFormControlElementById("element"); |
| FormFieldData result; |
| WebFormControlElementToFormField(element, nullptr, EXTRACT_VALUE, &result); |
| |
| FormFieldData expected; |
| expected.id_attribute = ASCIIToUTF16("element"); |
| expected.name = expected.id_attribute; |
| expected.value = ASCIIToUTF16("value"); |
| expected.form_control_type = "text"; |
| expected.autocomplete_attribute = "off"; |
| expected.max_length = WebInputElement::DefaultMaxLength(); |
| EXPECT_FORM_FIELD_DATA_EQUALS(expected, result); |
| } |
| |
| // We should be able to extract a text field with maxlength specified. |
| TEST_F(FormAutofillTest, WebFormControlElementToFormFieldMaxLength) { |
| LoadHTML("<INPUT type='text' id='element' value='value'" |
| " maxlength='5'/>"); |
| |
| WebLocalFrame* frame = GetMainFrame(); |
| ASSERT_NE(nullptr, frame); |
| |
| WebFormControlElement element = GetFormControlElementById("element"); |
| FormFieldData result; |
| WebFormControlElementToFormField(element, nullptr, EXTRACT_VALUE, &result); |
| |
| FormFieldData expected; |
| expected.id_attribute = ASCIIToUTF16("element"); |
| expected.name = expected.id_attribute; |
| expected.value = ASCIIToUTF16("value"); |
| expected.form_control_type = "text"; |
| expected.max_length = 5; |
| EXPECT_FORM_FIELD_DATA_EQUALS(expected, result); |
| } |
| |
| // We should be able to extract a text field that has been autofilled. |
| TEST_F(FormAutofillTest, WebFormControlElementToFormFieldAutofilled) { |
| LoadHTML("<INPUT type='text' id='element' value='value'/>"); |
| |
| WebLocalFrame* frame = GetMainFrame(); |
| ASSERT_NE(nullptr, frame); |
| |
| WebInputElement element = GetInputElementById("element"); |
| element.SetAutofillState(WebAutofillState::kAutofilled); |
| FormFieldData result; |
| WebFormControlElementToFormField(element, nullptr, EXTRACT_VALUE, &result); |
| |
| FormFieldData expected; |
| expected.id_attribute = ASCIIToUTF16("element"); |
| expected.name = expected.id_attribute; |
| expected.value = ASCIIToUTF16("value"); |
| expected.form_control_type = "text"; |
| expected.max_length = WebInputElement::DefaultMaxLength(); |
| expected.is_autofilled = true; |
| EXPECT_FORM_FIELD_DATA_EQUALS(expected, result); |
| } |
| |
| // We should be able to extract a radio or a checkbox field that has been |
| // autofilled. |
| TEST_F(FormAutofillTest, WebFormControlElementToClickableFormField) { |
| LoadHTML("<INPUT type='checkbox' id='checkbox' value='mail' checked/>" |
| "<INPUT type='radio' id='radio' value='male'/>"); |
| |
| WebLocalFrame* frame = GetMainFrame(); |
| ASSERT_NE(nullptr, frame); |
| |
| WebInputElement element = GetInputElementById("checkbox"); |
| element.SetAutofillState(WebAutofillState::kAutofilled); |
| FormFieldData result; |
| WebFormControlElementToFormField(element, nullptr, EXTRACT_VALUE, &result); |
| |
| FormFieldData expected; |
| expected.id_attribute = ASCIIToUTF16("checkbox"); |
| expected.name = expected.id_attribute; |
| expected.value = ASCIIToUTF16("mail"); |
| expected.form_control_type = "checkbox"; |
| expected.is_autofilled = true; |
| expected.check_status = FormFieldData::CheckStatus::kChecked; |
| EXPECT_FORM_FIELD_DATA_EQUALS(expected, result); |
| |
| element = GetInputElementById("radio"); |
| element.SetAutofillState(WebAutofillState::kAutofilled); |
| WebFormControlElementToFormField(element, nullptr, EXTRACT_VALUE, &result); |
| expected.id_attribute = ASCIIToUTF16("radio"); |
| expected.name = expected.id_attribute; |
| expected.value = ASCIIToUTF16("male"); |
| expected.form_control_type = "radio"; |
| expected.is_autofilled = true; |
| expected.check_status = FormFieldData::CheckStatus::kCheckableButUnchecked; |
| EXPECT_FORM_FIELD_DATA_EQUALS(expected, result); |
| } |
| |
| // We should be able to extract a <select> field. |
| TEST_F(FormAutofillTest, WebFormControlElementToFormFieldSelect) { |
| LoadHTML("<SELECT id='element'/>" |
| " <OPTION value='CA'>California</OPTION>" |
| " <OPTION value='TX'>Texas</OPTION>" |
| "</SELECT>"); |
| |
| WebLocalFrame* frame = GetMainFrame(); |
| ASSERT_NE(nullptr, frame); |
| |
| WebFormControlElement element = GetFormControlElementById("element"); |
| FormFieldData result1; |
| WebFormControlElementToFormField(element, nullptr, EXTRACT_VALUE, &result1); |
| |
| FormFieldData expected; |
| expected.id_attribute = ASCIIToUTF16("element"); |
| expected.name = expected.id_attribute; |
| expected.max_length = 0; |
| expected.form_control_type = "select-one"; |
| |
| expected.value = ASCIIToUTF16("CA"); |
| EXPECT_FORM_FIELD_DATA_EQUALS(expected, result1); |
| |
| FormFieldData result2; |
| WebFormControlElementToFormField( |
| element, nullptr, |
| static_cast<ExtractMask>(EXTRACT_VALUE | EXTRACT_OPTION_TEXT), &result2); |
| expected.value = ASCIIToUTF16("California"); |
| EXPECT_FORM_FIELD_DATA_EQUALS(expected, result2); |
| |
| FormFieldData result3; |
| WebFormControlElementToFormField(element, nullptr, EXTRACT_OPTIONS, &result3); |
| expected.value.clear(); |
| EXPECT_FORM_FIELD_DATA_EQUALS(expected, result3); |
| |
| ASSERT_EQ(2U, result3.option_values.size()); |
| ASSERT_EQ(2U, result3.option_contents.size()); |
| EXPECT_EQ(ASCIIToUTF16("CA"), result3.option_values[0]); |
| EXPECT_EQ(ASCIIToUTF16("California"), result3.option_contents[0]); |
| EXPECT_EQ(ASCIIToUTF16("TX"), result3.option_values[1]); |
| EXPECT_EQ(ASCIIToUTF16("Texas"), result3.option_contents[1]); |
| } |
| |
| // We copy extra attributes for the select field. |
| TEST_F(FormAutofillTest, |
| WebFormControlElementToFormFieldSelect_ExtraAttributes) { |
| LoadHTML("<SELECT id='element' autocomplete='off'/>" |
| " <OPTION value='CA'>California</OPTION>" |
| " <OPTION value='TX'>Texas</OPTION>" |
| "</SELECT>"); |
| |
| WebLocalFrame* frame = GetMainFrame(); |
| ASSERT_NE(nullptr, frame); |
| |
| WebFormControlElement element = GetFormControlElementById("element"); |
| element.SetAutofillState(WebAutofillState::kAutofilled); |
| |
| FormFieldData result1; |
| WebFormControlElementToFormField(element, nullptr, EXTRACT_VALUE, &result1); |
| |
| FormFieldData expected; |
| expected.id_attribute = ASCIIToUTF16("element"); |
| expected.name = expected.id_attribute; |
| expected.max_length = 0; |
| expected.form_control_type = "select-one"; |
| // We check that the extra attributes have been copied to |result1|. |
| expected.is_autofilled = true; |
| expected.autocomplete_attribute = "off"; |
| expected.should_autocomplete = false; |
| expected.is_focusable = true; |
| expected.text_direction = base::i18n::LEFT_TO_RIGHT; |
| |
| expected.value = ASCIIToUTF16("CA"); |
| EXPECT_FORM_FIELD_DATA_EQUALS(expected, result1); |
| } |
| |
| // When faced with <select> field with *many* options, we should trim them to a |
| // reasonable number. |
| TEST_F(FormAutofillTest, WebFormControlElementToFormFieldLongSelect) { |
| std::string html = "<SELECT id='element'/>"; |
| for (size_t i = 0; i < 2 * kMaxListSize; ++i) { |
| html += base::StringPrintf("<OPTION value='%" PRIuS "'>" |
| "%" PRIuS "</OPTION>", i, i); |
| } |
| html += "</SELECT>"; |
| LoadHTML(html.c_str()); |
| |
| WebLocalFrame* frame = GetMainFrame(); |
| ASSERT_TRUE(frame); |
| |
| WebFormControlElement element = GetFormControlElementById("element"); |
| FormFieldData result; |
| WebFormControlElementToFormField(element, nullptr, EXTRACT_OPTIONS, &result); |
| |
| EXPECT_TRUE(result.option_values.empty()); |
| EXPECT_TRUE(result.option_contents.empty()); |
| } |
| |
| // We should be able to extract a <textarea> field. |
| TEST_F(FormAutofillTest, WebFormControlElementToFormFieldTextArea) { |
| LoadHTML("<TEXTAREA id='element'>" |
| "This element's value " |
| "spans multiple lines." |
| "</TEXTAREA>"); |
| |
| WebLocalFrame* frame = GetMainFrame(); |
| ASSERT_NE(nullptr, frame); |
| |
| WebFormControlElement element = GetFormControlElementById("element"); |
| FormFieldData result_sans_value; |
| WebFormControlElementToFormField(element, nullptr, EXTRACT_NONE, |
| &result_sans_value); |
| |
| FormFieldData expected; |
| expected.id_attribute = ASCIIToUTF16("element"); |
| expected.name = expected.id_attribute; |
| expected.max_length = 0; |
| expected.form_control_type = "textarea"; |
| EXPECT_FORM_FIELD_DATA_EQUALS(expected, result_sans_value); |
| |
| FormFieldData result_with_value; |
| WebFormControlElementToFormField(element, nullptr, EXTRACT_VALUE, |
| &result_with_value); |
| expected.value = ASCIIToUTF16("This element's value\n" |
| "spans multiple lines."); |
| EXPECT_FORM_FIELD_DATA_EQUALS(expected, result_with_value); |
| } |
| |
| // We should be able to extract an <input type="month"> field. |
| TEST_F(FormAutofillTest, WebFormControlElementToFormFieldMonthInput) { |
| LoadHTML("<INPUT type='month' id='element' value='2011-12'>"); |
| |
| WebLocalFrame* frame = GetMainFrame(); |
| ASSERT_NE(nullptr, frame); |
| |
| WebFormControlElement element = GetFormControlElementById("element"); |
| FormFieldData result_sans_value; |
| WebFormControlElementToFormField(element, nullptr, EXTRACT_NONE, |
| &result_sans_value); |
| |
| FormFieldData expected; |
| expected.id_attribute = ASCIIToUTF16("element"); |
| expected.name = expected.id_attribute; |
| expected.max_length = 0; |
| expected.form_control_type = "month"; |
| EXPECT_FORM_FIELD_DATA_EQUALS(expected, result_sans_value); |
| |
| FormFieldData result_with_value; |
| WebFormControlElementToFormField(element, nullptr, EXTRACT_VALUE, |
| &result_with_value); |
| expected.value = ASCIIToUTF16("2011-12"); |
| EXPECT_FORM_FIELD_DATA_EQUALS(expected, result_with_value); |
| } |
| |
| // We should not extract the value for non-text and non-select fields. |
| TEST_F(FormAutofillTest, WebFormControlElementToFormFieldInvalidType) { |
| LoadHTML("<FORM name='TestForm' action='http://cnn.com' method='post'>" |
| " <INPUT type='hidden' id='hidden' value='apple'/>" |
| " <INPUT type='submit' id='submit' value='Send'/>" |
| "</FORM>"); |
| |
| WebLocalFrame* frame = GetMainFrame(); |
| ASSERT_NE(nullptr, frame); |
| |
| WebFormControlElement element = GetFormControlElementById("hidden"); |
| FormFieldData result; |
| WebFormControlElementToFormField(element, nullptr, EXTRACT_VALUE, &result); |
| |
| FormFieldData expected; |
| expected.max_length = 0; |
| |
| expected.id_attribute = ASCIIToUTF16("hidden"); |
| expected.name = expected.id_attribute; |
| expected.form_control_type = "hidden"; |
| EXPECT_FORM_FIELD_DATA_EQUALS(expected, result); |
| |
| element = GetFormControlElementById("submit"); |
| WebFormControlElementToFormField(element, nullptr, EXTRACT_VALUE, &result); |
| expected.id_attribute = ASCIIToUTF16("submit"); |
| expected.name = expected.id_attribute; |
| expected.form_control_type = "submit"; |
| EXPECT_FORM_FIELD_DATA_EQUALS(expected, result); |
| } |
| |
| // We should be able to extract password fields. |
| TEST_F(FormAutofillTest, WebFormControlElementToPasswordFormField) { |
| LoadHTML("<FORM name='TestForm' action='http://cnn.com' method='post'>" |
| " <INPUT type='password' id='password' value='secret'/>" |
| "</FORM>"); |
| |
| WebLocalFrame* frame = GetMainFrame(); |
| ASSERT_NE(nullptr, frame); |
| |
| WebFormControlElement element = GetFormControlElementById("password"); |
| FormFieldData result; |
| WebFormControlElementToFormField(element, nullptr, EXTRACT_VALUE, &result); |
| |
| FormFieldData expected; |
| expected.max_length = WebInputElement::DefaultMaxLength(); |
| expected.id_attribute = ASCIIToUTF16("password"); |
| expected.name = expected.id_attribute; |
| expected.form_control_type = "password"; |
| expected.value = ASCIIToUTF16("secret"); |
| EXPECT_FORM_FIELD_DATA_EQUALS(expected, result); |
| } |
| |
| // We should be able to extract the autocompletetype attribute. |
| TEST_F(FormAutofillTest, WebFormControlElementToFormFieldAutocompletetype) { |
| std::string html = |
| "<INPUT type='text' id='absent'/>" |
| "<INPUT type='text' id='empty' autocomplete=''/>" |
| "<INPUT type='text' id='off' autocomplete='off'/>" |
| "<INPUT type='text' id='regular' autocomplete='email'/>" |
| "<INPUT type='text' id='multi-valued' " |
| " autocomplete='billing email'/>" |
| "<INPUT type='text' id='experimental' x-autocompletetype='email'/>" |
| "<INPUT type='month' id='month' autocomplete='cc-exp'/>" |
| "<SELECT id='select' autocomplete='state'/>" |
| " <OPTION value='CA'>California</OPTION>" |
| " <OPTION value='TX'>Texas</OPTION>" |
| "</SELECT>" |
| "<TEXTAREA id='textarea' autocomplete='street-address'>" |
| " Some multi-" |
| " lined value" |
| "</TEXTAREA>"; |
| html += |
| "<INPUT type='text' id='malicious' autocomplete='" + |
| std::string(10000, 'x') + "'/>"; |
| LoadHTML(html.c_str()); |
| |
| WebLocalFrame* frame = GetMainFrame(); |
| ASSERT_NE(nullptr, frame); |
| |
| struct TestCase { |
| const std::string element_id; |
| const std::string form_control_type; |
| const std::string autocomplete_attribute; |
| }; |
| TestCase test_cases[] = { |
| // An absent attribute is equivalent to an empty one. |
| { "absent", "text", "" }, |
| // Make sure there are no issues parsing an empty attribute. |
| { "empty", "text", "" }, |
| // Make sure there are no issues parsing an attribute value that isn't a |
| // type hint. |
| { "off", "text", "off" }, |
| // Common case: exactly one type specified. |
| { "regular", "text", "email" }, |
| // Verify that we correctly extract multiple tokens as well. |
| { "multi-valued", "text", "billing email" }, |
| // Verify that <input type="month"> fields are supported. |
| { "month", "month", "cc-exp" }, |
| // We previously extracted this data from the experimental |
| // 'x-autocompletetype' attribute. Now that the field type hints are part |
| // of the spec under the autocomplete attribute, we no longer support the |
| // experimental version. |
| { "experimental", "text", "" }, |
|