// 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 #include #include "base/format_macros.h" #include "base/macros.h" #include "base/strings/string16.h" #include "base/strings/stringprintf.h" #include "base/strings/utf_string_conversions.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/form_data.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/WebKit/public/platform/WebString.h" #include "third_party/WebKit/public/platform/WebVector.h" #include "third_party/WebKit/public/web/WebDocument.h" #include "third_party/WebKit/public/web/WebElement.h" #include "third_party/WebKit/public/web/WebElementCollection.h" #include "third_party/WebKit/public/web/WebExceptionCode.h" #include "third_party/WebKit/public/web/WebFormControlElement.h" #include "third_party/WebKit/public/web/WebFormElement.h" #include "third_party/WebKit/public/web/WebInputElement.h" #include "third_party/WebKit/public/web/WebLocalFrame.h" #include "third_party/WebKit/public/web/WebSelectElement.h" using base::ASCIIToUTF16; using blink::WebDocument; using blink::WebElement; using blink::WebExceptionCode; using blink::WebFormControlElement; using blink::WebFormElement; using blink::WebFrame; using blink::WebInputElement; 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 name; 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[] = "
" " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
"; // 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[] = "Enter Shipping Info" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" ""; // This constant has no title tag, and should be passed to // LoadHTMLWithURLOverride to test the detection of unowned forms by URL. const char kUnownedUntitledFormHtml[] = "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" ""; // This constant does not have a title tag, but should match an unowned form // anyway because it is not English. const char kUnownedNonEnglishFormHtml[] = "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" ""; 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: { WebExceptionCode ec = 0; element = document.querySelector(web_descriptor, ec); if (ec) DVLOG(1) << "Query selector failed. Error code: " << ec << "."; 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() {} ~FormAutofillTest() override {} void ExpectLabels(const char* html, const std::vector& labels, const std::vector& names, const std::vector& values) { std::vector control_types(labels.size(), "text"); ExpectLabelsAndTypes(html, labels, names, values, control_types); } void ExpectLabelsAndTypes(const char* html, const std::vector& labels, const std::vector& names, const std::vector& values, const std::vector& control_types) { ASSERT_EQ(labels.size(), names.size()); ASSERT_EQ(labels.size(), values.size()); ASSERT_EQ(labels.size(), control_types.size()); LoadHTML(html); WebFrame* web_frame = GetMainFrame(); ASSERT_NE(nullptr, web_frame); FormCache form_cache(*web_frame); std::vector forms = form_cache.ExtractNewForms(); ASSERT_EQ(1U, forms.size()); const FormData& form = forms[0]; EXPECT_EQ(ASCIIToUTF16("TestForm"), form.name); EXPECT_EQ(GetCanonicalOriginForDocument(web_frame->document()), form.origin); EXPECT_EQ(GURL("http://cnn.com"), form.action); const std::vector& fields = form.fields; ASSERT_EQ(labels.size(), fields.size()); for (size_t i = 0; i < labels.size(); ++i) { int max_length = control_types[i] == "text" ? WebInputElement::defaultMaxLength() : 0; FormFieldData expected; expected.label = labels[i]; expected.name = names[i]; expected.value = values[i]; expected.form_control_type = control_types[i]; expected.max_length = max_length; SCOPED_TRACE(base::StringPrintf("i: %" PRIuS, i)); EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[i]); } } void ExpectJohnSmithLabels(const char* html) { std::vector labels, names, values; labels.push_back(ASCIIToUTF16("First name:")); names.push_back(ASCIIToUTF16("firstname")); values.push_back(ASCIIToUTF16("John")); labels.push_back(ASCIIToUTF16("Last name:")); names.push_back(ASCIIToUTF16("lastname")); values.push_back(ASCIIToUTF16("Smith")); labels.push_back(ASCIIToUTF16("Email:")); names.push_back(ASCIIToUTF16("email")); values.push_back(ASCIIToUTF16("john@example.com")); ExpectLabels(html, 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); WebFrame* web_frame = GetMainFrame(); ASSERT_NE(nullptr, web_frame); FormCache form_cache(*web_frame); std::vector forms = form_cache.ExtractNewForms(); 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, &form_data, &field)); if (!unowned) { EXPECT_EQ(ASCIIToUTF16("TestForm"), form_data.name); EXPECT_EQ(GURL("http://abc.com"), form_data.action); } const std::vector& 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].name)); expected.form_control_type = field_cases[i].form_control_type; expected.max_length = expected.form_control_type == "text" ? WebInputElement::defaultMaxLength() : 0; expected.name = ASCIIToUTF16(field_cases[i].name); 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.name)); WebString value; WebFormControlElement element = GetFormControlElementById(ASCIIToUTF16(field_case.name)); 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 = ASCIIToUTF16(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()->document().getElementById( id).to(); } WebInputElement GetInputElementById(const WebString& id) { return GetMainFrame()->document().getElementById( id).to(); } 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 should be autofilled. {"month", "month", "", "", true, "2017-11", "2017-11"}, // Non-empty 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, arraysize(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 should be previewed. {"month", "month", "", "", true, "2017-11", "2017-11"}, // Non-empty 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, arraysize(field_cases), &PreviewForm, &GetSuggestedValueWrapper); // Verify preview selection. WebInputElement firstname = GetInputElementById("firstname"); EXPECT_EQ(0, firstname.selectionStart()); EXPECT_EQ(19, firstname.selectionEnd()); } void TestUnmatchedUnownedForm(const char* html, const char* url_override) { if (url_override) LoadHTMLWithUrlOverride(html, url_override); else LoadHTML(html); WebFrame* web_frame = GetMainFrame(); ASSERT_NE(nullptr, web_frame); FormCache form_cache(*web_frame); std::vector forms = form_cache.ExtractNewForms(); ASSERT_EQ(0U, forms.size()); } void TestFindFormForInputElement(const char* html, bool unowned) { LoadHTML(html); WebFrame* web_frame = GetMainFrame(); ASSERT_NE(nullptr, web_frame); FormCache form_cache(*web_frame); std::vector forms = form_cache.ExtractNewForms(); 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, &form, &field)); EXPECT_EQ(GetCanonicalOriginForDocument(web_frame->document()), form.origin); if (!unowned) { EXPECT_EQ(ASCIIToUTF16("TestForm"), form.name); EXPECT_EQ(GURL("http://abc.com"), form.action); } const std::vector& fields = form.fields; ASSERT_EQ(4U, fields.size()); FormFieldData expected; expected.form_control_type = "text"; expected.max_length = WebInputElement::defaultMaxLength(); expected.name = ASCIIToUTF16("firstname"); expected.value = ASCIIToUTF16("John"); expected.label = ASCIIToUTF16("John"); EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[0]); EXPECT_FORM_FIELD_DATA_EQUALS(expected, field); expected.name = ASCIIToUTF16("lastname"); expected.value = ASCIIToUTF16("Smith"); expected.label = ASCIIToUTF16("Smith"); EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[1]); expected.name = ASCIIToUTF16("email"); 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.name = ASCIIToUTF16("phone"); 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); WebFrame* web_frame = GetMainFrame(); ASSERT_NE(nullptr, web_frame); FormCache form_cache(*web_frame); std::vector forms = form_cache.ExtractNewForms(); ASSERT_EQ(1U, forms.size()); // Get the textarea element we want to find. WebElement element = web_frame->document().getElementById("street-address"); WebFormControlElement textarea_element = element.to(); // Find the form and verify it's the correct form. FormData form; FormFieldData field; EXPECT_TRUE( FindFormAndFieldForFormControlElement(textarea_element, &form, &field)); EXPECT_EQ(GetCanonicalOriginForDocument(web_frame->document()), form.origin); if (!unowned) { EXPECT_EQ(ASCIIToUTF16("TestForm"), form.name); EXPECT_EQ(GURL("http://abc.com"), form.action); } const std::vector& fields = form.fields; ASSERT_EQ(4U, fields.size()); FormFieldData expected; expected.name = ASCIIToUTF16("firstname"); 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.name = ASCIIToUTF16("lastname"); 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.name = ASCIIToUTF16("email"); 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.name = ASCIIToUTF16("street-address"); 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); WebFrame* web_frame = GetMainFrame(); ASSERT_NE(nullptr, web_frame); FormCache form_cache(*web_frame); std::vector forms = form_cache.ExtractNewForms(); 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, &form, &field)); EXPECT_EQ(GetCanonicalOriginForDocument(web_frame->document()), form.origin); if (!unowned) { EXPECT_EQ(ASCIIToUTF16("TestForm"), form.name); EXPECT_EQ(GURL("http://abc.com"), form.action); } const std::vector& fields = form.fields; ASSERT_EQ(3U, fields.size()); FormFieldData expected; expected.form_control_type = "text"; expected.name = ASCIIToUTF16("firstname"); expected.max_length = 5; expected.is_autofilled = false; EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[0]); expected.name = ASCIIToUTF16("lastname"); expected.max_length = 7; expected.is_autofilled = false; EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[1]); expected.name = ASCIIToUTF16("email"); 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, &form2, &field2)); EXPECT_EQ(GetCanonicalOriginForDocument(web_frame->document()), form2.origin); if (!unowned) { EXPECT_EQ(ASCIIToUTF16("TestForm"), form2.name); EXPECT_EQ(GURL("http://abc.com"), form2.action); } const std::vector& fields2 = form2.fields; ASSERT_EQ(3U, fields2.size()); expected.form_control_type = "text"; expected.name = ASCIIToUTF16("firstname"); expected.value = ASCIIToUTF16("Broth"); expected.max_length = 5; expected.is_autofilled = true; EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields2[0]); expected.name = ASCIIToUTF16("lastname"); expected.value = ASCIIToUTF16("Jonatha"); expected.max_length = 7; expected.is_autofilled = true; EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields2[1]); expected.name = ASCIIToUTF16("email"); 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); WebFrame* web_frame = GetMainFrame(); ASSERT_NE(nullptr, web_frame); FormCache form_cache(*web_frame); std::vector forms = form_cache.ExtractNewForms(); 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, &form, &field)); EXPECT_EQ(GetCanonicalOriginForDocument(web_frame->document()), form.origin); if (!unowned) { EXPECT_EQ(ASCIIToUTF16("TestForm"), form.name); EXPECT_EQ(GURL("http://abc.com"), form.action); } const std::vector& fields = form.fields; ASSERT_EQ(3U, fields.size()); FormFieldData expected; expected.form_control_type = "text"; expected.max_length = WebInputElement::defaultMaxLength(); expected.name = ASCIIToUTF16("firstname"); EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[0]); expected.name = ASCIIToUTF16("lastname"); EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[1]); expected.name = ASCIIToUTF16("email"); 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, &form2, &field2)); EXPECT_EQ(GetCanonicalOriginForDocument(web_frame->document()), form2.origin); if (!unowned) { EXPECT_EQ(ASCIIToUTF16("TestForm"), form2.name); EXPECT_EQ(GURL("http://abc.com"), form2.action); } const std::vector& fields2 = form2.fields; ASSERT_EQ(3U, fields2.size()); expected.name = ASCIIToUTF16("firstname"); expected.value = ASCIIToUTF16("Brother"); EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[0]); expected.name = ASCIIToUTF16("lastname"); expected.value = ASCIIToUTF16("Jonathan"); EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[1]); expected.name = ASCIIToUTF16("email"); expected.value = ASCIIToUTF16("brotherj@example.com"); EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[2]); } void TestFillFormEmptyName(const char* html, bool unowned) { LoadHTML(html); WebFrame* web_frame = GetMainFrame(); ASSERT_NE(nullptr, web_frame); FormCache form_cache(*web_frame); std::vector forms = form_cache.ExtractNewForms(); 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, &form, &field)); EXPECT_EQ(GetCanonicalOriginForDocument(web_frame->document()), form.origin); if (!unowned) { EXPECT_EQ(ASCIIToUTF16("TestForm"), form.name); EXPECT_EQ(GURL("http://abc.com"), form.action); } const std::vector& fields = form.fields; ASSERT_EQ(3U, fields.size()); FormFieldData expected; expected.form_control_type = "text"; expected.max_length = WebInputElement::defaultMaxLength(); expected.name = ASCIIToUTF16("firstname"); EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[0]); expected.name = ASCIIToUTF16("lastname"); EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[1]); expected.name = ASCIIToUTF16("email"); 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, &form2, &field2)); EXPECT_EQ(GetCanonicalOriginForDocument(web_frame->document()), form2.origin); if (!unowned) { EXPECT_EQ(ASCIIToUTF16("TestForm"), form2.name); EXPECT_EQ(GURL("http://abc.com"), form2.action); } const std::vector& fields2 = form2.fields; ASSERT_EQ(3U, fields2.size()); expected.form_control_type = "text"; expected.max_length = WebInputElement::defaultMaxLength(); expected.name = ASCIIToUTF16("firstname"); expected.value = ASCIIToUTF16("Wyatt"); EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[0]); expected.name = ASCIIToUTF16("lastname"); expected.value = ASCIIToUTF16("Earp"); EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[1]); expected.name = ASCIIToUTF16("email"); expected.value = ASCIIToUTF16("wyatt@example.com"); EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[2]); } void TestFillFormEmptyFormNames(const char* html, bool unowned) { LoadHTML(html); WebFrame* web_frame = GetMainFrame(); ASSERT_NE(nullptr, web_frame); FormCache form_cache(*web_frame); std::vector forms = form_cache.ExtractNewForms(); 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, &form, &field)); EXPECT_EQ(GetCanonicalOriginForDocument(web_frame->document()), form.origin); if (!unowned) { EXPECT_TRUE(form.name.empty()); EXPECT_EQ(GURL("http://abc.com"), form.action); } const std::vector& 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.name = ASCIIToUTF16("apple"); expected.is_autofilled = false; EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[unowned_offset]); expected.name = ASCIIToUTF16("banana"); expected.is_autofilled = false; EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[unowned_offset + 1]); expected.name = ASCIIToUTF16("cantelope"); 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, &form2, &field2)); EXPECT_EQ(GetCanonicalOriginForDocument(web_frame->document()), form2.origin); if (!unowned) { EXPECT_TRUE(form2.name.empty()); EXPECT_EQ(GURL("http://abc.com"), form2.action); } const std::vector& fields2 = form2.fields; ASSERT_EQ(unowned_offset + 3, fields2.size()); expected.name = ASCIIToUTF16("apple"); expected.value = ASCIIToUTF16("Red"); expected.is_autofilled = true; EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields2[unowned_offset + 0]); expected.name = ASCIIToUTF16("banana"); expected.value = ASCIIToUTF16("Yellow"); expected.is_autofilled = true; EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields2[unowned_offset + 1]); expected.name = ASCIIToUTF16("cantelope"); 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) { LoadHTML(html); WebFrame* web_frame = GetMainFrame(); ASSERT_NE(nullptr, web_frame); FormCache form_cache(*web_frame); std::vector forms = form_cache.ExtractNewForms(); 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(ASCIIToUTF16("Wy")); // Find the form that contains the input element. FormData form; FormFieldData field; EXPECT_TRUE( FindFormAndFieldForFormControlElement(input_element, &form, &field)); EXPECT_EQ(GetCanonicalOriginForDocument(web_frame->document()), form.origin); if (!unowned) { EXPECT_EQ(ASCIIToUTF16("TestForm"), form.name); EXPECT_EQ(GURL("http://abc.com"), form.action); } const std::vector& fields = form.fields; ASSERT_EQ(3U, fields.size()); FormFieldData expected; expected.form_control_type = "text"; expected.max_length = WebInputElement::defaultMaxLength(); expected.name = ASCIIToUTF16("firstname"); expected.value = ASCIIToUTF16("Wy"); expected.is_autofilled = false; EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[0]); expected.name = ASCIIToUTF16("lastname"); if (initial_lastname) { expected.label = ASCIIToUTF16(initial_lastname); expected.value = ASCIIToUTF16(initial_lastname); } else { expected.label.clear(); expected.value.clear(); } expected.is_autofilled = false; EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[1]); expected.name = ASCIIToUTF16("email"); if (initial_email) { expected.label = ASCIIToUTF16(initial_email); expected.value = ASCIIToUTF16(initial_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); EXPECT_EQ(2, 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, &form2, &field2)); EXPECT_EQ(GetCanonicalOriginForDocument(web_frame->document()), form2.origin); if (!unowned) { EXPECT_EQ(ASCIIToUTF16("TestForm"), form2.name); EXPECT_EQ(GURL("http://abc.com"), form2.action); } const std::vector& fields2 = form2.fields; ASSERT_EQ(3U, fields2.size()); expected.name = ASCIIToUTF16("firstname"); expected.value = ASCIIToUTF16("Wyatt"); expected.label.clear(); expected.is_autofilled = true; EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields2[0]); expected.name = ASCIIToUTF16("lastname"); expected.value = ASCIIToUTF16("Earp"); expected.label.clear(); expected.is_autofilled = true; EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields2[1]); expected.name = ASCIIToUTF16("email"); expected.value = ASCIIToUTF16("wyatt@example.com"); expected.label.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 TestClearFormWithNode(const char* html, bool unowned) { LoadHTML(html); WebFrame* web_frame = GetMainFrame(); ASSERT_NE(nullptr, web_frame); FormCache form_cache(*web_frame); std::vector forms = form_cache.ExtractNewForms(); ASSERT_EQ(1U, forms.size()); // Set the auto-filled attribute. WebInputElement firstname = GetInputElementById("firstname"); firstname.setAutofilled(true); WebInputElement lastname = GetInputElementById("lastname"); lastname.setAutofilled(true); WebInputElement month = GetInputElementById("month"); month.setAutofilled(true); WebFormControlElement textarea = GetFormControlElementById("textarea"); textarea.setAutofilled(true); // 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.ClearFormWithElement(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, &form, &field)); EXPECT_EQ(GetCanonicalOriginForDocument(web_frame->document()), form.origin); EXPECT_FALSE(form.origin.is_empty()); if (!unowned) { EXPECT_EQ(ASCIIToUTF16("TestForm"), form.name); EXPECT_EQ(GURL("http://abc.com"), form.action); } const std::vector& fields = form.fields; ASSERT_EQ(9U, fields.size()); FormFieldData expected; expected.form_control_type = "text"; expected.max_length = WebInputElement::defaultMaxLength(); expected.name = ASCIIToUTF16("firstname"); expected.value.clear(); EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[0]); expected.name = ASCIIToUTF16("lastname"); expected.value.clear(); EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[1]); expected.name = ASCIIToUTF16("noAC"); 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.name = ASCIIToUTF16("notenabled"); 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.name = ASCIIToUTF16("month"); expected.value.clear(); expected.label.clear(); EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[4]); expected.name = ASCIIToUTF16("month-disabled"); expected.value = ASCIIToUTF16("2012-11"); expected.label = ASCIIToUTF16("2012-11"); EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[5]); expected.form_control_type = "textarea"; expected.name = ASCIIToUTF16("textarea"); expected.value.clear(); expected.label.clear(); EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[6]); expected.name = ASCIIToUTF16("textarea-disabled"); expected.value = ASCIIToUTF16(" Banana! "); EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[7]); expected.name = ASCIIToUTF16("textarea-noAC"); 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 TestClearFormWithNodeContainingSelectOne(const char* html, bool unowned) { LoadHTML(html); WebFrame* web_frame = GetMainFrame(); ASSERT_NE(nullptr, web_frame); FormCache form_cache(*web_frame); std::vector forms = form_cache.ExtractNewForms(); ASSERT_EQ(1U, forms.size()); // Set the auto-filled attribute. WebInputElement firstname = GetInputElementById("firstname"); firstname.setAutofilled(true); WebInputElement lastname = GetInputElementById("lastname"); lastname.setAutofilled(true); // Set the value and auto-filled attribute of the state element. WebSelectElement state = web_frame->document().getElementById("state").to(); state.setValue(WebString::fromUTF8("AK")); state.setAutofilled(true); // Clear the form. EXPECT_TRUE(form_cache.ClearFormWithElement(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, &form, &field)); EXPECT_EQ(GetCanonicalOriginForDocument(web_frame->document()), form.origin); EXPECT_FALSE(form.origin.is_empty()); if (!unowned) { EXPECT_EQ(ASCIIToUTF16("TestForm"), form.name); EXPECT_EQ(GURL("http://abc.com"), form.action); } const std::vector& fields = form.fields; ASSERT_EQ(3U, fields.size()); FormFieldData expected; expected.name = ASCIIToUTF16("firstname"); expected.value.clear(); expected.form_control_type = "text"; expected.max_length = WebInputElement::defaultMaxLength(); EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[0]); expected.name = ASCIIToUTF16("lastname"); expected.value.clear(); expected.form_control_type = "text"; expected.max_length = WebInputElement::defaultMaxLength(); EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[1]); expected.name = ASCIIToUTF16("state"); 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); WebFrame* web_frame = GetMainFrame(); ASSERT_NE(nullptr, web_frame); FormCache form_cache(*web_frame); std::vector forms = form_cache.ExtractNewForms(); ASSERT_EQ(1U, forms.size()); // Set the auto-filled attribute. WebInputElement firstname = GetInputElementById("firstname"); firstname.setAutofilled(true); WebInputElement lastname = GetInputElementById("lastname"); lastname.setAutofilled(true); WebInputElement email = GetInputElementById("email"); email.setAutofilled(true); WebInputElement email2 = GetInputElementById("email2"); email2.setAutofilled(true); WebInputElement phone = GetInputElementById("phone"); phone.setAutofilled(true); // Set the suggested values on two of the elements. lastname.setSuggestedValue(ASCIIToUTF16("Earp")); email.setSuggestedValue(ASCIIToUTF16("wyatt@earp.com")); email2.setSuggestedValue(ASCIIToUTF16("wyatt@earp.com")); phone.setSuggestedValue(ASCIIToUTF16("650-777-9999")); // Clear the previewed fields. EXPECT_TRUE(ClearPreviewedFormWithElement(lastname, false)); // Fields with empty suggestions suggestions are not modified. EXPECT_EQ(ASCIIToUTF16("Wyatt"), firstname.value()); 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); WebFrame* web_frame = GetMainFrame(); ASSERT_NE(nullptr, web_frame); FormCache form_cache(*web_frame); std::vector forms = form_cache.ExtractNewForms(); ASSERT_EQ(1U, forms.size()); // Set the auto-filled attribute. WebInputElement firstname = GetInputElementById("firstname"); firstname.setAutofilled(true); WebInputElement lastname = GetInputElementById("lastname"); lastname.setAutofilled(true); WebInputElement email = GetInputElementById("email"); email.setAutofilled(true); WebInputElement email2 = GetInputElementById("email2"); email2.setAutofilled(true); WebInputElement phone = GetInputElementById("phone"); phone.setAutofilled(true); // Set the suggested values on all of the elements. firstname.setSuggestedValue(ASCIIToUTF16("Wyatt")); lastname.setSuggestedValue(ASCIIToUTF16("Earp")); email.setSuggestedValue(ASCIIToUTF16("wyatt@earp.com")); email2.setSuggestedValue(ASCIIToUTF16("wyatt@earp.com")); phone.setSuggestedValue(ASCIIToUTF16("650-777-9999")); // Clear the previewed fields. EXPECT_TRUE(ClearPreviewedFormWithElement(firstname, false)); // Fields with non-empty values are restored. EXPECT_EQ(ASCIIToUTF16("W"), firstname.value()); 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); WebFrame* web_frame = GetMainFrame(); ASSERT_NE(nullptr, web_frame); FormCache form_cache(*web_frame); std::vector forms = form_cache.ExtractNewForms(); ASSERT_EQ(1U, forms.size()); // Set the auto-filled attribute. WebInputElement firstname = GetInputElementById("firstname"); firstname.setAutofilled(true); WebInputElement lastname = GetInputElementById("lastname"); lastname.setAutofilled(true); WebInputElement email = GetInputElementById("email"); email.setAutofilled(true); WebInputElement email2 = GetInputElementById("email2"); email2.setAutofilled(true); WebInputElement phone = GetInputElementById("phone"); phone.setAutofilled(true); // Set the suggested values on all of the elements. firstname.setSuggestedValue(ASCIIToUTF16("Wyatt")); lastname.setSuggestedValue(ASCIIToUTF16("Earp")); email.setSuggestedValue(ASCIIToUTF16("wyatt@earp.com")); email2.setSuggestedValue(ASCIIToUTF16("wyatt@earp.com")); phone.setSuggestedValue(ASCIIToUTF16("650-777-9999")); // Clear the previewed fields. EXPECT_TRUE(ClearPreviewedFormWithElement(firstname, true)); // Fields with non-empty values are restored. EXPECT_EQ(ASCIIToUTF16("W"), firstname.value()); 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); WebFrame* web_frame = GetMainFrame(); ASSERT_NE(nullptr, web_frame); FormCache form_cache(*web_frame); std::vector forms = form_cache.ExtractNewForms(); ASSERT_EQ(1U, forms.size()); // Set the autofilled attribute. WebInputElement firstname = GetInputElementById("firstname"); firstname.setAutofilled(false); WebInputElement lastname = GetInputElementById("lastname"); lastname.setAutofilled(true); WebInputElement email = GetInputElementById("email"); email.setAutofilled(true); WebInputElement phone = GetInputElementById("phone"); phone.setAutofilled(true); // Clear the fields. EXPECT_TRUE(form_cache.ClearFormWithElement(firstname)); // Verify only autofilled fields are cleared. EXPECT_EQ(ASCIIToUTF16("Wyatt"), firstname.value()); 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 void FillFormIncludingNonFocusableElementsWrapper( const FormData& form, const WebFormControlElement& element) { FillFormIncludingNonFocusableElements(form, element.form()); } static WebString GetValueWrapper(WebFormControlElement element) { if (element.formControlType() == "textarea") return element.to().value(); if (element.formControlType() == "select-one") return element.to().value(); return element.to().value(); } static WebString GetSuggestedValueWrapper(WebFormControlElement element) { if (element.formControlType() == "textarea") return element.to().suggestedValue(); if (element.formControlType() == "select-one") return element.to().suggestedValue(); return element.to().suggestedValue(); } private: DISALLOW_COPY_AND_ASSIGN(FormAutofillTest); }; // We should be able to extract a normal text field. TEST_F(FormAutofillTest, WebFormControlElementToFormField) { LoadHTML(""); WebFrame* frame = GetMainFrame(); ASSERT_NE(nullptr, frame); WebFormControlElement element = GetFormControlElementById("element"); FormFieldData result1; WebFormControlElementToFormField(element, EXTRACT_NONE, &result1); FormFieldData expected; expected.form_control_type = "text"; expected.max_length = WebInputElement::defaultMaxLength(); expected.name = ASCIIToUTF16("element"); expected.value.clear(); EXPECT_FORM_FIELD_DATA_EQUALS(expected, result1); FormFieldData result2; WebFormControlElementToFormField(element, EXTRACT_VALUE, &result2); expected.name = ASCIIToUTF16("element"); 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(""); WebFrame* frame = GetMainFrame(); ASSERT_NE(nullptr, frame); WebFormControlElement element = GetFormControlElementById("element"); FormFieldData result; WebFormControlElementToFormField(element, EXTRACT_VALUE, &result); FormFieldData expected; expected.name = ASCIIToUTF16("element"); 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(""); WebFrame* frame = GetMainFrame(); ASSERT_NE(nullptr, frame); WebFormControlElement element = GetFormControlElementById("element"); FormFieldData result; WebFormControlElementToFormField(element, EXTRACT_VALUE, &result); FormFieldData expected; expected.name = ASCIIToUTF16("element"); 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(""); WebFrame* frame = GetMainFrame(); ASSERT_NE(nullptr, frame); WebInputElement element = GetInputElementById("element"); element.setAutofilled(true); FormFieldData result; WebFormControlElementToFormField(element, EXTRACT_VALUE, &result); FormFieldData expected; expected.name = ASCIIToUTF16("element"); 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("" ""); WebFrame* frame = GetMainFrame(); ASSERT_NE(nullptr, frame); WebInputElement element = GetInputElementById("checkbox"); element.setAutofilled(true); FormFieldData result; WebFormControlElementToFormField(element, EXTRACT_VALUE, &result); FormFieldData expected; expected.name = ASCIIToUTF16("checkbox"); expected.value = ASCIIToUTF16("mail"); expected.form_control_type = "checkbox"; expected.is_autofilled = true; expected.is_checkable = true; expected.is_checked = true; EXPECT_FORM_FIELD_DATA_EQUALS(expected, result); element = GetInputElementById("radio"); element.setAutofilled(true); WebFormControlElementToFormField(element, EXTRACT_VALUE, &result); expected.name = ASCIIToUTF16("radio"); expected.value = ASCIIToUTF16("male"); expected.form_control_type = "radio"; expected.is_autofilled = true; expected.is_checkable = true; expected.is_checked = false; EXPECT_FORM_FIELD_DATA_EQUALS(expected, result); } // We should be able to extract a " " " " " ""); WebFrame* frame = GetMainFrame(); ASSERT_NE(nullptr, frame); WebFormControlElement element = GetFormControlElementById("element"); FormFieldData result1; WebFormControlElementToFormField(element, EXTRACT_VALUE, &result1); FormFieldData expected; expected.name = ASCIIToUTF16("element"); 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, static_cast(EXTRACT_VALUE | EXTRACT_OPTION_TEXT), &result2); expected.value = ASCIIToUTF16("California"); EXPECT_FORM_FIELD_DATA_EQUALS(expected, result2); FormFieldData result3; WebFormControlElementToFormField(element, 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(""); WebFrame* frame = GetMainFrame(); ASSERT_NE(nullptr, frame); WebFormControlElement element = GetFormControlElementById("element"); element.setAutofilled(true); FormFieldData result1; WebFormControlElementToFormField(element, EXTRACT_VALUE, &result1); FormFieldData expected; expected.name = ASCIIToUTF16("element"); 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 "; for (size_t i = 0; i < 2 * kMaxListSize; ++i) { html += base::StringPrintf("", i, i); } html += ""; LoadHTML(html.c_str()); WebFrame* frame = GetMainFrame(); ASSERT_TRUE(frame); WebFormControlElement element = GetFormControlElementById("element"); FormFieldData result; WebFormControlElementToFormField(element, EXTRACT_OPTIONS, &result); EXPECT_TRUE(result.option_values.empty()); EXPECT_TRUE(result.option_contents.empty()); } // We should be able to extract a "); WebFrame* frame = GetMainFrame(); ASSERT_NE(nullptr, frame); WebFormControlElement element = GetFormControlElementById("element"); FormFieldData result_sans_value; WebFormControlElementToFormField(element, EXTRACT_NONE, &result_sans_value); FormFieldData expected; expected.name = ASCIIToUTF16("element"); expected.max_length = 0; expected.form_control_type = "textarea"; EXPECT_FORM_FIELD_DATA_EQUALS(expected, result_sans_value); FormFieldData result_with_value; WebFormControlElementToFormField(element, 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 field. TEST_F(FormAutofillTest, WebFormControlElementToFormFieldMonthInput) { LoadHTML(""); WebFrame* frame = GetMainFrame(); ASSERT_NE(nullptr, frame); WebFormControlElement element = GetFormControlElementById("element"); FormFieldData result_sans_value; WebFormControlElementToFormField(element, EXTRACT_NONE, &result_sans_value); FormFieldData expected; expected.name = ASCIIToUTF16("element"); expected.max_length = 0; expected.form_control_type = "month"; EXPECT_FORM_FIELD_DATA_EQUALS(expected, result_sans_value); FormFieldData result_with_value; WebFormControlElementToFormField(element, 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("
" " " " " "
"); WebFrame* frame = GetMainFrame(); ASSERT_NE(nullptr, frame); WebFormControlElement element = GetFormControlElementById("hidden"); FormFieldData result; WebFormControlElementToFormField(element, EXTRACT_VALUE, &result); FormFieldData expected; expected.max_length = 0; expected.name = ASCIIToUTF16("hidden"); expected.form_control_type = "hidden"; EXPECT_FORM_FIELD_DATA_EQUALS(expected, result); element = GetFormControlElementById("submit"); WebFormControlElementToFormField(element, EXTRACT_VALUE, &result); expected.name = ASCIIToUTF16("submit"); 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("
" " " "
"); WebFrame* frame = GetMainFrame(); ASSERT_NE(nullptr, frame); WebFormControlElement element = GetFormControlElementById("password"); FormFieldData result; WebFormControlElementToFormField(element, EXTRACT_VALUE, &result); FormFieldData expected; expected.max_length = WebInputElement::defaultMaxLength(); expected.name = ASCIIToUTF16("password"); 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 = "" "" "" "" "" "" "" "" ""; html += ""; LoadHTML(html.c_str()); WebFrame* 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 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", "" }, // " " " " " " " " " " " " " " " // The below inputs should be ignored " " " " ""); WebFrame* frame = GetMainFrame(); ASSERT_NE(nullptr, frame); WebVector forms; frame->document().forms(forms); ASSERT_EQ(1U, forms.size()); WebInputElement input_element = GetInputElementById("firstname"); FormData form; FormFieldData field; EXPECT_TRUE(WebFormElementToFormData(forms[0], input_element, EXTRACT_VALUE, &form, &field)); EXPECT_EQ(ASCIIToUTF16("TestForm"), form.name); EXPECT_EQ(GetCanonicalOriginForDocument(frame->document()), form.origin); EXPECT_FALSE(form.origin.is_empty()); EXPECT_EQ(GURL("http://cnn.com"), form.action); const std::vector& fields = form.fields; ASSERT_EQ(6U, fields.size()); FormFieldData expected; expected.name = ASCIIToUTF16("firstname"); expected.value = ASCIIToUTF16("John"); expected.label = ASCIIToUTF16("First name:"); expected.form_control_type = "text"; expected.max_length = WebInputElement::defaultMaxLength(); EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[0]); expected.name = ASCIIToUTF16("lastname"); expected.value = ASCIIToUTF16("Smith"); expected.label = ASCIIToUTF16("Last name:"); expected.form_control_type = "text"; expected.max_length = WebInputElement::defaultMaxLength(); EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[1]); expected.name = ASCIIToUTF16("street-address"); expected.value = ASCIIToUTF16("123 Fantasy Ln.\nApt. 42"); expected.label = ASCIIToUTF16("Address:"); expected.form_control_type = "textarea"; expected.max_length = 0; EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[2]); expected.name = ASCIIToUTF16("state"); expected.value = ASCIIToUTF16("CA"); expected.label = ASCIIToUTF16("State:"); expected.form_control_type = "select-one"; expected.max_length = 0; EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[3]); expected.name = ASCIIToUTF16("password"); expected.value = ASCIIToUTF16("secret"); expected.label = ASCIIToUTF16("Password:"); expected.form_control_type = "password"; expected.max_length = WebInputElement::defaultMaxLength(); EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[4]); expected.name = ASCIIToUTF16("month"); expected.value = ASCIIToUTF16("2011-12"); expected.label = ASCIIToUTF16("Card expiration:"); expected.form_control_type = "month"; expected.max_length = 0; EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[5]); } TEST_F(FormAutofillTest, WebFormElementConsiderNonControlLabelableElements) { LoadHTML("
" " " " " " " " " "
"); WebFrame* frame = GetMainFrame(); ASSERT_NE(nullptr, frame); WebFormElement web_form = frame->document().getElementById("form") .to(); ASSERT_FALSE(web_form.isNull()); FormData form; EXPECT_TRUE(WebFormElementToFormData(web_form, WebFormControlElement(), EXTRACT_NONE, &form, nullptr)); const std::vector& fields = form.fields; ASSERT_EQ(1U, fields.size()); EXPECT_EQ(ASCIIToUTF16("firstname"), fields[0].name); } // We should not be able to serialize a form with too many fillable fields. TEST_F(FormAutofillTest, WebFormElementToFormDataTooManyFields) { std::string html = "
"; for (size_t i = 0; i < (kMaxParseableFields + 1); ++i) { html += ""; } html += "
"; LoadHTML(html.c_str()); WebFrame* frame = GetMainFrame(); ASSERT_NE(nullptr, frame); WebVector forms; frame->document().forms(forms); ASSERT_EQ(1U, forms.size()); WebInputElement input_element = GetInputElementById("firstname"); FormData form; FormFieldData field; EXPECT_FALSE(WebFormElementToFormData(forms[0], input_element, EXTRACT_VALUE, &form, &field)); } // Tests that the |should_autocomplete| is set to false for all the fields when // an autocomplete='off' attribute is set for the form in HTML. TEST_F(FormAutofillTest, WebFormElementToFormData_AutocompleteOff_OnForm) { LoadHTML( "
" " " " " " " " " " " " " "
"); WebFrame* frame = GetMainFrame(); ASSERT_NE(nullptr, frame); WebFormElement web_form = frame->document().getElementById("form").to(); ASSERT_FALSE(web_form.isNull()); FormData form; EXPECT_TRUE(WebFormElementToFormData(web_form, WebFormControlElement(), EXTRACT_NONE, &form, nullptr)); for (const FormFieldData& field : form.fields) { EXPECT_FALSE(field.should_autocomplete); } } // Tests that the |should_autocomplete| is set to false only for the field // which has an autocomplete='off' attribute set for it in HTML. TEST_F(FormAutofillTest, WebFormElementToFormData_AutocompleteOff_OnField) { LoadHTML( "
" " " " " " " " " " " " " "
"); WebFrame* frame = GetMainFrame(); ASSERT_NE(nullptr, frame); WebFormElement web_form = frame->document().getElementById("form").to(); ASSERT_FALSE(web_form.isNull()); FormData form; EXPECT_TRUE(WebFormElementToFormData(web_form, WebFormControlElement(), EXTRACT_NONE, &form, nullptr)); ASSERT_EQ(3U, form.fields.size()); EXPECT_FALSE(form.fields[0].should_autocomplete); EXPECT_TRUE(form.fields[1].should_autocomplete); EXPECT_TRUE(form.fields[2].should_autocomplete); } TEST_F(FormAutofillTest, ExtractForms) { ExpectJohnSmithLabels( "
" " First name: " " Last name: " " Email: " " " "
"); } TEST_F(FormAutofillTest, ExtractMultipleForms) { LoadHTML("
" " " " " " " " " "
" "
" " " " " " " " " "
"); WebFrame* web_frame = GetMainFrame(); ASSERT_NE(nullptr, web_frame); FormCache form_cache(*web_frame); std::vector forms = form_cache.ExtractNewForms(); ASSERT_EQ(2U, forms.size()); // First form. const FormData& form = forms[0]; EXPECT_EQ(ASCIIToUTF16("TestForm"), form.name); EXPECT_EQ(GetCanonicalOriginForDocument(web_frame->document()), form.origin); EXPECT_FALSE(form.origin.is_empty()); EXPECT_EQ(GURL("http://cnn.com"), form.action); const std::vector& fields = form.fields; ASSERT_EQ(3U, fields.size()); FormFieldData expected; expected.form_control_type = "text"; expected.max_length = WebInputElement::defaultMaxLength(); expected.name = ASCIIToUTF16("firstname"); expected.value = ASCIIToUTF16("John"); expected.label = ASCIIToUTF16("John"); EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[0]); expected.name = ASCIIToUTF16("lastname"); expected.value = ASCIIToUTF16("Smith"); expected.label = ASCIIToUTF16("Smith"); EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[1]); expected.name = ASCIIToUTF16("email"); expected.value = ASCIIToUTF16("john@example.com"); expected.label = ASCIIToUTF16("john@example.com"); EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[2]); // Second form. const FormData& form2 = forms[1]; EXPECT_EQ(ASCIIToUTF16("TestForm2"), form2.name); EXPECT_EQ(GetCanonicalOriginForDocument(web_frame->document()), form2.origin); EXPECT_FALSE(form.origin.is_empty()); EXPECT_EQ(GURL("http://zoo.com"), form2.action); const std::vector& fields2 = form2.fields; ASSERT_EQ(3U, fields2.size()); expected.name = ASCIIToUTF16("firstname"); expected.value = ASCIIToUTF16("Jack"); expected.label = ASCIIToUTF16("Jack"); EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields2[0]); expected.name = ASCIIToUTF16("lastname"); expected.value = ASCIIToUTF16("Adams"); expected.label = ASCIIToUTF16("Adams"); EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields2[1]); expected.name = ASCIIToUTF16("email"); expected.value = ASCIIToUTF16("jack@example.com"); expected.label = ASCIIToUTF16("jack@example.com"); EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields2[2]); } TEST_F(FormAutofillTest, OnlyExtractNewForms) { LoadHTML( "
" " " " " " " " " "
"); WebFrame* web_frame = GetMainFrame(); ASSERT_NE(nullptr, web_frame); FormCache form_cache(*web_frame); std::vector forms = form_cache.ExtractNewForms(); ASSERT_EQ(1U, forms.size()); // Second call should give nothing as there are no new forms. forms = form_cache.ExtractNewForms(); ASSERT_TRUE(forms.empty()); // Append to the current form will re-extract. ExecuteJavaScriptForTests( "var newInput = document.createElement('input');" "newInput.setAttribute('type', 'text');" "newInput.setAttribute('id', 'telephone');" "newInput.value = '12345';" "document.getElementById('testform').appendChild(newInput);"); msg_loop_.RunUntilIdle(); forms = form_cache.ExtractNewForms(); ASSERT_EQ(1U, forms.size()); const std::vector& fields = forms[0].fields; ASSERT_EQ(4U, fields.size()); FormFieldData expected; expected.form_control_type = "text"; expected.max_length = WebInputElement::defaultMaxLength(); expected.name = ASCIIToUTF16("firstname"); expected.value = ASCIIToUTF16("John"); expected.label = ASCIIToUTF16("John"); EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[0]); expected.name = ASCIIToUTF16("lastname"); expected.value = ASCIIToUTF16("Smith"); expected.label = ASCIIToUTF16("Smith"); EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[1]); expected.name = ASCIIToUTF16("email"); expected.value = ASCIIToUTF16("john@example.com"); expected.label = ASCIIToUTF16("john@example.com"); EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[2]); expected.name = ASCIIToUTF16("telephone"); expected.value = ASCIIToUTF16("12345"); expected.label.clear(); EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[3]); forms.clear(); // Completely new form will also be extracted. ExecuteJavaScriptForTests( "var newForm=document.createElement('form');" "newForm.id='new_testform';" "newForm.action='http://google.com';" "newForm.method='post';" "var newFirstname=document.createElement('input');" "newFirstname.setAttribute('type', 'text');" "newFirstname.setAttribute('id', 'second_firstname');" "newFirstname.value = 'Bob';" "var newLastname=document.createElement('input');" "newLastname.setAttribute('type', 'text');" "newLastname.setAttribute('id', 'second_lastname');" "newLastname.value = 'Hope';" "var newEmail=document.createElement('input');" "newEmail.setAttribute('type', 'text');" "newEmail.setAttribute('id', 'second_email');" "newEmail.value = 'bobhope@example.com';" "newForm.appendChild(newFirstname);" "newForm.appendChild(newLastname);" "newForm.appendChild(newEmail);" "document.body.appendChild(newForm);"); msg_loop_.RunUntilIdle(); web_frame = GetMainFrame(); forms = form_cache.ExtractNewForms(); ASSERT_EQ(1U, forms.size()); const std::vector& fields2 = forms[0].fields; ASSERT_EQ(3U, fields2.size()); expected.name = ASCIIToUTF16("second_firstname"); expected.value = ASCIIToUTF16("Bob"); expected.label.clear(); EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields2[0]); expected.name = ASCIIToUTF16("second_lastname"); expected.value = ASCIIToUTF16("Hope"); expected.label.clear(); EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields2[1]); expected.name = ASCIIToUTF16("second_email"); expected.value = ASCIIToUTF16("bobhope@example.com"); expected.label.clear(); EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields2[2]); } // We should not extract a form if it has too few fillable fields. TEST_F(FormAutofillTest, ExtractFormsTooFewFields) { LoadHTML("
" " " " " " " "
"); WebFrame* web_frame = GetMainFrame(); ASSERT_NE(nullptr, web_frame); FormCache form_cache(*web_frame); std::vector forms = form_cache.ExtractNewForms(); ASSERT_TRUE(forms.empty()); } // We should not report additional forms for empty forms. TEST_F(FormAutofillTest, ExtractFormsSkippedForms) { LoadHTML("
" " " " " "
"); WebFrame* web_frame = GetMainFrame(); ASSERT_NE(nullptr, web_frame); FormCache form_cache(*web_frame); std::vector forms = form_cache.ExtractNewForms(); ASSERT_TRUE(forms.empty()); } // We should not report additional forms for empty forms. TEST_F(FormAutofillTest, ExtractFormsNoFields) { LoadHTML("
" "
"); WebFrame* web_frame = GetMainFrame(); ASSERT_NE(nullptr, web_frame); FormCache form_cache(*web_frame); std::vector forms = form_cache.ExtractNewForms(); ASSERT_TRUE(forms.empty()); } // We should not extract a form if it has too few fillable fields. // Make sure radio and checkbox fields don't count. TEST_F(FormAutofillTest, ExtractFormsTooFewFieldsSkipsCheckable) { LoadHTML("
" " " " " " " " " " " "
"); WebFrame* web_frame = GetMainFrame(); ASSERT_NE(nullptr, web_frame); FormCache form_cache(*web_frame); std::vector forms = form_cache.ExtractNewForms(); ASSERT_TRUE(forms.empty()); } TEST_F(FormAutofillTest, WebFormElementToFormDataAutocomplete) { { // Form is still Autofill-able despite autocomplete=off. LoadHTML("
" " " " " " " " " "
"); WebFrame* web_frame = GetMainFrame(); ASSERT_NE(nullptr, web_frame); WebVector web_forms; web_frame->document().forms(web_forms); ASSERT_EQ(1U, web_forms.size()); WebFormElement web_form = web_forms[0]; FormData form; EXPECT_TRUE(WebFormElementToFormData(web_form, WebFormControlElement(), EXTRACT_NONE, &form, nullptr)); } } TEST_F(FormAutofillTest, FindFormForInputElement) { TestFindFormForInputElement( "
" " " " " " " " " " " "
", false); } TEST_F(FormAutofillTest, FindFormForInputElementForUnownedForm) { TestFindFormForInputElement( "delivery recipient" "" "" "" "" "", true); } TEST_F(FormAutofillTest, FindFormForTextAreaElement) { TestFindFormForTextAreaElement( "
" " " " " " " " " " " "
", false); } TEST_F(FormAutofillTest, FindFormForTextAreaElementForUnownedForm) { TestFindFormForTextAreaElement( "delivery address" "" "" "" "" "", true); } // Test regular FillForm function. TEST_F(FormAutofillTest, FillForm) { TestFillForm(kFormHtml, false, nullptr); } TEST_F(FormAutofillTest, FillFormForUnownedForm) { TestFillForm(kUnownedFormHtml, true, nullptr); } TEST_F(FormAutofillTest, FillFormForUnownedUntitledForm) { TestFillForm(kUnownedUntitledFormHtml, true, "http://example.test/checkout_flow"); } TEST_F(FormAutofillTest, FillFormForUnownedNonEnglishForm) { TestFillForm(kUnownedNonEnglishFormHtml, true, nullptr); } TEST_F(FormAutofillTest, FillFormForUnownedNonASCIIForm) { std::string html("accented latin: \xC3\xA0, thai: \xE0\xB8\x81, " "control: \x04, nbsp: \xEF\xBB\xBF, non-BMP: \xF0\x9F\x8C\x80; This " "should match a CHECKOUT flow despite the non-ASCII chars" ""); html.append(kUnownedUntitledFormHtml); TestFillForm(html.c_str(), true, nullptr); } TEST_F(FormAutofillTest, FillFormIncludingNonFocusableElements) { 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 be overriden. {"text", "notempty", "Hi", "", true, "filled notempty", "filled notempty"}, {"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 also be autofilled. {"text", "invisible", "", "", true, "filled invisible", "filled invisible"}, // Fields with "display:none" should also be autofilled. {"text", "displaynone", "", "", true, "filled displaynone", "filled displaynone"}, // Regular should be autofilled. {"month", "month", "", "", true, "2017-11", "2017-11"}, // Non-empty should be overridden. {"month", "month-nonempty", "2011-12", "", true, "2017-11", "2017-11"}, // 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"}, // Nonempty textarea elements should be overridden. {"textarea", "textarea-nonempty", "Go\naway!", "", true, "some multi-\nline value", "some multi-\nline value"}, }; TestFormFillFunctions(kFormHtml, false, nullptr, field_cases, arraysize(field_cases), &FillFormIncludingNonFocusableElementsWrapper, &GetValueWrapper); } TEST_F(FormAutofillTest, PreviewForm) { TestPreviewForm(kFormHtml, false, nullptr); } TEST_F(FormAutofillTest, PreviewFormForUnownedForm) { TestPreviewForm(kUnownedFormHtml, true, nullptr); } TEST_F(FormAutofillTest, PreviewFormForUnownedUntitledForm) { // This test uses a mixed-case URL to be sure that the url match is not // case-sensitive. TestPreviewForm(kUnownedUntitledFormHtml, true, "http://example.test/Enter_Shipping_Address/"); } TEST_F(FormAutofillTest, PreviewFormForUnownedNonEnglishForm) { TestPreviewForm(kUnownedNonEnglishFormHtml, true, nullptr); } // Data that looks like an unowned form should NOT be matched unless an // additional indicator is present, such as title tag or url, to prevent false // positives. The fields that have an autocomplete attribute should match since // there is no chance of making a prediction error. TEST_F(FormAutofillTest, UnmatchedFormNoURL) { TestUnmatchedUnownedForm(kUnownedUntitledFormHtml, nullptr); } TEST_F(FormAutofillTest, UnmatchedFormPathWithoutKeywords) { TestUnmatchedUnownedForm(kUnownedUntitledFormHtml, "http://example.test/path_without_keywords"); } TEST_F(FormAutofillTest, UnmatchedFormKeywordInQueryOnly) { TestUnmatchedUnownedForm(kUnownedUntitledFormHtml, "http://example.test/search?q=checkout+in+query"); } TEST_F(FormAutofillTest, UnmatchedFormTitleWithoutKeywords) { std::string wrong_title_html( "This title has nothing to do with autofill"); wrong_title_html += kUnownedUntitledFormHtml; TestUnmatchedUnownedForm(wrong_title_html.c_str(), nullptr); } TEST_F(FormAutofillTest, UnmatchedFormNonASCII) { std::string html("Non-ASCII soft hyphen in the middle of " "keyword prevents a match here: check\xC2\xADout" ""); html.append(kUnownedUntitledFormHtml); TestUnmatchedUnownedForm(html.c_str(), nullptr); } TEST_F(FormAutofillTest, Labels) { ExpectJohnSmithLabels( "
" " " " " " " " " " " " " " " "
"); } TEST_F(FormAutofillTest, LabelsWithSpans) { ExpectJohnSmithLabels( "
" " " " " " " " " " " " " " " "
"); } // This test is different from FormAutofillTest.Labels in that the label // elements for= attribute is set to the name of the form control element it is // a label for instead of the id of the form control element. This is invalid // because the for= attribute must be set to the id of the form control element; // however, current label parsing code will extract the text from the previous // label element and apply it to the following input field. TEST_F(FormAutofillTest, InvalidLabels) { ExpectJohnSmithLabels( "
" " " " " " " " " " " " " " " "
"); } // This test has three form control elements, only one of which has a label // element associated with it. TEST_F(FormAutofillTest, OneLabelElement) { ExpectJohnSmithLabels( "
" " First name:" " " " " " " " Email:" " " " " "
"); } TEST_F(FormAutofillTest, LabelsInferredFromText) { ExpectJohnSmithLabels( "
" " First name:" " " " Last name:" " " " Email:" " " " " "
"); } TEST_F(FormAutofillTest, LabelsInferredFromParagraph) { ExpectJohnSmithLabels( "
" "

