summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorbenquan@chromium.org <benquan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-07-31 06:48:44 +0000
committerbenquan@chromium.org <benquan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-07-31 06:48:44 +0000
commitfe21c155e04010ba917b58633b6237ebca002b28 (patch)
tree841d61a70865a756676d6233abc063df1bf0efa7
parent28129a8b69ef2f45cd58fb7f0e4be796f5ec8a56 (diff)
downloadchromium_src-fe21c155e04010ba917b58633b6237ebca002b28.zip
chromium_src-fe21c155e04010ba917b58633b6237ebca002b28.tar.gz
chromium_src-fe21c155e04010ba917b58633b6237ebca002b28.tar.bz2
Add filter mask to autofill functions to filter fields that we do not want to fill.
BUG=263575 Review URL: https://chromiumcodereview.appspot.com/20643003 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@214597 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/renderer/autofill/form_autofill_browsertest.cc528
-rw-r--r--components/autofill/content/renderer/autofill_agent.cc2
-rw-r--r--components/autofill/content/renderer/form_autofill_util.cc41
-rw-r--r--components/autofill/content/renderer/form_autofill_util.h6
4 files changed, 273 insertions, 304 deletions
diff --git a/chrome/renderer/autofill/form_autofill_browsertest.cc b/chrome/renderer/autofill/form_autofill_browsertest.cc
index da76916..68fa4c7 100644
--- a/chrome/renderer/autofill/form_autofill_browsertest.cc
+++ b/chrome/renderer/autofill/form_autofill_browsertest.cc
@@ -5,10 +5,12 @@
#include <vector>
#include "base/format_macros.h"
+#include "base/metrics/field_trial.h"
#include "base/strings/string16.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
+#include "chrome/common/metrics/entropy_provider.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"
@@ -36,6 +38,36 @@ using WebKit::WebNode;
using WebKit::WebString;
using WebKit::WebVector;
+namespace {
+
+struct AutofillFieldCase {
+ 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.
+};
+
+static const char kFormHtml[] =
+ "<FORM name=\"TestForm\" action=\"http://buh.com\" method=\"post\">"
+ " <INPUT type=\"text\" id=\"firstname\"/>"
+ " <INPUT type=\"text\" id=\"lastname\"/>"
+ " <INPUT type=\"hidden\" id=\"imhidden\"/>"
+ " <INPUT type=\"text\" id=\"notempty\" value=\"Hi\"/>"
+ " <INPUT type=\"text\" autocomplete=\"off\" id=\"noautocomplete\"/>"
+ " <INPUT type=\"text\" disabled=\"disabled\" id=\"notenabled\"/>"
+ " <INPUT type=\"text\" readonly id=\"readonly\"/>"
+ " <INPUT type=\"text\" style=\"visibility: hidden\""
+ " id=\"invisible\"/>"
+ " <INPUT type=\"text\" style=\"display: none\" id=\"displaynone\"/>"
+ " <INPUT type=\"submit\" name=\"reply-send\" value=\"Send\"/>"
+ "</FORM>";
+
+} // namespace
+
namespace autofill {
class FormAutofillTest : public ChromeRenderViewTest {
@@ -109,6 +141,102 @@ class FormAutofillTest : public ChromeRenderViewTest {
ExpectLabels(html, labels, names, values);
}
+ typedef void (*FillFormFunction)(const FormData& form,
+ const WebInputElement& element);
+
+ typedef WebString (WebInputElement::*GetValueFunction)(void) const;
+
+ // Test FormFillxxx functions.
+ void TestFormFillFunctions(const char* html,
+ const AutofillFieldCase* field_cases,
+ size_t number_of_field_cases,
+ FillFormFunction fill_form_function,
+ GetValueFunction get_value_function) {
+ LoadHTML(html);
+
+ WebFrame* web_frame = GetMainFrame();
+ ASSERT_NE(static_cast<WebFrame*>(NULL), web_frame);
+
+ FormCache form_cache;
+ std::vector<FormData> forms;
+ form_cache.ExtractForms(*web_frame, &forms);
+ ASSERT_EQ(1U, forms.size());
+
+ // Get the input element we want to find.
+ WebElement element = web_frame->document().getElementById("firstname");
+ WebInputElement input_element = element.to<WebInputElement>();
+
+ // Find the form that contains the input element.
+ FormData form_data;
+ FormFieldData field;
+ EXPECT_TRUE(
+ FindFormAndFieldForInputElement(input_element,
+ &form_data,
+ &field,
+ autofill::REQUIRE_AUTOCOMPLETE));
+ EXPECT_EQ(ASCIIToUTF16("TestForm"), form_data.name);
+ EXPECT_EQ(GURL(web_frame->document().url()), form_data.origin);
+ EXPECT_EQ(GURL("http://buh.com"), form_data.action);
+
+ const std::vector<FormFieldData>& fields = form_data.fields;
+ ASSERT_EQ(number_of_field_cases, fields.size());
+
+ FormFieldData expected;
+ expected.form_control_type = "text";
+ expected.max_length = WebInputElement::defaultMaxLength();
+
+ // 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.name = ASCIIToUTF16(field_cases[i].name);
+ expected.value = ASCIIToUTF16(field_cases[i].initial_value);
+ 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);
+ }
+
+ // 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) {
+ ValidteFilledField(field_cases[i], get_value_function);
+ }
+ }
+
+ // Validate an Autofilled field.
+ void ValidteFilledField(const AutofillFieldCase& field_case,
+ GetValueFunction get_value_function) {
+ SCOPED_TRACE(base::StringPrintf("Verify autofilled value for field %s",
+ field_case.name));
+ WebInputElement input_element = GetMainFrame()->document().getElementById(
+ ASCIIToUTF16(field_case.name)).to<WebInputElement>();
+ EXPECT_EQ(field_case.should_be_autofilled, input_element.isAutofilled());
+ if (field_case.should_be_autofilled) {
+ EXPECT_EQ(ASCIIToUTF16(field_case.expected_value),
+ (input_element.*get_value_function)());
+ } else {
+ WebString expected_value = ASCIIToUTF16(field_case.expected_value);
+ if (expected_value.isEmpty())
+ EXPECT_TRUE((input_element.*get_value_function)().isEmpty());
+ else
+ EXPECT_EQ(expected_value, (input_element.*get_value_function)());
+ }
+ }
+
+ static void FillFormForAllFieldsWrapper(const FormData& form,
+ const WebInputElement& element) {
+ FillFormForAllElements(form, element.form());
+ }
+
+ static void FillFormIncludingNonFocusableElementsWrapper(
+ const FormData& form,
+ const WebInputElement& element) {
+ FillFormIncludingNonFocusableElements(form, element.form());
+ }
+
private:
DISALLOW_COPY_AND_ASSIGN(FormAutofillTest);
};
@@ -835,230 +963,118 @@ TEST_F(FormAutofillTest, FindForm) {
EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields2[2]);
}
+// Test regular FillForm function.
TEST_F(FormAutofillTest, FillForm) {
- LoadHTML("<FORM name=\"TestForm\" action=\"http://buh.com\" method=\"post\">"
- " <INPUT type=\"text\" id=\"firstname\"/>"
- " <INPUT type=\"text\" id=\"lastname\"/>"
- " <INPUT type=\"hidden\" id=\"imhidden\"/>"
- " <INPUT type=\"text\" id=\"notempty\" value=\"Hi\"/>"
- " <INPUT type=\"text\" autocomplete=\"off\" id=\"noautocomplete\"/>"
- " <INPUT type=\"text\" disabled=\"disabled\" id=\"notenabled\"/>"
- " <INPUT type=\"text\" readonly id=\"readonly\"/>"
- " <INPUT type=\"text\" style=\"visibility: hidden\""
- " id=\"invisible\"/>"
- " <INPUT type=\"text\" style=\"display: none\" id=\"displaynone\"/>"
- " <INPUT type=\"submit\" name=\"reply-send\" value=\"Send\"/>"
- "</FORM>");
-
- WebFrame* web_frame = GetMainFrame();
- ASSERT_NE(static_cast<WebFrame*>(NULL), web_frame);
-
- FormCache form_cache;
- std::vector<FormData> forms;
- form_cache.ExtractForms(*web_frame, &forms);
- ASSERT_EQ(1U, forms.size());
-
- // Get the input element we want to find.
- WebElement element = web_frame->document().getElementById("firstname");
- WebInputElement input_element = element.to<WebInputElement>();
-
- // Find the form that contains the input element.
- FormData form;
- FormFieldData field;
- EXPECT_TRUE(FindFormAndFieldForInputElement(input_element, &form, &field,
- autofill::REQUIRE_AUTOCOMPLETE));
- EXPECT_EQ(ASCIIToUTF16("TestForm"), form.name);
- EXPECT_EQ(GURL(web_frame->document().url()), form.origin);
- EXPECT_EQ(GURL("http://buh.com"), form.action);
-
- const std::vector<FormFieldData>& fields = form.fields;
- ASSERT_EQ(7U, fields.size());
-
- FormFieldData expected;
- expected.form_control_type = "text";
- expected.max_length = WebInputElement::defaultMaxLength();
-
- expected.name = ASCIIToUTF16("firstname");
- expected.value = string16();
- EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[0]);
-
- expected.name = ASCIIToUTF16("lastname");
- expected.value = string16();
- EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[1]);
-
- expected.name = ASCIIToUTF16("notempty");
- expected.value = ASCIIToUTF16("Hi");
- EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[2]);
-
- expected.name = ASCIIToUTF16("notenabled");
- expected.value = string16();
- EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[3]);
-
- expected.name = ASCIIToUTF16("readonly");
- expected.value = string16();
- EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[4]);
-
- expected.name = ASCIIToUTF16("invisible");
- expected.value = string16();
- EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[5]);
-
- expected.name = ASCIIToUTF16("displaynone");
- expected.value = string16();
- EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[6]);
-
- // Fill the form.
- form.fields[0].value = ASCIIToUTF16("Wyatt");
- form.fields[1].value = ASCIIToUTF16("Earp");
- form.fields[2].value = ASCIIToUTF16("Alpha");
- form.fields[3].value = ASCIIToUTF16("Beta");
- form.fields[4].value = ASCIIToUTF16("Gamma");
- form.fields[5].value = ASCIIToUTF16("Delta");
- form.fields[6].value = ASCIIToUTF16("Epsilon");
- FillForm(form, input_element);
-
- // Verify the filled elements.
- WebDocument document = web_frame->document();
- WebInputElement firstname =
- document.getElementById("firstname").to<WebInputElement>();
- EXPECT_TRUE(firstname.isAutofilled());
- EXPECT_EQ(ASCIIToUTF16("Wyatt"), firstname.value());
- EXPECT_EQ(5, firstname.selectionStart());
- EXPECT_EQ(5, firstname.selectionEnd());
-
- WebInputElement lastname =
- document.getElementById("lastname").to<WebInputElement>();
- EXPECT_TRUE(lastname.isAutofilled());
- EXPECT_EQ(ASCIIToUTF16("Earp"), lastname.value());
-
- // Non-empty fields are not filled.
- WebInputElement notempty =
- document.getElementById("notempty").to<WebInputElement>();
- EXPECT_FALSE(notempty.isAutofilled());
- EXPECT_EQ(ASCIIToUTF16("Hi"), notempty.value());
-
- // autocomplete=off fields are not filled.
- WebInputElement noautocomplete =
- document.getElementById("noautocomplete").to<WebInputElement>();
- EXPECT_FALSE(noautocomplete.isAutofilled());
- EXPECT_TRUE(noautocomplete.value().isEmpty());
-
- // Disabled fields are not filled.
- WebInputElement notenabled =
- document.getElementById("notenabled").to<WebInputElement>();
- EXPECT_FALSE(notenabled.isAutofilled());
- EXPECT_TRUE(notenabled.value().isEmpty());
-
- // Read-only fields are not filled.
- WebInputElement readonly =
- document.getElementById("readonly").to<WebInputElement>();
- EXPECT_FALSE(readonly.isAutofilled());
- EXPECT_TRUE(readonly.value().isEmpty());
+ static const AutofillFieldCase field_cases[] = {
+ // fields: name, initial_value, autocomplete_attribute,
+ // should_be_autofilled, autofill_value, expected_value
+
+ // Regular empty fields (firstname & lastname) should be autofilled.
+ {"firstname", "", "", true, "filled firstname", "filled firstname"},
+ {"lastname", "", "", true, "filled lastname", "filled lastname"},
+ // hidden fields should not be extracted to form_data.
+ // Non empty fields should not be autofilled.
+ {"notempty", "Hi", "", false, "filled notempty", "Hi"},
+ // "noautocomplete" should not be extracted to form_data.
+ // Disabled fields should not be autofilled.
+ {"notenabled", "", "", false, "filled notenabled", ""},
+ // Readonly fields should not be autofilled.
+ {"readonly", "", "", false, "filled readonly", ""},
+ // Fields with "visibility: hidden" should not be autofilled.
+ {"invisible", "", "", false, "filled invisible", ""},
+ // Fields with "display:none" should not be autofilled.
+ {"displaynone", "", "", false, "filled displaynone", ""},
+ };
+ TestFormFillFunctions(kFormHtml, field_cases, arraysize(field_cases),
+ FillForm, &WebInputElement::value);
+ // Verify preview selection.
+ WebInputElement firstname = GetMainFrame()->document().
+ getElementById("firstname").to<WebInputElement>();
+ EXPECT_EQ(16, firstname.selectionStart());
+ EXPECT_EQ(16, firstname.selectionEnd());
+}
- // |visibility:hidden| fields are not filled.
- WebInputElement invisible =
- document.getElementById("invisible").to<WebInputElement>();
- EXPECT_FALSE(invisible.isAutofilled());
- EXPECT_TRUE(invisible.value().isEmpty());
+TEST_F(FormAutofillTest, FillFormIncludingNonFocusableElements) {
+ static const AutofillFieldCase field_cases[] = {
+ // fields: name, initial_value, autocomplete_attribute,
+ // should_be_autofilled, autofill_value, expected_value
+
+ // Regular empty fields (firstname & lastname) should be autofilled.
+ {"firstname", "", "", true, "filled firstname", "filled firstname"},
+ {"lastname", "", "", true, "filled lastname", "filled lastname"},
+ // hidden fields should not be extracted to form_data.
+ // Non empty fields should be overrided.
+ {"notempty", "Hi", "", true, "filled notempty", "filled notempty"},
+ // "noautocomplete" should not be extracted to form_data.
+ // Disabled fields should not be autofilled.
+ {"notenabled", "", "", false, "filled notenabled", ""},
+ // Readonly fields should not be autofilled.
+ {"readonly", "", "", false, "filled readonly", ""},
+ // Fields with "visibility: hidden" should also be autofilled.
+ {"invisible", "", "", true, "filled invisible", "filled invisible"},
+ // Fields with "display:none" should also be autofilled.
+ {"displaynone", "", "", true, "filled displaynone", "filled displaynone"},
+ };
+ TestFormFillFunctions(kFormHtml, field_cases, arraysize(field_cases),
+ &FillFormIncludingNonFocusableElementsWrapper,
+ &WebInputElement::value);
+}
- // |display:none| fields are not filled.
- WebInputElement display_none =
- document.getElementById("displaynone").to<WebInputElement>();
- EXPECT_FALSE(display_none.isAutofilled());
- EXPECT_TRUE(display_none.value().isEmpty());
+TEST_F(FormAutofillTest, FillFormForAllElements) {
+ static const AutofillFieldCase field_cases[] = {
+ // fields: name, initial_value, autocomplete_attribute,
+ // should_be_autofilled, autofill_value, expected_value
+
+ // All fields except hidden fields (type="hidden") should be Autofilled.
+ {"firstname", "", "", true, "filled firstname", "filled firstname"},
+ {"lastname", "", "", true, "filled lastname", "filled lastname"},
+ // hidden fields should not be extracted to form_data.
+ {"notempty", "Hi", "", true, "filled notempty", "filled notempty"},
+ {"noautocomplete", "", "off", true, "filled noautocomplete",
+ "filled noautocomplete"},
+ {"notenabled", "", "", true, "filled notenabled", "filled notenabled"},
+ {"readonly", "", "", true, "filled readonly", "filled readonly"},
+ {"invisible", "", "", true, "filled invisible", "filled invisible"},
+ {"displaynone", "", "", true, "filled displaynone", "filled displaynone"},
+ };
+ // Enable Autocheckout because |FillFormForAllElements| is only used by
+ // Autocheckout.
+ base::FieldTrialList field_trial_list(
+ new metrics::SHA1EntropyProvider("foo"));
+ base::FieldTrialList::CreateFieldTrial("Autocheckout", "Yes");
+ TestFormFillFunctions(kFormHtml, field_cases, arraysize(field_cases),
+ &FillFormForAllFieldsWrapper, &WebInputElement::value);
}
TEST_F(FormAutofillTest, PreviewForm) {
- LoadHTML("<FORM name=\"TestForm\" action=\"http://buh.com\" method=\"post\">"
- " <INPUT type=\"text\" id=\"firstname\"/>"
- " <INPUT type=\"text\" id=\"lastname\"/>"
- " <INPUT type=\"text\" id=\"notempty\" value=\"Hi\"/>"
- " <INPUT type=\"text\" autocomplete=\"off\" id=\"noautocomplete\"/>"
- " <INPUT type=\"text\" disabled=\"disabled\" id=\"notenabled\"/>"
- " <INPUT type=\"submit\" name=\"reply-send\" value=\"Send\"/>"
- "</FORM>");
-
- WebFrame* web_frame = GetMainFrame();
- ASSERT_NE(static_cast<WebFrame*>(NULL), web_frame);
-
- FormCache form_cache;
- std::vector<FormData> forms;
- form_cache.ExtractForms(*web_frame, &forms);
- ASSERT_EQ(1U, forms.size());
-
- // Get the input element we want to find.
- WebElement element = web_frame->document().getElementById("firstname");
- WebInputElement input_element = element.to<WebInputElement>();
-
- // Find the form that contains the input element.
- FormData form;
- FormFieldData field;
- EXPECT_TRUE(FindFormAndFieldForInputElement(input_element, &form, &field,
- autofill::REQUIRE_AUTOCOMPLETE));
- EXPECT_EQ(ASCIIToUTF16("TestForm"), form.name);
- EXPECT_EQ(GURL(web_frame->document().url()), form.origin);
- EXPECT_EQ(GURL("http://buh.com"), form.action);
-
- const std::vector<FormFieldData>& fields = form.fields;
- ASSERT_EQ(4U, fields.size());
-
- FormFieldData expected;
- expected.form_control_type = "text";
- expected.max_length = WebInputElement::defaultMaxLength();
-
- expected.name = ASCIIToUTF16("firstname");
- expected.value = string16();
- EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[0]);
-
- expected.name = ASCIIToUTF16("lastname");
- expected.value = string16();
- EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[1]);
-
- expected.name = ASCIIToUTF16("notempty");
- expected.value = ASCIIToUTF16("Hi");
- EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[2]);
-
- expected.name = ASCIIToUTF16("notenabled");
- expected.value = string16();
- EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[3]);
-
- // Preview the form.
- form.fields[0].value = ASCIIToUTF16("Wyatt");
- form.fields[1].value = ASCIIToUTF16("Earp");
- form.fields[2].value = ASCIIToUTF16("Alpha");
- form.fields[3].value = ASCIIToUTF16("Beta");
- PreviewForm(form, input_element);
+ static const char* html =
+ "<FORM name=\"TestForm\" action=\"http://buh.com\" method=\"post\">"
+ " <INPUT type=\"text\" id=\"firstname\"/>"
+ " <INPUT type=\"text\" id=\"lastname\"/>"
+ " <INPUT type=\"text\" id=\"notempty\" value=\"Hi\"/>"
+ " <INPUT type=\"text\" autocomplete=\"off\" id=\"noautocomplete\"/>"
+ " <INPUT type=\"text\" disabled=\"disabled\" id=\"notenabled\"/>"
+ " <INPUT type=\"submit\" name=\"reply-send\" value=\"Send\"/>"
+ "</FORM>";
+
+ static const AutofillFieldCase field_cases[] = {
+ // Normal empty fields should be previewed.
+ {"firstname", "", "", true, "suggested firstname", "suggested firstname"},
+ {"lastname", "", "", true, "suggested lastname", "suggested lastname"},
+ // Non empty fields should not be previewed.
+ {"notempty", "Hi", "", false, "filled notempty", ""},
+ // "noautocomplete" should not be extracted to form_data.
+ // Disabled fields should not be previewed.
+ {"notenabled", "", "", false, "filled notenabled", ""},
+ };
+ TestFormFillFunctions(html, field_cases, arraysize(field_cases), &PreviewForm,
+ &WebInputElement::suggestedValue);
- // Verify the previewed elements.
- WebDocument document = web_frame->document();
- WebInputElement firstname =
- document.getElementById("firstname").to<WebInputElement>();
- EXPECT_TRUE(firstname.isAutofilled());
- EXPECT_EQ(ASCIIToUTF16("Wyatt"), firstname.suggestedValue());
+ // Verify preview selection.
+ WebInputElement firstname = GetMainFrame()->document().
+ getElementById("firstname").to<WebInputElement>();
EXPECT_EQ(0, firstname.selectionStart());
- EXPECT_EQ(5, firstname.selectionEnd());
-
- WebInputElement lastname =
- document.getElementById("lastname").to<WebInputElement>();
- EXPECT_TRUE(lastname.isAutofilled());
- EXPECT_EQ(ASCIIToUTF16("Earp"), lastname.suggestedValue());
-
- // Non-empty fields are not previewed.
- WebInputElement notempty =
- document.getElementById("notempty").to<WebInputElement>();
- EXPECT_FALSE(notempty.isAutofilled());
- EXPECT_TRUE(notempty.suggestedValue().isEmpty());
-
- // autocomplete=off fields are not previewed.
- WebInputElement noautocomplete =
- document.getElementById("noautocomplete").to<WebInputElement>();
- EXPECT_FALSE(noautocomplete.isAutofilled());
- EXPECT_TRUE(noautocomplete.suggestedValue().isEmpty());
-
- // Disabled fields are not previewed.
- WebInputElement notenabled =
- document.getElementById("notenabled").to<WebInputElement>();
- EXPECT_FALSE(notenabled.isAutofilled());
- EXPECT_TRUE(notenabled.suggestedValue().isEmpty());
+ EXPECT_EQ(19, firstname.selectionEnd());
}
TEST_F(FormAutofillTest, Labels) {
@@ -2260,86 +2276,6 @@ TEST_F(FormAutofillTest, FillFormEmptyFormNames) {
EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields2[2]);
}
-TEST_F(FormAutofillTest, FillFormIncludingNonFocusableElements) {
- LoadHTML("<FORM action=\"http://abc.com\" method=\"post\" id=\"formid\">"
- " <INPUT type=\"text\" id=\"firstname\" value=\"not-firstname\"/>"
- " <INPUT type=\"text\" id=\"lastname\"/>"
- " <INPUT type=\"text\" id=\"middlename\"/>"
- " <INPUT type=\"submit\" value=\"Send\"/>"
- "</FORM>"
- "<FORM action=\"http://abc.com\" method=\"post\">"
- " <INPUT type=\"text\" id=\"apple\"/>"
- " <INPUT type=\"text\" id=\"banana\"/>"
- " <INPUT type=\"text\" id=\"cantelope\"/>"
- " <INPUT type=\"submit\" value=\"Send\"/>"
- "</FORM>");
-
- WebFrame* web_frame = GetMainFrame();
- ASSERT_NE(static_cast<WebFrame*>(NULL), web_frame);
-
- FormCache form_cache;
- std::vector<FormData> forms;
- form_cache.ExtractForms(*web_frame, &forms);
- ASSERT_EQ(2U, forms.size());
-
- // Get the input element we want to find.
- WebElement firstname = web_frame->document().getElementById("firstname");
- WebInputElement input_element = firstname.to<WebInputElement>();
- WebElement formid = web_frame->document().getElementById("formid");
- WebFormElement formid_element = formid.to<WebFormElement>();
-
- // Find the form that contains the input element.
- FormData form;
- FormFieldData field;
- EXPECT_TRUE(FindFormAndFieldForInputElement(input_element, &form, &field,
- autofill::REQUIRE_NONE));
- EXPECT_EQ(ASCIIToUTF16("formid"), form.name);
- EXPECT_EQ(GURL(web_frame->document().url()), form.origin);
- EXPECT_EQ(GURL("http://abc.com"), form.action);
- const std::vector<FormFieldData>& fields = form.fields;
- ASSERT_EQ(3U, fields.size());
- FormFieldData expected;
- expected.form_control_type = "text";
- expected.max_length = WebInputElement::defaultMaxLength();
- expected.is_autofilled = false;
- expected.name = ASCIIToUTF16("firstname");
- expected.value = ASCIIToUTF16("not-firstname");
- EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[0]);
- expected.name = ASCIIToUTF16("lastname");
- expected.value = string16();
- EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[1]);
-
- // Fill the form.
- form.fields[0].value = ASCIIToUTF16("FirstName");
- form.fields[1].value = ASCIIToUTF16("LastName");
- FillFormIncludingNonFocusableElements(form, formid_element);
-
- // Find the newly-filled form that contains the input element, and verify
- // if all fields have been filled.
- FormData form2;
- FormFieldData field2;
- EXPECT_TRUE(FindFormAndFieldForInputElement(input_element, &form2, &field2,
- autofill::REQUIRE_NONE));
- EXPECT_EQ(ASCIIToUTF16("formid"), form2.name);
- EXPECT_EQ(GURL(web_frame->document().url()), form2.origin);
- EXPECT_EQ(GURL("http://abc.com"), form2.action);
- std::vector<FormFieldData>& fields2 = form2.fields;
- ASSERT_EQ(3U, fields2.size());
- expected.form_control_type = "text";
- expected.max_length = WebInputElement::defaultMaxLength();
- // All of the fields should be autofilled now.
- expected.is_autofilled = true;
-
- // fields[0].value should have changed from not-firstname to FirstName.
- expected.name = ASCIIToUTF16("firstname");
- expected.value = ASCIIToUTF16("FirstName");
- EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields2[0]);
-
- expected.name = ASCIIToUTF16("lastname");
- expected.value = ASCIIToUTF16("LastName");
- EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields2[1]);
-}
-
TEST_F(FormAutofillTest, ThreePartPhone) {
LoadHTML("<FORM name=\"TestForm\" action=\"http://cnn.com\" method=\"post\">"
" Phone:"
diff --git a/components/autofill/content/renderer/autofill_agent.cc b/components/autofill/content/renderer/autofill_agent.cc
index a48f573..9434971 100644
--- a/components/autofill/content/renderer/autofill_agent.cc
+++ b/components/autofill/content/renderer/autofill_agent.cc
@@ -581,7 +581,7 @@ void AutofillAgent::OnFillFormsAndClick(
// Fill the form.
for (size_t i = 0; i < forms.size(); ++i)
- FillFormIncludingNonFocusableElements(forms[i], form_elements_[i]);
+ FillFormForAllElements(forms[i], form_elements_[i]);
// Click elements in click_elements_after_form_fill.
for (size_t i = 0; i < click_elements_after_form_fill.size(); ++i) {
diff --git a/components/autofill/content/renderer/form_autofill_util.cc b/components/autofill/content/renderer/form_autofill_util.cc
index 4c36547..55f3a03 100644
--- a/components/autofill/content/renderer/form_autofill_util.cc
+++ b/components/autofill/content/renderer/form_autofill_util.cc
@@ -52,6 +52,17 @@ namespace {
// The maximum length allowed for form data.
const size_t kMaxDataLength = 1024;
+// A bit field mask for FillForm functions to not fill some fields.
+enum FieldFilterMask {
+ FILTER_NONE = 0,
+ FILTER_DISABLED_ELEMENTS = 1 << 0,
+ FILTER_READONLY_ELEMENTS = 1 << 1,
+ FILTER_NON_FOCUSABLE_ELEMENTS = 1 << 2,
+ FILTER_ALL_NON_EDITIABLE_ELEMENTS = FILTER_DISABLED_ELEMENTS |
+ FILTER_READONLY_ELEMENTS |
+ FILTER_NON_FOCUSABLE_ELEMENTS,
+};
+
bool IsOptionElement(const WebElement& element) {
CR_DEFINE_STATIC_LOCAL(WebString, kOption, ("option"));
return element.hasTagName(kOption);
@@ -463,7 +474,7 @@ typedef void (*Callback)(const FormFieldData&,
void ForEachMatchingFormField(const WebFormElement& form_element,
const WebElement& initiating_element,
const FormData& data,
- bool only_focusable_elements,
+ FieldFilterMask filters,
bool force_override,
Callback callback) {
std::vector<WebFormControlElement> control_elements;
@@ -504,8 +515,9 @@ void ForEachMatchingFormField(const WebFormElement& form_element,
!is_initiating_element && !input_element->value().isEmpty())
continue;
- if (!element->isEnabled() || element->isReadOnly() ||
- (only_focusable_elements && !element->isFocusable()))
+ if (((filters & FILTER_DISABLED_ELEMENTS) && !element->isEnabled()) ||
+ ((filters & FILTER_READONLY_ELEMENTS) && element->isReadOnly()) ||
+ ((filters & FILTER_NON_FOCUSABLE_ELEMENTS) && !element->isFocusable()))
continue;
callback(data.fields[i], is_initiating_element, element);
@@ -930,20 +942,35 @@ void FillForm(const FormData& form, const WebInputElement& element) {
ForEachMatchingFormField(form_element,
element,
form,
- true, /* only_focusable_elements */
+ FILTER_ALL_NON_EDITIABLE_ELEMENTS,
false, /* dont force override */
&FillFormField);
}
void FillFormIncludingNonFocusableElements(const FormData& form_data,
- const WebFormElement& form_element) {
+ const WebFormElement& form_element) {
+ if (form_element.isNull())
+ return;
+
+ FieldFilterMask filter_mask = static_cast<FieldFilterMask>(
+ FILTER_DISABLED_ELEMENTS | FILTER_READONLY_ELEMENTS);
+ ForEachMatchingFormField(form_element,
+ WebInputElement(),
+ form_data,
+ filter_mask,
+ true, /* force override */
+ &FillFormField);
+}
+
+void FillFormForAllElements(const FormData& form_data,
+ const WebFormElement& form_element) {
if (form_element.isNull())
return;
ForEachMatchingFormField(form_element,
WebInputElement(),
form_data,
- false, /* only_focusable_elements */
+ FILTER_NONE,
true, /* force override */
&FillFormField);
}
@@ -956,7 +983,7 @@ void PreviewForm(const FormData& form, const WebInputElement& element) {
ForEachMatchingFormField(form_element,
element,
form,
- true, /* only_focusable_elements */
+ FILTER_ALL_NON_EDITIABLE_ELEMENTS,
false, /* dont force override */
&PreviewFormField);
}
diff --git a/components/autofill/content/renderer/form_autofill_util.h b/components/autofill/content/renderer/form_autofill_util.h
index aec0614..5a12418 100644
--- a/components/autofill/content/renderer/form_autofill_util.h
+++ b/components/autofill/content/renderer/form_autofill_util.h
@@ -118,6 +118,12 @@ void FillFormIncludingNonFocusableElements(
const FormData& form_data,
const WebKit::WebFormElement& form_element);
+// Fills all (including disabled, read-only and non-focusable) form control
+// elements within |form_element| with field data from |form_data|.
+void FillFormForAllElements(
+ const FormData& form_data,
+ const WebKit::WebFormElement& form_element);
+
// Previews the form represented by |form|. |element| is the input element that
// initiated the preview process.
void PreviewForm(const FormData& form,