Bug 1020698 - Implement @autocomplete for <textarea>. r=baku
The dom.forms.autocomplete.formautofill check in nsContentUtils::InternalSerializeAutocompleteAttribute
will control if values other than "on" and "off" are supported.
MozReview-Commit-ID: 48X3OzvuOpV
--- a/dom/base/nsContentUtils.cpp
+++ b/dom/base/nsContentUtils.cpp
@@ -1132,17 +1132,17 @@ nsContentUtils::SerializeAutocompleteAtt
*
* @return {AutocompleteAttrState} The state of the attribute (invalid/valid).
*/
nsContentUtils::AutocompleteAttrState
nsContentUtils::InternalSerializeAutocompleteAttribute(const nsAttrValue* aAttrVal,
mozilla::dom::AutocompleteInfo& aInfo,
bool aGrantAllValidValue)
{
- // No sandbox attribute so we are done
+ // No autocomplete attribute so we are done
if (!aAttrVal) {
return eAutocompleteAttrState_Invalid;
}
uint32_t numTokens = aAttrVal->GetAtomCount();
if (!numTokens) {
return eAutocompleteAttrState_Invalid;
}
--- a/dom/html/HTMLTextAreaElement.cpp
+++ b/dom/html/HTMLTextAreaElement.cpp
@@ -58,16 +58,17 @@ HTMLTextAreaElement::HTMLTextAreaElement
mLastValueChangeWasInteractive(false),
mHandlingSelect(false),
mDoneAddingChildren(!aFromParser),
mInhibitStateRestoration(!!(aFromParser & FROM_PARSER_FRAGMENT)),
mDisabledChanged(false),
mCanShowInvalidUI(true),
mCanShowValidUI(true),
mIsPreviewEnabled(false),
+ mAutocompleteAttrState(nsContentUtils::eAutocompleteAttrState_Unknown),
mState(this)
{
AddMutationObserver(this);
// Set up our default state. By default we're enabled (since we're
// a control type that can be disabled but not actually disabled
// right now), optional, and valid. We are NOT readwrite by default
// until someone calls UpdateEditableState on us, apparently! Also
@@ -431,16 +432,19 @@ HTMLTextAreaElement::ParseAttribute(int3
aAttribute == nsGkAtoms::minlength) {
return aResult.ParseNonNegativeIntValue(aValue);
} else if (aAttribute == nsGkAtoms::cols) {
aResult.ParseIntWithFallback(aValue, DEFAULT_COLS);
return true;
} else if (aAttribute == nsGkAtoms::rows) {
aResult.ParseIntWithFallback(aValue, DEFAULT_ROWS_TEXTAREA);
return true;
+ } else if (aAttribute == nsGkAtoms::autocomplete) {
+ aResult.ParseAtomArray(aValue);
+ return true;
}
}
return nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
aResult);
}
void
HTMLTextAreaElement::MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
@@ -1055,16 +1059,19 @@ HTMLTextAreaElement::AfterSetAttr(int32_
}
UpdateValueMissingValidityState();
// This *has* to be called *after* validity has changed.
if (aName == nsGkAtoms::readonly || aName == nsGkAtoms::disabled) {
UpdateBarredFromConstraintValidation();
}
+ } else if (aName == nsGkAtoms::autocomplete) {
+ // Clear the cached @autocomplete attribute state.
+ mAutocompleteAttrState = nsContentUtils::eAutocompleteAttrState_Unknown;
} else if (aName == nsGkAtoms::maxlength) {
UpdateTooLongValidityState();
} else if (aName == nsGkAtoms::minlength) {
UpdateTooShortValidityState();
}
}
return nsGenericHTMLFormElementWithState::AfterSetAttr(aNameSpaceID, aName, aValue,
@@ -1364,10 +1371,20 @@ HTMLTextAreaElement::FieldSetDisabledCha
}
JSObject*
HTMLTextAreaElement::WrapNode(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
{
return HTMLTextAreaElementBinding::Wrap(aCx, this, aGivenProto);
}
+void
+HTMLTextAreaElement::GetAutocomplete(DOMString& aValue)
+{
+ const nsAttrValue* attributeVal = GetParsedAttr(nsGkAtoms::autocomplete);
+
+ mAutocompleteAttrState =
+ nsContentUtils::SerializeAutocompleteAttribute(attributeVal, aValue,
+ mAutocompleteAttrState);
+}
+
} // namespace dom
} // namespace mozilla
--- a/dom/html/HTMLTextAreaElement.h
+++ b/dom/html/HTMLTextAreaElement.h
@@ -176,16 +176,21 @@ public:
void UpdateTooLongValidityState();
void UpdateTooShortValidityState();
void UpdateValueMissingValidityState();
void UpdateBarredFromConstraintValidation();
nsresult GetValidationMessage(nsAString& aValidationMessage,
ValidityStateType aType) override;
// Web IDL binding methods
+ void GetAutocomplete(DOMString& aValue);
+ void SetAutocomplete(const nsAString& aValue, ErrorResult& aRv)
+ {
+ SetHTMLAttr(nsGkAtoms::autocomplete, aValue, aRv);
+ }
bool Autofocus()
{
return GetBoolAttr(nsGkAtoms::autofocus);
}
void SetAutofocus(bool aAutoFocus, ErrorResult& aError)
{
SetHTMLBoolAttr(nsGkAtoms::autofocus, aAutoFocus, aError);
}
@@ -342,16 +347,18 @@ protected:
/** Whether our disabled state has changed from the default **/
bool mDisabledChanged;
/** Whether we should make :-moz-ui-invalid apply on the element. **/
bool mCanShowInvalidUI;
/** Whether we should make :-moz-ui-valid apply on the element. **/
bool mCanShowValidUI;
bool mIsPreviewEnabled;
+ nsContentUtils::AutocompleteAttrState mAutocompleteAttrState;
+
void FireChangeEventIfNeeded();
nsString mFocusedValue;
/** The state of the text editor (selection controller and the editor) **/
nsTextEditorState mState;
NS_IMETHOD SelectAll(nsPresContext* aPresContext);
--- a/dom/html/test/forms/mochitest.ini
+++ b/dom/html/test/forms/mochitest.ini
@@ -1,16 +1,17 @@
[DEFAULT]
support-files =
save_restore_radio_groups.sjs
test_input_number_data.js
!/dom/html/test/reflect.js
FAIL.html
PASS.html
+[test_autocomplete.html]
[test_bug1039548.html]
[test_bug1283915.html]
[test_bug1286509.html]
skip-if = os == "android" # up/down arrow keys not supported on android
[test_button_attributes_reflection.html]
[test_input_radio_indeterminate.html]
[test_input_radio_radiogroup.html]
[test_input_radio_required.html]
@@ -20,17 +21,16 @@ skip-if = os == "android" # up/down arro
[test_form_attribute-2.html]
[test_form_attribute-3.html]
[test_form_attribute-4.html]
[test_form_attributes_reflection.html]
[test_form_named_getter_dynamic.html]
[test_formaction_attribute.html]
[test_formnovalidate_attribute.html]
[test_input_attributes_reflection.html]
-[test_input_autocomplete.html]
[test_input_color_input_change_events.html]
[test_input_color_picker_initial.html]
[test_input_color_picker_popup.html]
skip-if = android_version == '18' # Android, bug 1147974
[test_input_color_picker_update.html]
skip-if = android_version == '18' # Android, bug 1147974
[test_input_date_bad_input.html]
[test_input_date_key_events.html]
rename from dom/html/test/forms/test_input_autocomplete.html
rename to dom/html/test/forms/test_autocomplete.html
--- a/dom/html/test/forms/test_input_autocomplete.html
+++ b/dom/html/test/forms/test_autocomplete.html
@@ -1,15 +1,15 @@
<!DOCTYPE html>
<html>
<!--
-Test @autocomplete on <input>
+Test @autocomplete on <input>/<select>/<textarea>
-->
<head>
- <title>Test for <input autocomplete='…'></title>
+ <title>Test for @autocomplete</title>
<script src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" href="/tests/SimpleTest/test.css"/>
<script>
"use strict";
var values = [
// @autocomplete content attribute, expected IDL attribute value
@@ -103,28 +103,33 @@ function start() {
inputField.removeAttribute("type");
else
inputField.type = type;
checkAutocompleteValues(inputField, type || "");
}
var selectField = document.getElementById("select-field");
checkAutocompleteValues(selectField, "select");
+
+ var textarea = document.getElementById("textarea");
+ checkAutocompleteValues(textarea, "textarea");
+
SimpleTest.finish();
}
SimpleTest.waitForExplicitFinish();
SpecialPowers.pushPrefEnv({"set": [["dom.forms.autocomplete.formautofill", true]]}, start);
</script>
</head>
<body>
<p id="display"></p>
<div id="content" style="display: none">
<form>
<input id="input-field" />
<select id="select-field" />
+ <textarea id="textarea"></textarea>
</form>
</div>
<pre id="test">
</pre>
</body>
</html>
--- a/dom/webidl/HTMLTextAreaElement.webidl
+++ b/dom/webidl/HTMLTextAreaElement.webidl
@@ -11,17 +11,18 @@
* and create derivative works of this document.
*/
interface nsIEditor;
interface XULControllers;
[HTMLConstructor]
interface HTMLTextAreaElement : HTMLElement {
- // attribute DOMString autocomplete;
+ [CEReactions, SetterThrows, Pure]
+ attribute DOMString autocomplete;
[CEReactions, SetterThrows, Pure]
attribute boolean autofocus;
[CEReactions, SetterThrows, Pure]
attribute unsigned long cols;
// attribute DOMString dirName;
[CEReactions, SetterThrows, Pure]
attribute boolean disabled;
[Pure]
--- a/testing/web-platform/meta/html/dom/interfaces.html.ini
+++ b/testing/web-platform/meta/html/dom/interfaces.html.ini
@@ -1067,28 +1067,22 @@
expected: FAIL
[HTMLButtonElement interface: document.createElement("button") must inherit property "menu" with the proper type (11)]
expected: FAIL
[HTMLButtonElement interface: document.createElement("button") must inherit property "labels" with the proper type (18)]
expected: FAIL
- [HTMLTextAreaElement interface: attribute autocomplete]
- expected: FAIL
-
[HTMLTextAreaElement interface: attribute dirName]
expected: FAIL
[HTMLTextAreaElement interface: attribute inputMode]
expected: FAIL
- [HTMLTextAreaElement interface: document.createElement("textarea") must inherit property "autocomplete" with the proper type (0)]
- expected: FAIL
-
[HTMLTextAreaElement interface: document.createElement("textarea") must inherit property "dirName" with the proper type (3)]
expected: FAIL
[HTMLTextAreaElement interface: document.createElement("textarea") must inherit property "inputMode" with the proper type (6)]
expected: FAIL
[HTMLKeygenElement interface: existence and properties of interface object]
expected: FAIL
@@ -3815,19 +3809,16 @@
expected: FAIL
[HTMLInputElement interface: createInput("reset") must inherit property "dirName" with the proper type]
expected: FAIL
[HTMLInputElement interface: createInput("button") must inherit property "dirName" with the proper type]
expected: FAIL
- [HTMLTextAreaElement interface: document.createElement("textarea") must inherit property "autocomplete" with the proper type]
- expected: FAIL
-
[HTMLTextAreaElement interface: document.createElement("textarea") must inherit property "dirName" with the proper type]
expected: FAIL
[HTMLTextAreaElement interface: document.createElement("textarea") must inherit property "inputMode" with the proper type]
expected: FAIL
[HTMLScriptElement interface: document.createElement("script") must inherit property "noModule" with the proper type]
expected: FAIL
--- a/testing/web-platform/meta/html/dom/reflection-forms.html.ini
+++ b/testing/web-platform/meta/html/dom/reflection-forms.html.ini
@@ -3458,67 +3458,16 @@
expected: FAIL
[input.inputMode: IDL set to "KANA-NAME"]
expected: FAIL
[input.inputMode: IDL set to "Kana-name"]
expected: FAIL
- [textarea.autocomplete: typeof IDL attribute]
- expected: FAIL
-
- [textarea.autocomplete: IDL get with DOM attribute unset]
- expected: FAIL
-
- [textarea.autocomplete: IDL set to ""]
- expected: FAIL
-
- [textarea.autocomplete: IDL set to " \\0\\x01\\x02\\x03\\x04\\x05\\x06\\x07 \\b\\t\\n\\v\\f\\r\\x0e\\x0f \\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17 \\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f foo "]
- expected: FAIL
-
- [textarea.autocomplete: IDL set to undefined]
- expected: FAIL
-
- [textarea.autocomplete: IDL set to 7]
- expected: FAIL
-
- [textarea.autocomplete: IDL set to 1.5]
- expected: FAIL
-
- [textarea.autocomplete: IDL set to true]
- expected: FAIL
-
- [textarea.autocomplete: IDL set to false]
- expected: FAIL
-
- [textarea.autocomplete: IDL set to object "[object Object\]"]
- expected: FAIL
-
- [textarea.autocomplete: IDL set to NaN]
- expected: FAIL
-
- [textarea.autocomplete: IDL set to Infinity]
- expected: FAIL
-
- [textarea.autocomplete: IDL set to -Infinity]
- expected: FAIL
-
- [textarea.autocomplete: IDL set to "\\0"]
- expected: FAIL
-
- [textarea.autocomplete: IDL set to null]
- expected: FAIL
-
- [textarea.autocomplete: IDL set to object "test-toString"]
- expected: FAIL
-
- [textarea.autocomplete: IDL set to object "test-valueOf"]
- expected: FAIL
-
[textarea.inputMode: setAttribute() to "kana-name"]
expected: FAIL
[textarea.inputMode: setAttribute() to "xkana-name"]
expected: FAIL
[textarea.inputMode: setAttribute() to "kana-name\\0"]
expected: FAIL