Bug 559766 - add accessibility support for @list on HTML input and for HTML datalist, r=marcoz
authorAlexander Surkov <surkov.alexander@gmail.com>
Fri, 07 Oct 2011 15:02:18 +0900
changeset 78297 f1f69b249f454e1660879e11e10293b5ea70ce27
parent 78296 87f58aa55ce8dc35b6d7d42a26d5795b55c117b7
child 78298 b5507a7924357ac3580c99f2bf8097468c17d54c
push id2480
push usersurkov.alexander@gmail.com
push dateFri, 07 Oct 2011 06:02:49 +0000
treeherdermozilla-inbound@f1f69b249f45 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmarcoz
bugs559766
milestone10.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 559766 - add accessibility support for @list on HTML input and for HTML datalist, r=marcoz
accessible/src/html/nsHTMLFormControlAccessible.cpp
accessible/tests/mochitest/events/test_focus_autocomplete.xul
accessible/tests/mochitest/states/test_inputs.html
--- a/accessible/src/html/nsHTMLFormControlAccessible.cpp
+++ b/accessible/src/html/nsHTMLFormControlAccessible.cpp
@@ -506,16 +506,20 @@ nsHTMLTextFieldAccessible::NativeState()
 
   // Expose autocomplete states if this input is part of autocomplete widget.
   nsAccessible* widget = ContainerWidget();
   if (widget && widget-IsAutoComplete()) {
     state |= states::HASPOPUP | states::SUPPORTS_AUTOCOMPLETION;
     return state;
   }
 
+  // Expose autocomplete state if it has associated autocomplete list.
+  if (mContent->HasAttr(kNameSpaceID_None, nsGkAtoms::list))
+    return state | states::SUPPORTS_AUTOCOMPLETION;
+
   // No parent can mean a fake widget created for XUL textbox. If accessible
   // is unattached from tree then we don't care.
   if (mParent && gIsFormFillEnabled) {
     // Check to see if autocompletion is allowed on this input. We don't expose
     // it for password fields even though the entire password can be remembered
     // for a page if the user asks it to be. However, the kind of autocomplete
     // we're talking here is based on what the user types, where a popup of
     // possible choices comes up.
--- a/accessible/tests/mochitest/events/test_focus_autocomplete.xul
+++ b/accessible/tests/mochitest/events/test_focus_autocomplete.xul
@@ -68,30 +68,54 @@
       this.iframe = getAccessible(aIFrameID);
 
       this.eventSeq = [
         new invokerChecker(EVENT_REORDER, this.iframe)
       ];
 
       this.invoke = function initFormAutoCompleteBy_invoke()
       {
-        var iframeDOMDoc = getFormAutoCompleteDOMDoc(aIFrameID);
+        var iframeDOMDoc = getIFrameDOMDoc(aIFrameID);
 
         var inputNode = iframeDOMDoc.getElementById("input");
         inputNode.value = aAutoCompleteValue;
         var formNode = iframeDOMDoc.getElementById("form");
         formNode.submit();
       }
 
       this.getID = function initFormAutoCompleteBy_getID()
       {
         return "init form autocomplete by '" + aAutoCompleteValue + "'";
       }
     }
 
+    function loadHTML5ListAutoComplete(aIFrameID)
+    {
+      this.iframeNode = getNode(aIFrameID);
+      this.iframe = getAccessible(aIFrameID);
+
+      this.eventSeq = [
+        new invokerChecker(EVENT_REORDER, this.iframe)
+      ];
+
+      this.invoke = function loadHTML5ListAutoComplete_invoke()
+      {
+        var url = "data:text/html,<html><body>" +
+          "<datalist id='cities'><option>hello</option><option>hi</option></datalist>" +
+          "<input id='input' list='cities'>" +
+          "</body></html>";
+        this.iframeNode.setAttribute("src", url);
+      }
+
+      this.getID = function loadHTML5ListAutoComplete_getID()
+      {
+        return "load HTML5 list autocomplete page";
+      }
+    }
+
     function removeChar(aID, aCheckerOrEventSeq)
     {
       this.__proto__ = new synthAction(aID, aCheckerOrEventSeq);
 
       this.invoke = function removeChar_invoke()
       {
         synthesizeKey("VK_LEFT", { shiftKey: true });
         synthesizeKey("VK_DELETE", {});
@@ -274,17 +298,17 @@
 
       this.autocomplete = this.autocompleteNode.localName == "searchbar" ?
         getAccessible(this.autocompleteNode.textbox) :
         getAccessible(this.autocompleteNode);
 
       this.index = aIdx;
     }
 
-    function getFormAutoCompleteDOMDoc(aIFrameID)
+    function getIFrameDOMDoc(aIFrameID)
     {
       return getNode(aIFrameID).contentDocument;
     }
 
     ////////////////////////////////////////////////////////////////////////////
     // Test helpers
 
     function queueAutoCompleteTests(aID)
@@ -357,16 +381,17 @@
       // register 'test-a11y-search' autocomplete search
       initAutoComplete([ "hello", "hi" ],
                        [ "Beep beep'm beep beep yeah", "Baby you can drive my car" ]);
 
       gInitQueue = new eventQueue();
       gInitQueue.push(new loadFormAutoComplete("iframe"));
       gInitQueue.push(new initFormAutoCompleteBy("iframe", "hello"));
       gInitQueue.push(new initFormAutoCompleteBy("iframe", "hi"));
+      gInitQueue.push(new loadHTML5ListAutoComplete("iframe2"));
       gInitQueue.onFinish = function initQueue_onFinish()
       {
         SimpleTest.executeSoon(doTests);
         return DO_NOT_FINISH_TEST;
       }
       gInitQueue.invoke();
     }
 