First name:

" "

Last name:

" " " "

Email:

" " " " " "
"); } TEST_F(FormAutofillTest, LabelsInferredFromBold) { ExpectJohnSmithLabels( "
" " First name:" " Last name:" " " " Email:" " " " " "
"); } TEST_F(FormAutofillTest, LabelsInferredPriorToImgOrBr) { ExpectJohnSmithLabels( "
" " First name:" " Last name:" " " " Email:
" " " " " "
"); } TEST_F(FormAutofillTest, LabelsInferredFromTableCell) { ExpectJohnSmithLabels( "
" "" " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
First name:
Last name:
Email:
" " " "
" "
"); } TEST_F(FormAutofillTest, LabelsInferredFromTableCellTH) { ExpectJohnSmithLabels( "
" "" " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
First name:
Last name:
Email:
" " " "
" "
"); } TEST_F(FormAutofillTest, LabelsInferredFromTableCellNested) { std::vector labels, names, values; labels.push_back(ASCIIToUTF16("First name: Bogus")); names.push_back(ASCIIToUTF16("firstname")); values.push_back(ASCIIToUTF16("John")); labels.push_back(ASCIIToUTF16("Last name:")); names.push_back(ASCIIToUTF16("lastname")); values.push_back(ASCIIToUTF16("Smith")); labels.push_back(ASCIIToUTF16("Email:")); names.push_back(ASCIIToUTF16("email")); values.push_back(ASCIIToUTF16("john@example.com")); ExpectLabels( "
" "" " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
" " " " First name:" " " " " " Bogus" " " " " " " " " " " "
" " " " Last name:" " " " " " " " " " " "
" " " " Email:" " " " " " " " " " " "
" " " "
" "
", labels, names, values); } TEST_F(FormAutofillTest, LabelsInferredFromTableEmptyTDs) { std::vector labels, names, values; labels.push_back(ASCIIToUTF16("* First Name")); names.push_back(ASCIIToUTF16("firstname")); values.push_back(ASCIIToUTF16("John")); labels.push_back(ASCIIToUTF16("* Last Name")); names.push_back(ASCIIToUTF16("lastname")); values.push_back(ASCIIToUTF16("Smith")); labels.push_back(ASCIIToUTF16("* Email")); names.push_back(ASCIIToUTF16("email")); values.push_back(ASCIIToUTF16("john@example.com")); ExpectLabels( "
" "" " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
" " *" " First Name" " " " " "
" " *" " Last Name" " " " " "
" " *" " Email" " " " " "
" " " "
" "
", labels, names, values); } TEST_F(FormAutofillTest, LabelsInferredFromPreviousTD) { std::vector labels, names, values; labels.push_back(ASCIIToUTF16("* First Name")); names.push_back(ASCIIToUTF16("firstname")); values.push_back(ASCIIToUTF16("John")); labels.push_back(ASCIIToUTF16("* Last Name")); names.push_back(ASCIIToUTF16("lastname")); values.push_back(ASCIIToUTF16("Smith")); labels.push_back(ASCIIToUTF16("* Email")); names.push_back(ASCIIToUTF16("email")); values.push_back(ASCIIToUTF16("john@example.com")); ExpectLabels( "
" "" " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
* First Name" " Bogus" " " " " "
* Last Name" " " "
* Email" " " "
" " " "
" "
", labels, names, values); } // " " " " " " " " " " " " *" " Middle Name" " " " " " " " " " " " " " " " " " *" " Last Name" " " " " " " " " " " " " " " " *" " Country" " " " " " " " " " " " " " " " *" " Email" " " " " " " " " " " " " " " " " " " " " " " " " "" "", labels, names, values, control_types); } TEST_F(FormAutofillTest, LabelsInferredFromTableLabels) { ExpectJohnSmithLabels( "
" "" " " " " " " " " " " " " " " " " " " "
" " " " " "
" " " " " "
" " " " " "
" "" "
"); } TEST_F(FormAutofillTest, LabelsInferredFromTableTDInterveningElements) { ExpectJohnSmithLabels( "
" "" " " " " " " " " " " " " " " " " " " "
" " First name:" "
" " " "
" " Last name:" "
" " " "
" " Email:" "
" " " "
" "" "
"); } // Verify that we correctly infer labels when the label text spans multiple // adjacent HTML elements, not separated by whitespace. TEST_F(FormAutofillTest, LabelsInferredFromTableAdjacentElements) { std::vector labels, names, values; labels.push_back(ASCIIToUTF16("*First Name")); names.push_back(ASCIIToUTF16("firstname")); values.push_back(ASCIIToUTF16("John")); labels.push_back(ASCIIToUTF16("*Last Name")); names.push_back(ASCIIToUTF16("lastname")); values.push_back(ASCIIToUTF16("Smith")); labels.push_back(ASCIIToUTF16("*Email")); names.push_back(ASCIIToUTF16("email")); values.push_back(ASCIIToUTF16("john@example.com")); ExpectLabels( "
" "" " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
" " *First Name" " " " " "
" " *Last Name" " " " " "
" " *Email" " " " " "
" " " "
" "
", labels, names, values); } // Verify that we correctly infer labels when the label text resides in the // previous row. TEST_F(FormAutofillTest, LabelsInferredFromTableRow) { std::vector labels, names, values; labels.push_back(ASCIIToUTF16("*First Name")); names.push_back(ASCIIToUTF16("firstname")); values.push_back(ASCIIToUTF16("John")); labels.push_back(ASCIIToUTF16("*Last Name")); names.push_back(ASCIIToUTF16("lastname")); values.push_back(ASCIIToUTF16("Smith")); labels.push_back(ASCIIToUTF16("*Email")); names.push_back(ASCIIToUTF16("email")); values.push_back(ASCIIToUTF16("john@example.com")); labels.push_back(ASCIIToUTF16("NAME")); names.push_back(ASCIIToUTF16("name2")); values.push_back(ASCIIToUTF16("John Smith")); labels.push_back(ASCIIToUTF16("EMAIL")); names.push_back(ASCIIToUTF16("email2")); values.push_back(ASCIIToUTF16("john@example2.com")); labels.push_back(ASCIIToUTF16("Phone")); names.push_back(ASCIIToUTF16("phone1")); values.push_back(ASCIIToUTF16("123")); labels.push_back(ASCIIToUTF16("Phone")); names.push_back(ASCIIToUTF16("phone2")); values.push_back(ASCIIToUTF16("456")); labels.push_back(ASCIIToUTF16("Phone")); names.push_back(ASCIIToUTF16("phone3")); values.push_back(ASCIIToUTF16("7890")); labels.push_back(ASCIIToUTF16("Credit Card Number")); names.push_back(ASCIIToUTF16("ccnumber")); values.push_back(ASCIIToUTF16("4444555544445555")); ExpectLabels( "
" "" " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
*First Name*Last Name*Email
" " " " " " " " " " " "
NAMEEMAIL
" " " " " " " "
Phone
" " " " " " " " " " " "
" " Credit Card Number" "
" " " "
" " " "
", labels, names, values); } // Verify that we correctly infer labels when enclosed within a list item. TEST_F(FormAutofillTest, LabelsInferredFromListItem) { std::vector labels, names, values; labels.push_back(ASCIIToUTF16("* Home Phone")); names.push_back(ASCIIToUTF16("areacode")); values.push_back(ASCIIToUTF16("415")); labels.push_back(ASCIIToUTF16("* Home Phone")); names.push_back(ASCIIToUTF16("prefix")); values.push_back(ASCIIToUTF16("555")); labels.push_back(ASCIIToUTF16("* Home Phone")); names.push_back(ASCIIToUTF16("suffix")); values.push_back(ASCIIToUTF16("1212")); ExpectLabels( "" "
" "
  • " " Bogus" "
  • " "
  • " " " " " " " " " "
  • " "
  • " " " "
  • " "
    " "", labels, names, values); } TEST_F(FormAutofillTest, LabelsInferredFromDefinitionList) { std::vector labels, names, values; labels.push_back(ASCIIToUTF16("* First name: Bogus")); names.push_back(ASCIIToUTF16("firstname")); values.push_back(ASCIIToUTF16("John")); labels.push_back(ASCIIToUTF16("Last name:")); names.push_back(ASCIIToUTF16("lastname")); values.push_back(ASCIIToUTF16("Smith")); labels.push_back(ASCIIToUTF16("Email:")); names.push_back(ASCIIToUTF16("email")); values.push_back(ASCIIToUTF16("john@example.com")); ExpectLabels( "
    " "
    " "
    " " " " *" " " " " " First name:" " " " " " Bogus" " " "
    " "
    " " " " " " " "
    " "
    " " " " Last name:" " " "
    " "
    " " " " " " " "
    " "
    " " " " Email:" " " "
    " "
    " " " " " " " "
    " "
    " "
    " " " "
    " "
    " "
    ", labels, names, values); } TEST_F(FormAutofillTest, LabelsInferredWithSameName) { std::vector labels, names, values; labels.push_back(ASCIIToUTF16("Address Line 1:")); names.push_back(ASCIIToUTF16("Address")); values.push_back(base::string16()); labels.push_back(ASCIIToUTF16("Address Line 2:")); names.push_back(ASCIIToUTF16("Address")); values.push_back(base::string16()); labels.push_back(ASCIIToUTF16("Address Line 3:")); names.push_back(ASCIIToUTF16("Address")); values.push_back(base::string16()); ExpectLabels( "
    " " Address Line 1:" " " " Address Line 2:" " " " Address Line 3:" " " " " "
    ", labels, names, values); } TEST_F(FormAutofillTest, LabelsInferredWithImageTags) { std::vector labels, names, values; labels.push_back(ASCIIToUTF16("Phone:")); names.push_back(ASCIIToUTF16("dayphone1")); values.push_back(base::string16()); labels.push_back(ASCIIToUTF16("")); names.push_back(ASCIIToUTF16("dayphone2")); values.push_back(base::string16()); labels.push_back(ASCIIToUTF16("")); names.push_back(ASCIIToUTF16("dayphone3")); values.push_back(base::string16()); labels.push_back(ASCIIToUTF16("ext.:")); names.push_back(ASCIIToUTF16("dayphone4")); values.push_back(base::string16()); labels.push_back(base::string16()); names.push_back(ASCIIToUTF16("dummy")); values.push_back(base::string16()); ExpectLabels( "
    " " Phone:" " " " " " -" " " " " " " " -" " " " " " ext.:" " " " " " " "
    ", labels, names, values); } TEST_F(FormAutofillTest, LabelsInferredFromDivTable) { ExpectJohnSmithLabels( "
    " "
    First name:
    " " " " " " " "
    " "
    Last name:
    " " " " " " " "
    " "
    Email:
    " " " " " " " "
    " "" "
    "); } TEST_F(FormAutofillTest, LabelsInferredFromDivSiblingTable) { ExpectJohnSmithLabels( "
    " "
    First name:
    " "
    " " " " " " " "
    " "
    Last name:
    " "
    " " " " " " " "
    " "
    Email:
    " "
    " " " " " " " "
    " "" "
    "); } TEST_F(FormAutofillTest, LabelsInferredFromLabelInDivTable) { ExpectJohnSmithLabels( "
    " "" "" "
    " " " "
    " "
    " " " "
    " "" "
    " " " " " " " "
    " "" "
    "); } TEST_F(FormAutofillTest, LabelsInferredFromDefinitionListRatherThanDivTable) { ExpectJohnSmithLabels( "
    " "
    This is not a label.
    " "
    " "
    " " " " First name:" " " "
    " "
    " " " " " " " "
    " "
    " " " " Last name:" " " "
    " "
    " " " " " " " "
    " "
    " " " " Email:" " " "
    " "
    " " " " " " " "
    " "
    " "
    " " " "
    " "
    " "
    " "
    "); } TEST_F(FormAutofillTest, FillFormMaxLength) { TestFillFormMaxLength( "
    " " " " " " " " " "
    ", false); } TEST_F(FormAutofillTest, FillFormMaxLengthForUnownedForm) { TestFillFormMaxLength( "delivery recipient info" "" "" "" "", true); } // This test uses negative values of the maxlength attribute for input elements. // In this case, the maxlength of the input elements is set to the default // maxlength (defined in WebKit.) TEST_F(FormAutofillTest, FillFormNegativeMaxLength) { TestFillFormNegativeMaxLength( "delivery recipient info" "
    " " " " " " " " " "
    ", false); } TEST_F(FormAutofillTest, FillFormNegativeMaxLengthForUnownedForm) { TestFillFormNegativeMaxLength( "delivery recipient info" "" "" "" "", true); } TEST_F(FormAutofillTest, FillFormEmptyName) { TestFillFormEmptyName( "
    " " " " " " " " " "
    ", false); } TEST_F(FormAutofillTest, FillFormEmptyNameForUnownedForm) { TestFillFormEmptyName( "delivery recipient info" "" "" "" "", true); } TEST_F(FormAutofillTest, FillFormEmptyFormNames) { TestFillFormEmptyFormNames( "
    " " " " " " " " " "
    " "
    " " " " " " " " " "
    ", false); } TEST_F(FormAutofillTest, FillFormEmptyFormNamesForUnownedForm) { TestFillFormEmptyFormNames( "enter delivery preferences" "" "" "" "" "" "" "", true); } TEST_F(FormAutofillTest, ThreePartPhone) { LoadHTML("
    " " Phone:" " " " -" " " " -" " " " ext.:" " " " " "
    "); WebFrame* frame = GetMainFrame(); ASSERT_NE(nullptr, frame); WebVector forms; frame->document().forms(forms); ASSERT_EQ(1U, forms.size()); FormData form; EXPECT_TRUE(WebFormElementToFormData(forms[0], WebFormControlElement(), EXTRACT_VALUE, &form, nullptr)); EXPECT_EQ(ASCIIToUTF16("TestForm"), form.name); EXPECT_EQ(GetCanonicalOriginForDocument(frame->document()), form.origin); EXPECT_FALSE(form.origin.is_empty()); EXPECT_EQ(GURL("http://cnn.com"), form.action); const std::vector& fields = form.fields; ASSERT_EQ(4U, fields.size()); FormFieldData expected; expected.form_control_type = "text"; expected.max_length = WebInputElement::defaultMaxLength(); expected.label = ASCIIToUTF16("Phone:"); expected.name = ASCIIToUTF16("dayphone1"); EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[0]); expected.label = ASCIIToUTF16(""); expected.name = ASCIIToUTF16("dayphone2"); EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[1]); expected.label = ASCIIToUTF16(""); expected.name = ASCIIToUTF16("dayphone3"); EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[2]); expected.label = ASCIIToUTF16("ext.:"); expected.name = ASCIIToUTF16("dayphone4"); EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[3]); } TEST_F(FormAutofillTest, MaxLengthFields) { LoadHTML("
    " " Phone:" " " " -" " " " -" " " " ext.:" " " " " " " " " "
    "); WebFrame* frame = GetMainFrame(); ASSERT_NE(nullptr, frame); WebVector forms; frame->document().forms(forms); ASSERT_EQ(1U, forms.size()); FormData form; EXPECT_TRUE(WebFormElementToFormData(forms[0], WebFormControlElement(), EXTRACT_VALUE, &form, nullptr)); EXPECT_EQ(ASCIIToUTF16("TestForm"), form.name); EXPECT_EQ(GetCanonicalOriginForDocument(frame->document()), form.origin); EXPECT_EQ(GURL("http://cnn.com"), form.action); const std::vector& fields = form.fields; ASSERT_EQ(6U, fields.size()); FormFieldData expected; expected.form_control_type = "text"; expected.label = ASCIIToUTF16("Phone:"); expected.name = ASCIIToUTF16("dayphone1"); expected.max_length = 3; EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[0]); expected.label = ASCIIToUTF16(""); expected.name = ASCIIToUTF16("dayphone2"); expected.max_length = 3; EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[1]); expected.label = ASCIIToUTF16(""); expected.name = ASCIIToUTF16("dayphone3"); expected.max_length = 4; EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[2]); expected.label = ASCIIToUTF16("ext.:"); expected.name = ASCIIToUTF16("dayphone4"); expected.max_length = 5; EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[3]); // When unspecified |size|, default is returned. expected.label.clear(); expected.name = ASCIIToUTF16("default1"); expected.max_length = WebInputElement::defaultMaxLength(); EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[4]); // When invalid |size|, default is returned. expected.label.clear(); expected.name = ASCIIToUTF16("invalid1"); expected.max_length = WebInputElement::defaultMaxLength(); EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[5]); } // This test re-creates the experience of typing in a field then selecting a // profile from the Autofill suggestions popup. The field that is being typed // into should be filled even though it's not technically empty. TEST_F(FormAutofillTest, FillFormNonEmptyField) { TestFillFormNonEmptyField( "
    " " " " " " " " " "
    ", false, nullptr, nullptr); } TEST_F(FormAutofillTest, FillFormNonEmptyFieldsWithDefaultValues) { TestFillFormNonEmptyField( "
    " " " " " " " " " "
    ", false, "Enter last name", "Enter email"); } TEST_F(FormAutofillTest, FillFormNonEmptyFieldForUnownedForm) { TestFillFormNonEmptyField( "delivery recipient info" "" "" "" "", true, nullptr, nullptr); } TEST_F(FormAutofillTest, ClearFormWithNode) { TestClearFormWithNode( "
    " " " " " " " " " " " " " " " " " " " " " "
    ", false); } TEST_F(FormAutofillTest, ClearFormWithNodeForUnownedForm) { TestClearFormWithNode( "store checkout" " " " " " " " " " " " " " " " " " " " " " ", true); } TEST_F(FormAutofillTest, ClearFormWithNodeContainingSelectOne) { TestClearFormWithNodeContainingSelectOne( "
    " " " " " " " " " "
    ", false); } TEST_F(FormAutofillTest, ClearFormWithNodeContainingSelectOneForUnownedForm) { TestClearFormWithNodeContainingSelectOne( "store checkout" "" "" "" "", true); } TEST_F(FormAutofillTest, ClearPreviewedFormWithElement) { TestClearPreviewedFormWithElement( "
    " " " " " " " " " " " " " "
    "); } TEST_F(FormAutofillTest, ClearPreviewedFormWithElementForUnownedForm) { TestClearPreviewedFormWithElement( "store checkout" "" "" "" "" "" ""); } TEST_F(FormAutofillTest, ClearPreviewedFormWithNonEmptyInitiatingNode) { TestClearPreviewedFormWithNonEmptyInitiatingNode( "
    " " " " " " " " " " " " " "
    "); } TEST_F(FormAutofillTest, ClearPreviewedFormWithNonEmptyInitiatingNodeForUnownedForm) { TestClearPreviewedFormWithNonEmptyInitiatingNode( "shipping details" "" "" "" "" "" ""); } TEST_F(FormAutofillTest, ClearPreviewedFormWithAutofilledInitiatingNode) { TestClearPreviewedFormWithAutofilledInitiatingNode( "
    " " " " " " " " " " " " " "
    "); } TEST_F(FormAutofillTest, ClearPreviewedFormWithAutofilledInitiatingNodeForUnownedForm) { TestClearPreviewedFormWithAutofilledInitiatingNode( "shipping details" "" "" "" "" "" ""); } // Autofill's "Clear Form" should clear only autofilled fields TEST_F(FormAutofillTest, ClearOnlyAutofilledFields) { TestClearOnlyAutofilledFields( "
    " " " " " " " " " " " "
    "); } TEST_F(FormAutofillTest, ClearOnlyAutofilledFieldsForUnownedForm) { TestClearOnlyAutofilledFields( "shipping details" "" "" "" "" ""); } // If we have multiple labels per id, the labels concatenated into label string. TEST_F(FormAutofillTest, MultipleLabelsPerElement) { std::vector labels, names, values; labels.push_back(ASCIIToUTF16("First Name:")); names.push_back(ASCIIToUTF16("firstname")); values.push_back(ASCIIToUTF16("John")); labels.push_back(ASCIIToUTF16("Last Name:")); names.push_back(ASCIIToUTF16("lastname")); values.push_back(ASCIIToUTF16("Smith")); labels.push_back(ASCIIToUTF16("Email: xxx@yyy.com")); names.push_back(ASCIIToUTF16("email")); values.push_back(ASCIIToUTF16("john@example.com")); ExpectLabels( "
    " " " " " " " " " " " " " " " " " " " " " "
    ", labels, names, values); } TEST_F(FormAutofillTest, ClickElement) { LoadHTML("" ""); WebFrame* frame = GetMainFrame(); ASSERT_NE(nullptr, frame); // Successful retrieval by id. WebElementDescriptor clicker; clicker.retrieval_method = WebElementDescriptor::ID; clicker.descriptor = "link"; EXPECT_TRUE(ClickElement(frame->document(), clicker)); // Successful retrieval by css selector. clicker.retrieval_method = WebElementDescriptor::CSS_SELECTOR; clicker.descriptor = "button[name='button']"; EXPECT_TRUE(ClickElement(frame->document(), clicker)); // Unsuccessful retrieval due to invalid CSS selector. clicker.descriptor = "^*&"; EXPECT_FALSE(ClickElement(frame->document(), clicker)); // Unsuccessful retrieval because element does not exist. clicker.descriptor = "#junk"; EXPECT_FALSE(ClickElement(frame->document(), clicker)); } TEST_F(FormAutofillTest, SelectOneAsText) { LoadHTML("
    " " " " " " " " " "
    "); WebFrame* frame = GetMainFrame(); ASSERT_NE(nullptr, frame); // Set the value of the select-one. WebSelectElement select_element = frame->document().getElementById("country").to(); select_element.setValue(WebString::fromUTF8("AL")); WebVector forms; frame->document().forms(forms); ASSERT_EQ(1U, forms.size()); FormData form; // Extract the country select-one value as text. EXPECT_TRUE(WebFormElementToFormData( forms[0], WebFormControlElement(), static_cast(EXTRACT_VALUE | EXTRACT_OPTION_TEXT), &form, nullptr)); EXPECT_EQ(ASCIIToUTF16("TestForm"), form.name); EXPECT_EQ(GetCanonicalOriginForDocument(frame->document()), form.origin); EXPECT_EQ(GURL("http://cnn.com"), form.action); const std::vector& fields = form.fields; ASSERT_EQ(3U, fields.size()); FormFieldData expected; expected.name = ASCIIToUTF16("firstname"); 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.name = ASCIIToUTF16("lastname"); 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.name = ASCIIToUTF16("country"); expected.value = ASCIIToUTF16("Albania"); expected.label.clear(); expected.form_control_type = "select-one"; expected.max_length = 0; EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[2]); form.fields.clear(); // Extract the country select-one value as value. EXPECT_TRUE(WebFormElementToFormData(forms[0], WebFormControlElement(), EXTRACT_VALUE, &form, nullptr)); EXPECT_EQ(ASCIIToUTF16("TestForm"), form.name); EXPECT_EQ(GetCanonicalOriginForDocument(frame->document()), form.origin); EXPECT_EQ(GURL("http://cnn.com"), form.action); ASSERT_EQ(3U, fields.size()); expected.name = ASCIIToUTF16("firstname"); 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.name = ASCIIToUTF16("lastname"); 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.name = ASCIIToUTF16("country"); expected.value = ASCIIToUTF16("AL"); expected.label.clear(); expected.form_control_type = "select-one"; expected.max_length = 0; EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[2]); } TEST_F(FormAutofillTest, UnownedFormElementsAndFieldSetsToFormDataFieldsets) { std::vector fieldsets; std::vector control_elements; const ExtractMask extract_mask = static_cast(EXTRACT_VALUE | EXTRACT_OPTIONS); LoadHTML("delivery info" "
    " "
    " " " " " " " " " "
    " "
    " " " " " "
    " "
    "); WebFrame* frame = GetMainFrame(); ASSERT_NE(nullptr, frame); control_elements = GetUnownedAutofillableFormFieldElements( frame->document().all(), &fieldsets); ASSERT_EQ(3U, control_elements.size()); ASSERT_EQ(2U, fieldsets.size()); FormData form; EXPECT_TRUE(UnownedCheckoutFormElementsAndFieldSetsToFormData( fieldsets, control_elements, nullptr, frame->document(), extract_mask, &form, nullptr)); EXPECT_TRUE(form.name.empty()); EXPECT_EQ(frame->document().url(), form.origin); EXPECT_FALSE(form.action.is_valid()); const std::vector& fields = form.fields; ASSERT_EQ(3U, fields.size()); FormFieldData expected; expected.form_control_type = "text"; expected.max_length = WebInputElement::defaultMaxLength(); expected.name = ASCIIToUTF16("firstname"); expected.value = ASCIIToUTF16("John"); expected.label = ASCIIToUTF16("First name:"); EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[0]); expected.name = ASCIIToUTF16("lastname"); expected.value = ASCIIToUTF16("Smith"); expected.label = ASCIIToUTF16("Last name:"); EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[1]); expected.name = ASCIIToUTF16("email"); expected.value = ASCIIToUTF16("john@example.com"); expected.label = ASCIIToUTF16("Email:"); EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[2]); } TEST_F(FormAutofillTest, UnownedFormElementsAndFieldSetsToFormDataControlOutsideOfFieldset) { std::vector fieldsets; std::vector control_elements; const ExtractMask extract_mask = static_cast(EXTRACT_VALUE | EXTRACT_OPTIONS); LoadHTML("shipping details" "
    " "
    " " " " " " " " " " " "
    " " " "
    "); WebFrame* frame = GetMainFrame(); ASSERT_NE(nullptr, frame); control_elements = GetUnownedAutofillableFormFieldElements( frame->document().all(), &fieldsets); ASSERT_EQ(3U, control_elements.size()); ASSERT_EQ(1U, fieldsets.size()); FormData form; EXPECT_TRUE(UnownedCheckoutFormElementsAndFieldSetsToFormData( fieldsets, control_elements, nullptr, frame->document(), extract_mask, &form, nullptr)); EXPECT_TRUE(form.name.empty()); EXPECT_EQ(frame->document().url(), form.origin); EXPECT_FALSE(form.action.is_valid()); const std::vector& fields = form.fields; ASSERT_EQ(3U, fields.size()); FormFieldData expected; expected.form_control_type = "text"; expected.max_length = WebInputElement::defaultMaxLength(); expected.name = ASCIIToUTF16("firstname"); expected.value = ASCIIToUTF16("John"); expected.label = ASCIIToUTF16("First name:"); EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[0]); expected.name = ASCIIToUTF16("lastname"); expected.value = ASCIIToUTF16("Smith"); expected.label = ASCIIToUTF16("Last name:"); EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[1]); expected.name = ASCIIToUTF16("email"); expected.value = ASCIIToUTF16("john@example.com"); expected.label = ASCIIToUTF16("Email:"); EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[2]); } TEST_F(FormAutofillTest, UnownedFormElementsAndFieldSetsToFormDataWithForm) { std::vector fieldsets; std::vector control_elements; const ExtractMask extract_mask = static_cast(EXTRACT_VALUE | EXTRACT_OPTIONS); LoadHTML(kFormHtml); WebFrame* frame = GetMainFrame(); ASSERT_NE(nullptr, frame); control_elements = GetUnownedAutofillableFormFieldElements( frame->document().all(), &fieldsets); ASSERT_TRUE(control_elements.empty()); ASSERT_TRUE(fieldsets.empty()); FormData form; EXPECT_FALSE(UnownedCheckoutFormElementsAndFieldSetsToFormData( fieldsets, control_elements, nullptr, frame->document(), extract_mask, &form, nullptr)); } TEST_F(FormAutofillTest, FormCache_ExtractNewForms) { struct { const char* html; const bool has_extracted_form; const bool is_form_tag; const bool is_formless_checkout; } test_cases[] = { // An empty form should not be extracted {"
    " "
    ", false, true, false}, // A form with less than three fields with no autocomplete type(s) should // not be extracted. {"
    " " " "
    ", false, true, false}, // A form with less than three fields with at least one autocomplete type // should be extracted. {"
    " " " "
    ", true, true, false}, // A form with three or more fields should be extracted. {"
    " " " " " " " " " "
    ", true, true, false}, // An input field with an autocomplete attribute outside of a form should // be extracted. The is_formless_checkout attribute should // then be true. {"" "", true, false, false}, // An input field without an autocomplete attribute outside of a form // should not be extracted. {"" "", false, false, false}, // A form with one field which is password should not be extracted. {"
    " " " "
    ", false, true, false}, // A form with two fields which are passwords should be extracted. {"
    " " " " " "
    ", true, true, false}, }; for (auto test_case : test_cases) { LoadHTML(test_case.html); WebFrame* web_frame = GetMainFrame(); ASSERT_NE(nullptr, web_frame); FormCache form_cache(*web_frame); std::vector forms = form_cache.ExtractNewForms(); EXPECT_EQ(test_case.has_extracted_form, forms.size() == 1); if (test_case.has_extracted_form) { EXPECT_EQ(test_case.is_form_tag, forms[0].is_form_tag); EXPECT_EQ(test_case.is_formless_checkout, forms[0].is_formless_checkout); } } } } // namespace form_util } // namespace autofill