Bug 1629078 part 2: Make date/time inputs labellable by an ancestor HTML label and expose text-input-type attribute. r=MarcoZ
authorJames Teh <jteh@mozilla.com>
Thu, 23 Apr 2020 04:48:53 +0000
changeset 525539 73607b44ad6b837ba2de1f4d01fa26b86d81cda0
parent 525538 305e91b012119051b51a91be0eb83e032e02ebd6
child 525540 47426d145e246fa1924fbda83a8ecb0d25a6f606
push id37339
push usernerli@mozilla.com
push dateThu, 23 Apr 2020 09:52:48 +0000
treeherdermozilla-central@47426d145e24 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersMarcoZ
bugs1629078
milestone77.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 1629078 part 2: Make date/time inputs labellable by an ancestor HTML label and expose text-input-type attribute. r=MarcoZ In order for a form control to be labelled by an ancestor HTML label, its Accessible must return true for isWidget(). Also, HTML AAM says the text-input-type attribute should be exposed. Differential Revision: https://phabricator.services.mozilla.com/D72080
accessible/base/MarkupMap.h
accessible/html/HTMLFormControlAccessible.h
accessible/tests/mochitest/elm/test_HTMLSpec.html
--- a/accessible/base/MarkupMap.h
+++ b/accessible/base/MarkupMap.h
@@ -208,23 +208,23 @@ MARKUPMAP(
         return new HTMLButtonAccessible(aElement, aContext->Document());
       }
       if (aElement->AttrValueIs(kNameSpaceID_None, nsGkAtoms::type,
                                 nsGkAtoms::radio, eIgnoreCase)) {
         return new HTMLRadioButtonAccessible(aElement, aContext->Document());
       }
       if (aElement->AttrValueIs(kNameSpaceID_None, nsGkAtoms::type,
                                 nsGkAtoms::time, eIgnoreCase)) {
-        return new EnumRoleAccessible<roles::GROUPING>(aElement,
-                                                       aContext->Document());
+        return new HTMLDateTimeAccessible<roles::GROUPING>(
+            aElement, aContext->Document());
       }
       if (aElement->AttrValueIs(kNameSpaceID_None, nsGkAtoms::type,
                                 nsGkAtoms::date, eIgnoreCase)) {
-        return new EnumRoleAccessible<roles::DATE_EDITOR>(aElement,
-                                                          aContext->Document());
+        return new HTMLDateTimeAccessible<roles::DATE_EDITOR>(
+            aElement, aContext->Document());
       }
       return nullptr;
     },
     0)
 
 MARKUPMAP(ins, New_HyperText, roles::CONTENT_INSERTION)
 
 MARKUPMAP(
--- a/accessible/html/HTMLFormControlAccessible.h
+++ b/accessible/html/HTMLFormControlAccessible.h
@@ -3,16 +3,17 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef MOZILLA_A11Y_HTMLFormControlAccessible_H_
 #define MOZILLA_A11Y_HTMLFormControlAccessible_H_
 
 #include "FormControlAccessible.h"
 #include "HyperTextAccessibleWrap.h"
+#include "nsAccUtils.h"
 
 namespace mozilla {
 class TextEditor;
 namespace a11y {
 
 /**
  * Accessible for HTML input@type="radio" element.
  */
@@ -277,12 +278,46 @@ class HTMLProgressAccessible : public Le
 
   // Widgets
   virtual bool IsWidget() const override;
 
  protected:
   virtual ~HTMLProgressAccessible() {}
 };
 
+/**
+ * Accessible for HTML date/time inputs.
+ */
+template <a11y::role R>
+class HTMLDateTimeAccessible : public AccessibleWrap {
+ public:
+  HTMLDateTimeAccessible(nsIContent* aContent, DocAccessible* aDoc)
+      : AccessibleWrap(aContent, aDoc) {}
+
+  NS_INLINE_DECL_REFCOUNTING_INHERITED(HTMLDateTimeAccessible, AccessibleWrap)
+
+  // Accessible
+  virtual mozilla::a11y::role NativeRole() const override { return R; }
+  virtual already_AddRefed<nsIPersistentProperties> NativeAttributes()
+      override {
+    nsCOMPtr<nsIPersistentProperties> attributes =
+        AccessibleWrap::NativeAttributes();
+    // Unfortunately, an nsStaticAtom can't be passed as a
+    // template argument, so fetch the type from the DOM.
+    nsAutoString type;
+    if (mContent->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::type,
+                                       type)) {
+      nsAccUtils::SetAccAttr(attributes, nsGkAtoms::textInputType, type);
+    }
+    return attributes.forget();
+  }
+
+  // Widgets
+  virtual bool IsWidget() const override { return true; }
+
+ protected:
+  virtual ~HTMLDateTimeAccessible() {}
+};
+
 }  // namespace a11y
 }  // namespace mozilla
 
 #endif
--- a/accessible/tests/mochitest/elm/test_HTMLSpec.html
+++ b/accessible/tests/mochitest/elm/test_HTMLSpec.html
@@ -844,32 +844,36 @@
       };
       testElm("input_reset", obj);
 
       // ////////////////////////////////////////////////////////////////////////
       // HTML:input@type="time"
 
       obj = {
         role: ROLE_GROUPING,
+        name: "time label",
+        attributes: { "text-input-type": "time" },
         children: [
           { role: ROLE_SPINBUTTON },
           { role: ROLE_TEXT_LEAF },
           { role: ROLE_SPINBUTTON },
           { role: ROLE_TEXT_LEAF },
           { role: ROLE_ENTRY },
           { role: ROLE_PUSHBUTTON },
         ],
       };
       testElm("input_time", obj);
 
       // ////////////////////////////////////////////////////////////////////////
       // HTML:input@type="date"
 
       obj = {
         role: ROLE_DATE_EDITOR,
+        name: "date label",
+        attributes: { "text-input-type": "date" },
         children: [
           { role: ROLE_SPINBUTTON },
           { role: ROLE_TEXT_LEAF },
           { role: ROLE_SPINBUTTON },
           { role: ROLE_TEXT_LEAF },
           { role: ROLE_SPINBUTTON },
           { role: ROLE_PUSHBUTTON },
         ],
@@ -1749,18 +1753,22 @@
   <input id="input_password" type="password" value="44">
   <input id="input_password_readonly" type="password" value="44" readonly>
   <input id="input_radio" type="radio">
   <input id="input_radio_true" type="radio" checked>
   <input id="input_range" type="range">
   <form>
     <input id="input_reset" type="reset">
   </form>
-  <input id="input_time" type="time" value="23:23">
-  <input id="input_date" type="date" value="2017-11-10">
+  <label>time label
+    <input id="input_time" type="time" value="23:23">
+  </label>
+  <label>date label
+    <input id="input_date" type="date" value="2017-11-10">
+  </label>
 
   <p id="ins_container">normal<ins>Inserted</ins></p>
   <p id="kbd_container">normal<kbd>cmd</kbd></p>
 
   <label id="label">label<input id="label_input"></label>
   <label id="label_for" for="label_for_input">label</label>
   <input id="label_for_input">