@@ -381,17 +406,21 @@
       queueAutoCompleteTests("autocomplete");
 
       ////////////////////////////////////////////////////////////////////////////
       // richlistbox popup autocomplete tests
       queueAutoCompleteTests("richautocomplete");
 
       ////////////////////////////////////////////////////////////////////////////
       // HTML form autocomplete tests
-      queueAutoCompleteTests(getFormAutoCompleteDOMDoc("iframe").getElementById("input"));
+      queueAutoCompleteTests(getIFrameDOMDoc("iframe").getElementById("input"));
+
+      ////////////////////////////////////////////////////////////////////////////
+      // HTML5 list autocomplete tests
+      queueAutoCompleteTests(getIFrameDOMDoc("iframe2").getElementById("input"));
 
       ////////////////////////////////////////////////////////////////////////////
       // searchbar tests
 
       // focus searchbar, focus on text entry
       gQueue.push(new synthFocus("searchbar",
                                  new focusChecker(getTextEntry, "searchbar")));
       // open search engine popup, no focus
@@ -433,16 +462,21 @@
          title="Focus event inconsistent for search box autocomplete">
         Mozilla Bug 383759
       </a>
       <a target="_blank"
          href="https://bugzilla.mozilla.org/show_bug.cgi?id=673958"
          title="Rework accessible focus handling">
         Mozilla Bug 673958
       </a>
+      <a target="_blank"
+         href="https://bugzilla.mozilla.org/show_bug.cgi?id=559766"
+         title="Add accessibility support for @list on HTML input and for HTML datalist">
+        Mozilla Bug 559766
+      </a>
       <p id="display"></p>
       <div id="content" style="display: none"></div>
       <pre id="test">
       </pre>
     </body>
 
     <vbox flex="1">
       <textbox id="autocomplete" type="autocomplete"
@@ -450,14 +484,16 @@
 
       <textbox id="richautocomplete" type="autocomplete"
                autocompletesearch="test-a11y-search"
                autocompletepopup="richpopup"/>
       <panel id="richpopup" type="autocomplete-richlistbox" noautofocus="true"/>
 
       <iframe id="iframe"/>
 
+      <iframe id="iframe2"/>
+
       <searchbar id="searchbar"/>
 
       <vbox id="eventdump"/>
     </vbox>
   </hbox>
 </window>
--- a/accessible/tests/mochitest/states/test_inputs.html
+++ b/accessible/tests/mochitest/states/test_inputs.html
@@ -60,16 +60,22 @@
     //var invalid = ["maxlength","pattern","email","url"];
     //document.getElementById("maxlength").value = "i am too long";
     var invalid = ["pattern","email","url"];
     for (i in invalid) {
       testStates(invalid[i], STATE_INVALID);
       testStates(invalid[i] + "2", 0, 0, STATE_INVALID);
     }
 
+    // autocomplete states
+    testStates("autocomplete-default", 0, EXT_STATE_SUPPORTS_AUTOCOMPLETION);
+    testStates("autocomplete-off", 0, 0, 0, EXT_STATE_SUPPORTS_AUTOCOMPLETION);
+    testStates("autocomplete-formoff", 0, 0, 0, EXT_STATE_SUPPORTS_AUTOCOMPLETION);
+    testStates("autocomplete-list", 0, EXT_STATE_SUPPORTS_AUTOCOMPLETION);
+    testStates("autocomplete-list2", 0, EXT_STATE_SUPPORTS_AUTOCOMPLETION);
     SimpleTest.finish();
   }
 
   SimpleTest.waitForExplicitFinish();
   addA11yLoadEvent(doTest);
   </script>
 </head>
 
@@ -94,16 +100,21 @@
      title="Expose intrinsic invalid state to accessibility API">
     Mozilla Bug 601205
   </a>
   <a target="_blank"
      href="https://bugzilla.mozilla.org/show_bug.cgi?id=601205"
      title="Expose intrinsic invalid state to accessibility API">
     Mozilla Bug 601205
   </a>
+  <a target="_blank"
+     href="https://bugzilla.mozilla.org/show_bug.cgi?id=559766"
+     title="Add accessibility support for @list on HTML input and for HTML datalist">
+    Mozilla Bug 559766
+  </a>
   <p id="display"></p>
   <div id="content" style="display: none"></div>
   <pre id="test">
   </pre>
 
 
   <form>
     <input id="input" type="input" required>
@@ -150,10 +161,23 @@
   <input id="maxlength2" maxlength="100" value="foo">
   <input id="pattern" pattern="bar" value="foo">
   <input id="pattern2" pattern="bar" value="bar">
   <input id="email" type="email" value="foo">
   <input id="email2" type="email" value="foo@bar.com">
   <input id="url" type="url" value="foo">
   <input id="url2" type="url" value="http://mozilla.org/">
 
+  <!-- autocomplete -->
+  <input id="autocomplete-default">
+  <input id="autocomplete-off" autocomplete="off">
+  <form autocomplete="off">
+    <input id="autocomplete-formoff">
+  </form>
+  <datalist id="cities">
+    <option>Paris</option>
+    <option>San Francisco</option>
+  </datalist>
+  <input id="autocomplete-list" list="cities">
+  <input id="autocomplete-list2" list="cities" autocomplete="off">
+
   </body>
 </html>