Commit 9be8ba95 authored by ziran.sun@samsung.com's avatar ziran.sun@samsung.com

Add autofill preview support for Textarea

BUG=314976
R=isherman@chromium.org

Review URL: https://codereview.chromium.org/112663005

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@243977 0039d316-1c4b-4281-b951-d872f2087c98
parent c67e7090
...@@ -161,7 +161,7 @@ class FormAutofillTest : public ChromeRenderViewTest { ...@@ -161,7 +161,7 @@ class FormAutofillTest : public ChromeRenderViewTest {
typedef void (*FillFormFunction)(const FormData& form, typedef void (*FillFormFunction)(const FormData& form,
const WebInputElement& element); const WebInputElement& element);
typedef WebString (WebInputElement::*GetValueFunction)(void) const; typedef WebString (*GetValueFunction)(WebFormControlElement element);
// Test FormFillxxx functions. // Test FormFillxxx functions.
void TestFormFillFunctions(const char* html, void TestFormFillFunctions(const char* html,
...@@ -235,13 +235,11 @@ class FormAutofillTest : public ChromeRenderViewTest { ...@@ -235,13 +235,11 @@ class FormAutofillTest : public ChromeRenderViewTest {
if (element.formControlType() == "select-one") { if (element.formControlType() == "select-one") {
value = element.to<WebSelectElement>().value(); value = element.to<WebSelectElement>().value();
} else if (element.formControlType() == "textarea") { } else if (element.formControlType() == "textarea") {
value = element.to<WebTextAreaElement>().value(); value = get_value_function(element);
} else { } else {
ASSERT_TRUE(element.formControlType() == "text" || ASSERT_TRUE(element.formControlType() == "text" ||
element.formControlType() == "month"); element.formControlType() == "month");
WebInputElement input_element = GetMainFrame()->document().getElementById( value = get_value_function(element);
ASCIIToUTF16(field_case.name)).to<WebInputElement>();
value = (input_element.*get_value_function)();
} }
const WebString expected_value = ASCIIToUTF16(field_case.expected_value); const WebString expected_value = ASCIIToUTF16(field_case.expected_value);
...@@ -264,6 +262,20 @@ class FormAutofillTest : public ChromeRenderViewTest { ...@@ -264,6 +262,20 @@ class FormAutofillTest : public ChromeRenderViewTest {
FillFormIncludingNonFocusableElements(form, element.form()); FillFormIncludingNonFocusableElements(form, element.form());
} }
static WebString GetValueWrapper(WebFormControlElement element) {
if (element.formControlType() == "textarea")
return element.to<WebTextAreaElement>().value();
return element.to<WebInputElement>().value();
}
static WebString GetSuggestedValueWrapper(WebFormControlElement element) {
if (element.formControlType() == "textarea")
return element.to<WebTextAreaElement>().suggestedValue();
return element.to<WebInputElement>().suggestedValue();
}
private: private:
DISALLOW_COPY_AND_ASSIGN(FormAutofillTest); DISALLOW_COPY_AND_ASSIGN(FormAutofillTest);
}; };
...@@ -1115,7 +1127,7 @@ TEST_F(FormAutofillTest, FillForm) { ...@@ -1115,7 +1127,7 @@ TEST_F(FormAutofillTest, FillForm) {
"some multi-\nline value", "Go\naway!"}, "some multi-\nline value", "Go\naway!"},
}; };
TestFormFillFunctions(kFormHtml, field_cases, arraysize(field_cases), TestFormFillFunctions(kFormHtml, field_cases, arraysize(field_cases),
FillForm, &WebInputElement::value); FillForm, &GetValueWrapper);
// Verify preview selection. // Verify preview selection.
WebInputElement firstname = GetMainFrame()->document(). WebInputElement firstname = GetMainFrame()->document().
getElementById("firstname").to<WebInputElement>(); getElementById("firstname").to<WebInputElement>();
...@@ -1165,34 +1177,47 @@ TEST_F(FormAutofillTest, FillFormIncludingNonFocusableElements) { ...@@ -1165,34 +1177,47 @@ TEST_F(FormAutofillTest, FillFormIncludingNonFocusableElements) {
}; };
TestFormFillFunctions(kFormHtml, field_cases, arraysize(field_cases), TestFormFillFunctions(kFormHtml, field_cases, arraysize(field_cases),
&FillFormIncludingNonFocusableElementsWrapper, &FillFormIncludingNonFocusableElementsWrapper,
&WebInputElement::value); &GetValueWrapper);
} }
TEST_F(FormAutofillTest, PreviewForm) { TEST_F(FormAutofillTest, PreviewForm) {
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[] = { static const AutofillFieldCase field_cases[] = {
// Normal empty fields should be previewed. // Normal empty fields should be previewed.
{"text", "firstname", "", "", true, "suggested firstname", {"text", "firstname", "", "", true, "suggested firstname",
"suggested firstname"}, "suggested firstname"},
{"text", "lastname", "", "", true, "suggested lastname", {"text", "lastname", "", "", true, "suggested lastname",
"suggested lastname"}, "suggested lastname"},
// Hidden fields should not be extracted to form_data.
// Non empty fields should not be previewed. // Non empty fields should not be previewed.
{"text", "notempty", "Hi", "", false, "filled notempty", ""}, {"text", "notempty", "Hi", "", false, "suggested notempty", ""},
// "noautocomplete" should not be extracted to form_data. // "noautocomplete" should not be extracted to form_data.
// Disabled fields should not be previewed. // Disabled fields should not be previewed.
{"text", "notenabled", "", "", false, "filled notenabled", ""}, {"text", "notenabled", "", "", false, "suggested notenabled", ""},
// Readonly fields should not be previewed.
{"text", "readonly", "", "", false, "suggested readonly", ""},
// Fields with "visibility: hidden" should not be previewed.
{"text", "invisible", "", "", false, "suggested invisible",
""},
// Fields with "display:none" should not previewed.
{"text", "displaynone", "", "", false, "suggested displaynone",
""},
// Regular <input type="month"> should not be previewed.
{"month", "month", "", "", false, "2017-11", ""},
// Non-empty <input type="month"> should not be previewed.
{"month", "month-nonempty", "2011-12", "", false, "2017-11", ""},
// Regular select fields preview is not yet supported
{"select-one", "select", "", "", false, "TX", ""},
// Select fields preview is not yet supported
{"select-one", "select-nonempty", "CA", "", false, "TX", "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, field_cases, arraysize(field_cases), &PreviewForm, TestFormFillFunctions(kFormHtml, field_cases, arraysize(field_cases),
&WebInputElement::suggestedValue); &PreviewForm, &GetSuggestedValueWrapper);
// Verify preview selection. // Verify preview selection.
WebInputElement firstname = GetMainFrame()->document(). WebInputElement firstname = GetMainFrame()->document().
......
...@@ -570,21 +570,26 @@ void PreviewFormField(const FormFieldData& data, ...@@ -570,21 +570,26 @@ void PreviewFormField(const FormFieldData& data,
if (data.value.empty()) if (data.value.empty())
return; return;
// Only preview input fields. Excludes checkboxes and radio buttons, as there // Preview input and textarea fields. For input fields, excludes checkboxes
// is no provision for setSuggestedCheckedValue in WebInputElement. // and radio buttons, as there is no provision for setSuggestedCheckedValue
// in WebInputElement.
WebInputElement* input_element = toWebInputElement(field); WebInputElement* input_element = toWebInputElement(field);
if (!IsTextInput(input_element)) if (IsTextInput(input_element)) {
return; // If the maxlength attribute contains a negative value, maxLength()
// returns the default maxlength value.
// If the maxlength attribute contains a negative value, maxLength() input_element->setSuggestedValue(
// returns the default maxlength value.
input_element->setSuggestedValue(
data.value.substr(0, input_element->maxLength())); data.value.substr(0, input_element->maxLength()));
input_element->setAutofilled(true); input_element->setAutofilled(true);
if (is_initiating_node) { if (is_initiating_node) {
// Select the part of the text that the user didn't type. // Select the part of the text that the user didn't type.
input_element->setSelectionRange(input_element->value().length(), input_element->setSelectionRange(
input_element->suggestedValue().length()); input_element->value().length(),
input_element->suggestedValue().length());
}
} else if (IsTextAreaElement(*field)) {
WebTextAreaElement textarea = field->to<WebTextAreaElement>();
textarea.setSuggestedValue(data.value);
field->setAutofilled(true);
} }
} }
...@@ -1047,38 +1052,53 @@ bool ClearPreviewedFormWithElement(const WebInputElement& element, ...@@ -1047,38 +1052,53 @@ bool ClearPreviewedFormWithElement(const WebInputElement& element,
ExtractAutofillableElements(form_element, REQUIRE_AUTOCOMPLETE, ExtractAutofillableElements(form_element, REQUIRE_AUTOCOMPLETE,
&control_elements); &control_elements);
for (size_t i = 0; i < control_elements.size(); ++i) { for (size_t i = 0; i < control_elements.size(); ++i) {
// Only text input elements can be previewed.
WebInputElement* input_element = toWebInputElement(&control_elements[i]);
if (!IsTextInput(input_element))
continue;
// If the input element is not auto-filled, we did not preview it, so there
// is nothing to reset.
if (!input_element->isAutofilled())
continue;
// There might be unrelated elements in this form which have already been // There might be unrelated elements in this form which have already been
// auto-filled. For example, the user might have already filled the address // auto-filled. For example, the user might have already filled the address
// part of a form and now be dealing with the credit card section. We only // part of a form and now be dealing with the credit card section. We only
// want to reset the auto-filled status for fields that were previewed. // want to reset the auto-filled status for fields that were previewed.
if (input_element->suggestedValue().isEmpty()) WebFormControlElement control_element = control_elements[i];
// Only text input and textarea elements can be previewed.
WebInputElement* input_element = toWebInputElement(&control_element);
if (!IsTextInput(input_element) && !IsTextAreaElement(control_element))
continue;
// If the element is not auto-filled, we did not preview it,
// so there is nothing to reset.
if(!control_element.isAutofilled())
continue;
if ((IsTextInput(input_element) &&
input_element->suggestedValue().isEmpty()) ||
(IsTextAreaElement(control_element) &&
control_element.to<WebTextAreaElement>().suggestedValue().isEmpty()))
continue; continue;
// Clear the suggested value. For the initiating node, also restore the // Clear the suggested value. For the initiating node, also restore the
// original value. // original value.
input_element->setSuggestedValue(WebString()); if (IsTextInput(input_element)) {
bool is_initiating_node = (element == *input_element); input_element->setSuggestedValue(WebString());
if (is_initiating_node) bool is_initiating_node = (element == *input_element);
input_element->setAutofilled(was_autofilled); if (is_initiating_node)
else input_element->setAutofilled(was_autofilled);
input_element->setAutofilled(false); else
input_element->setAutofilled(false);
// Clearing the suggested value in the focused node (above) can cause
// selection to be lost. We force selection range to restore the text // Clearing the suggested value in the focused node (above) can cause
// cursor. // selection to be lost. We force selection range to restore the text
if (is_initiating_node) { // cursor.
int length = input_element->value().length(); if (is_initiating_node) {
input_element->setSelectionRange(length, length); int length = input_element->value().length();
input_element->setSelectionRange(length, length);
}
} else if (IsTextAreaElement(control_element)) {
WebTextAreaElement text_area = control_element.to<WebTextAreaElement>();
text_area.setSuggestedValue(WebString());
bool is_initiating_node = (element == text_area);
if (is_initiating_node)
control_element.setAutofilled(was_autofilled);
else
control_element.setAutofilled(false);
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment