Bug 1020698 - Implement @autocomplete for <textarea>. r=baku
authorMatthew Noorenberghe <mozilla@noorenberghe.ca>
Wed, 08 Nov 2017 21:35:04 -0800
changeset 393256 b693fb4f900d51d3fda7300de6405a40b99ede4f
parent 393255 20fbea037bce2e3b262fe528214c1dc1afd033c0
child 393257 4a65f0921a8545c8ec5f0f0de2b9557dbec66a89
push id32956
push usercsabou@mozilla.com
push dateThu, 23 Nov 2017 09:44:48 +0000
treeherdermozilla-central@b6bed1b710c3 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbaku
bugs1020698
milestone59.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
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
dom/base/nsContentUtils.cpp
dom/html/HTMLTextAreaElement.cpp
dom/html/HTMLTextAreaElement.h
dom/html/test/forms/mochitest.ini
dom/html/test/forms/test_autocomplete.html
dom/html/test/forms/test_input_autocomplete.html
dom/webidl/HTMLTextAreaElement.webidl
testing/web-platform/meta/html/dom/interfaces.html.ini
testing/web-platform/meta/html/dom/reflection-forms.html.ini
--- 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 &lt;input autocomplete='…'&gt;</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