Bug 924284 - Output accessible values. r=yzen
authorEitan Isaacson <eitan@monotonous.org>
Mon, 14 Oct 2013 12:56:19 -0700
changeset 164529 0e82e8f1c85fd4c086774eb77e1616124b372e4e
parent 164528 9e39971f3bb3e948338209ae3a7149eb2e4cc934
child 164530 f327334172abc1e5aa9a4c1e926f31ccdc997233
push id3066
push userakeybl@mozilla.com
push dateMon, 09 Dec 2013 19:58:46 +0000
treeherdermozilla-beta@a31a0dce83aa [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersyzen
bugs924284
milestone27.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 924284 - Output accessible values. r=yzen
accessible/src/jsat/OutputGenerator.jsm
accessible/tests/mochitest/jsat/output.js
accessible/tests/mochitest/jsat/test_braille.html
accessible/tests/mochitest/jsat/test_explicit_names.html
accessible/tests/mochitest/jsat/test_utterance_order.html
--- a/accessible/src/jsat/OutputGenerator.jsm
+++ b/accessible/src/jsat/OutputGenerator.jsm
@@ -6,18 +6,19 @@
 
 const Cc = Components.classes;
 const Ci = Components.interfaces;
 const Cu = Components.utils;
 const Cr = Components.results;
 
 const INCLUDE_DESC = 0x01;
 const INCLUDE_NAME = 0x02;
-const INCLUDE_CUSTOM = 0x04;
-const NAME_FROM_SUBTREE_RULE = 0x08;
+const INCLUDE_VALUE = 0x04;
+const INCLUDE_CUSTOM = 0x08;
+const NAME_FROM_SUBTREE_RULE = 0x10;
 
 const OUTPUT_DESC_FIRST = 0;
 const OUTPUT_DESC_LAST = 1;
 
 const ROLE_LISTITEM = Ci.nsIAccessibleRole.ROLE_LISTITEM;
 const ROLE_STATICTEXT = Ci.nsIAccessibleRole.ROLE_STATICTEXT;
 const ROLE_LINK = Ci.nsIAccessibleRole.ROLE_LINK;
 
@@ -59,18 +60,19 @@ this.OutputGenerator = {
     let addOutput = function addOutput(aAccessible) {
       output.push.apply(output, self.genForObject(aAccessible, aContext));
     };
     let ignoreSubtree = function ignoreSubtree(aAccessible) {
       let roleString = Utils.AccRetrieval.getStringRole(aAccessible.role);
       let nameRule = self.roleRuleMap[roleString] || 0;
       // Ignore subtree if the name is explicit and the role's name rule is the
       // NAME_FROM_SUBTREE_RULE.
-      return (nameRule & NAME_FROM_SUBTREE_RULE) &&
-        (Utils.getAttributes(aAccessible)['explicit-name'] === 'true');
+      return (((nameRule & INCLUDE_VALUE) && aAccessible.value) ||
+              ((nameRule & NAME_FROM_SUBTREE_RULE) &&
+               Utils.getAttributes(aAccessible)['explicit-name'] === 'true'));
     };
 
     let contextStart = this._getContextStart(aContext);
 
     if (this.outputOrder === OUTPUT_DESC_FIRST) {
       contextStart.forEach(addOutput);
       addOutput(aContext.accessible);
       [addOutput(node) for
@@ -251,19 +253,19 @@ this.OutputGenerator = {
     'pagetab': INCLUDE_DESC | NAME_FROM_SUBTREE_RULE,
     'graphic': INCLUDE_DESC,
     'pushbutton': INCLUDE_DESC | NAME_FROM_SUBTREE_RULE,
     'checkbutton': INCLUDE_DESC | NAME_FROM_SUBTREE_RULE,
     'radiobutton': INCLUDE_DESC | NAME_FROM_SUBTREE_RULE,
     'buttondropdown': NAME_FROM_SUBTREE_RULE,
     'combobox': INCLUDE_DESC,
     'droplist': INCLUDE_DESC,
-    'progressbar': INCLUDE_DESC,
-    'slider': INCLUDE_DESC,
-    'spinbutton': INCLUDE_DESC,
+    'progressbar': INCLUDE_DESC | INCLUDE_VALUE,
+    'slider': INCLUDE_DESC | INCLUDE_VALUE,
+    'spinbutton': INCLUDE_DESC | INCLUDE_VALUE,
     'diagram': INCLUDE_DESC,
     'animation': INCLUDE_DESC,
     'equation': INCLUDE_DESC,
     'buttonmenu': INCLUDE_DESC | NAME_FROM_SUBTREE_RULE,
     'buttondropdowngrid': NAME_FROM_SUBTREE_RULE,
     'pagetablist': INCLUDE_DESC,
     'canvas': INCLUDE_DESC,
     'check menu item': INCLUDE_DESC | NAME_FROM_SUBTREE_RULE,
@@ -273,17 +275,17 @@ this.OutputGenerator = {
     'radio menu item': INCLUDE_DESC | NAME_FROM_SUBTREE_RULE,
     'table column header': NAME_FROM_SUBTREE_RULE,
     'table row header': NAME_FROM_SUBTREE_RULE,
     'tear off menu item': NAME_FROM_SUBTREE_RULE,
     'toggle button': INCLUDE_DESC | NAME_FROM_SUBTREE_RULE,
     'parent menuitem': NAME_FROM_SUBTREE_RULE,
     'header': INCLUDE_DESC,
     'footer': INCLUDE_DESC,
-    'entry': INCLUDE_DESC | INCLUDE_NAME,
+    'entry': INCLUDE_DESC | INCLUDE_NAME | INCLUDE_VALUE,
     'caption': INCLUDE_DESC,
     'document frame': INCLUDE_DESC,
     'heading': INCLUDE_DESC,
     'calendar': INCLUDE_DESC | INCLUDE_NAME,
     'combobox list': INCLUDE_DESC,
     'combobox option': INCLUDE_DESC | NAME_FROM_SUBTREE_RULE,
     'listbox option': INCLUDE_DESC | NAME_FROM_SUBTREE_RULE,
     'listbox rich option': NAME_FROM_SUBTREE_RULE,
@@ -304,16 +306,24 @@ this.OutputGenerator = {
       if (aFlags & INCLUDE_DESC) {
         let desc = this._getLocalizedStates(aStates);
         let roleStr = this._getLocalizedRole(aRoleStr);
         if (roleStr)
           desc.push(roleStr);
         output.push(desc.join(' '));
       }
 
+      if (aFlags & INCLUDE_VALUE) {
+        let value = aAccessible.value;
+        if (value) {
+          output[this.outputOrder === OUTPUT_DESC_FIRST ?
+                 'push' : 'unshift'](value);
+        }
+      }
+
       this._addName(output, aAccessible, aFlags);
       this._addLandmark(output, aAccessible);
 
       return output;
     },
 
     label: function label(aAccessible, aRoleStr, aStates, aFlags, aContext) {
       if (aContext.isNestedControl ||
@@ -322,28 +332,20 @@ this.OutputGenerator = {
         // we don't need the context.
         return [];
       }
 
       return this.objectOutputFunctions.defaultFunc.apply(this, arguments);
     },
 
     entry: function entry(aAccessible, aRoleStr, aStates, aFlags) {
-      let output = [];
-      let desc = this._getLocalizedStates(aStates);
-      desc.push(this._getLocalizedRole(
-                  (aStates.ext & Ci.nsIAccessibleStates.EXT_STATE_MULTI_LINE) ?
-                    'textarea' : 'entry'));
-
-      output.push(desc.join(' '));
-
-      this._addName(output, aAccessible, aFlags);
-      this._addLandmark(output, aAccessible);
-
-      return output;
+      let rolestr = (aStates.ext & Ci.nsIAccessibleStates.EXT_STATE_MULTI_LINE) ?
+            'textarea' : 'entry';
+      return this.objectOutputFunctions.defaultFunc.apply(
+        this, [aAccessible, rolestr, aStates, aFlags]);
     },
 
     pagetab: function pagetab(aAccessible, aRoleStr, aStates, aFlags) {
       let localizedRole = this._getLocalizedRole(aRoleStr);
       let itemno = {};
       let itemof = {};
       aAccessible.groupPosition({}, itemof, itemno);
       let output = [];
--- a/accessible/tests/mochitest/jsat/output.js
+++ b/accessible/tests/mochitest/jsat/output.js
@@ -20,17 +20,19 @@ Cu.import("resource://gre/modules/access
 function testContextOutput(expected, aAccOrElmOrID, aOldAccOrElmOrID, aGenerator) {
   aOldAccOrElmOrID = aOldAccOrElmOrID || "root";
   var accessible = getAccessible(aAccOrElmOrID);
   var oldAccessible = getAccessible(aOldAccOrElmOrID);
   var context = new PivotContext(accessible, oldAccessible);
   var output = aGenerator.genForContext(context).output;
 
   isDeeply(output, expected,
-    "Context output is correct for " + aAccOrElmOrID);
+           "Context output is correct for " + aAccOrElmOrID +
+           " (output: " + output.join(", ") + ") ==" +
+           " (expected: " + expected.join(", ") + ")");
 }
 
 /**
  * Test object output generated array that includes names.
  * Note: test ignores outputs without the name.
  *
  * @param aAccOrElmOrID identifier to get an accessible to test.
  * @param aGenerator    the output generator to use when generating accessible
--- a/accessible/tests/mochitest/jsat/test_braille.html
+++ b/accessible/tests/mochitest/jsat/test_braille.html
@@ -51,16 +51,22 @@ https://bugzilla.mozilla.org/show_bug.cg
           accOrElmOrID: "ul_li_one",
           expected: [["*", "ul item 1"], ["*", "ul item 1"]]
         },{
           accOrElmOrID: "ol_li_one",
           expected: [["1.", "ol item 1"], ["1.", "ol item 1"]]
         },{
           accOrElmOrID: "textarea",
           expected: [["txtarea", "Here lies treasure."], ["Here lies treasure.", "txtarea"]]
+        },{
+          accOrElmOrID: "textentry",
+          expected: [["entry", "Mario", "First name:"], ["First name:", "Mario", "entry"]]
+        },{
+          accOrElmOrID: "range",
+          expected: [["slider", "3", "Points:"], ["Points:", "3", "slider"]]
         }];
 
         // Test all possible braille order preference values.
         tests.forEach(function run(test) {
           var brailleOrderValues = [0, 1];
           brailleOrderValues.forEach(
             function testBrailleOrder(brailleOrder) {
               SpecialPowers.setIntPref(PREF_UTTERANCE_ORDER, brailleOrder);
@@ -104,11 +110,13 @@ https://bugzilla.mozilla.org/show_bug.cg
         <li id="ul_li_one">ul item 1</li>
         <li id="ul_li_two">ul item 2</li>
         <li id="ul_li_three">ul item 3</li>
         <li id="ul_li_three">ul item 4</li>
       </ul>
       <textarea id="textarea" cols="80" rows="5">
         Here lies treasure.
       </textarea>
+      <label>First name: <input id="textentry" value="Mario"></label>
+      <label>Points: <input id="range" type="range" name="points" min="1" max="10" value="3"></label>
    </div>
   </body>
 </html>
--- a/accessible/tests/mochitest/jsat/test_explicit_names.html
+++ b/accessible/tests/mochitest/jsat/test_explicit_names.html
@@ -23,17 +23,17 @@
       }, {
         accOrElmOrID: "button1",
         expected: ["button", "Press me"]
       }, {
         accOrElmOrID: "button2",
         expected: ["button", "Press me"]
       }, {
         accOrElmOrID: "textarea1",
-        expected: ["text area", "Test Text Area", "This is the text area text."]
+        expected: ["text area", "This is the text area text.", "Test Text Area"]
       }, {
         accOrElmOrID: "textarea2",
         expected: ["text area", "This is the text area text."]
       }, {
         accOrElmOrID: "heading1",
         expected: ["heading level 1", "Test heading", "This is the heading."]
       }, {
         accOrElmOrID: "heading2",
--- a/accessible/tests/mochitest/jsat/test_utterance_order.html
+++ b/accessible/tests/mochitest/jsat/test_utterance_order.html
@@ -166,16 +166,34 @@ https://bugzilla.mozilla.org/show_bug.cg
           expected: [['not checked check button', 'Blue'],
                      ['Blue', 'not checked check button']]
         },
         {
           // This is a nested control.
           accOrElmOrID: "input1",
           expected: [['not checked check button', 'Orange'],
                      ['Orange', 'not checked check button']]
+        },
+        {
+          // Landing on this label should mimic landing on the entry.
+          accOrElmOrID: "label3",
+          expected: [['entry', 'Joe', 'First name:'],
+                     ['First name:', 'Joe', 'entry']]
+        },
+        {
+          // This is a nested control with a value.
+          accOrElmOrID: "input3",
+          expected: [['entry', 'Joe', 'First name:'],
+                     ['First name:', 'Joe', 'entry']]
+        },
+        {
+          // This is a nested control with a value.
+          accOrElmOrID: "input4",
+          expected: [['slider', '3', 'Points:'],
+                     ['Points:', '3', 'slider']]
         }];
 
         // Test all possible utterance order preference values.
         tests.forEach(function run(test) {
           var utteranceOrderValues = [0, 1];
           utteranceOrderValues.forEach(
             function testUtteranceOrder(utteranceOrder) {
               SpecialPowers.setIntPref(PREF_UTTERANCE_ORDER, utteranceOrder);
@@ -249,11 +267,15 @@ https://bugzilla.mozilla.org/show_bug.cg
       <div role="tablist">
         <a id="tab1" href="#" role="tab" aria-selected="true">Account</a>
         <a id="tab2" href="#" role="tab" aria-selected="false">Advanced</a>
       </div>
       <form id="form1">
         <label id="label1"><input id="input1" type="checkbox">Orange</label>
         <input id="input2" type="checkbox"><label id="label2" for="input2">Blue</label>
       </form>
+      <label id="label3">First name: <input id="input3" value="Joe"></label>
+      <label id="label4">Points:
+        <input id="input4" type="range" name="points" min="1" max="10" value="3">
+      </label>
     </div>
   </body>
 </html>