Bug 888247 - ARIA columnheader/rowheader shouldn't be selectable by default, r=tbsaunde
authorAlexander Surkov <surkov.alexander@gmail.com>
Fri, 19 Jul 2013 11:20:51 -0400
changeset 139253 6165611d666f70c80400fdae17a0e5e2ff3c0a68
parent 139252 3f7dab57851c4d7b33616ec13d037830d88d2d0a
child 139254 be10b6e8dfad97e3a23aff36965d02ccd2837582
push idunknown
push userunknown
push dateunknown
reviewerstbsaunde
bugs888247
milestone25.0a1
Bug 888247 - ARIA columnheader/rowheader shouldn't be selectable by default, r=tbsaunde
accessible/src/base/ARIAMap.cpp
accessible/src/base/ARIAStateMap.cpp
accessible/src/base/ARIAStateMap.h
accessible/src/generic/ARIAGridAccessible.cpp
accessible/tests/mochitest/table.js
accessible/tests/mochitest/table/test_sels_ariagrid.html
--- a/accessible/src/base/ARIAMap.cpp
+++ b/accessible/src/base/ARIAMap.cpp
@@ -107,17 +107,17 @@ static nsRoleMapEntry sWAIRoleMaps[] =
     &nsGkAtoms::columnheader,
     roles::COLUMNHEADER,
     kUseMapRole,
     eNoValue,
     eSortAction,
     eNoLiveAttr,
     eTableCell,
     kNoReqStates,
-    eARIASelectable,
+    eARIASelectableIfDefined,
     eARIAReadonlyOrEditableIfDefined
   },
   { // combobox
     &nsGkAtoms::combobox,
     roles::COMBOBOX,
     kUseMapRole,
     eNoValue,
     eOpenCloseAction,
@@ -458,17 +458,17 @@ static nsRoleMapEntry sWAIRoleMaps[] =
     &nsGkAtoms::rowheader,
     roles::ROWHEADER,
     kUseMapRole,
     eNoValue,
     eSortAction,
     eNoLiveAttr,
     eTableCell,
     kNoReqStates,
-    eARIASelectable,
+    eARIASelectableIfDefined,
     eARIAReadonlyOrEditableIfDefined
   },
   { // scrollbar
     &nsGkAtoms::scrollbar,
     roles::SCROLLBAR,
     kUseMapRole,
     eHasValueMinMax,
     eNoAction,
--- a/accessible/src/base/ARIAStateMap.cpp
+++ b/accessible/src/base/ARIAStateMap.cpp
@@ -295,16 +295,26 @@ aria::MapToState(EStateRule aRule, dom::
       static const TokenTypeData data(
         nsGkAtoms::aria_selected, eBoolType | eDefinedIfAbsent,
         states::SELECTABLE, states::SELECTED);
 
       MapTokenType(aElement, aState, data);
       return true;
     }
 
+    case eARIASelectableIfDefined:
+    {
+      static const TokenTypeData data(
+        nsGkAtoms::aria_selected, eBoolType,
+        states::SELECTABLE, states::SELECTED);
+
+      MapTokenType(aElement, aState, data);
+      return true;
+    }
+
     case eReadonlyUntilEditable:
     {
       if (!(*aState & states::EDITABLE))
         *aState |= states::READONLY;
 
       return true;
     }
 
--- a/accessible/src/base/ARIAStateMap.h
+++ b/accessible/src/base/ARIAStateMap.h
@@ -37,16 +37,17 @@ enum EStateRule
   eARIAMultiSelectable,
   eARIAOrientation,
   eARIAPressed,
   eARIAReadonly,
   eARIAReadonlyOrEditable,
   eARIAReadonlyOrEditableIfDefined,
   eARIARequired,
   eARIASelectable,
+  eARIASelectableIfDefined,
   eReadonlyUntilEditable,
   eIndeterminateIfNoValue
 };
 
 /**
  * Expose the accessible states for the given element accordingly to state
  * mapping rule.
  *
--- a/accessible/src/generic/ARIAGridAccessible.cpp
+++ b/accessible/src/generic/ARIAGridAccessible.cpp
@@ -460,18 +460,18 @@ ARIAGridAccessible::SetARIASelected(Acce
   nsIContent *content = aAccessible->GetContent();
   NS_ENSURE_STATE(content);
 
   nsresult rv = NS_OK;
   if (aIsSelected)
     rv = content->SetAttr(kNameSpaceID_None, nsGkAtoms::aria_selected,
                           NS_LITERAL_STRING("true"), aNotify);
   else
-    rv = content->UnsetAttr(kNameSpaceID_None,
-                            nsGkAtoms::aria_selected, aNotify);
+    rv = content->SetAttr(kNameSpaceID_None, nsGkAtoms::aria_selected,
+                          NS_LITERAL_STRING("false"), aNotify);
 
   NS_ENSURE_SUCCESS(rv, rv);
 
   // No "smart" select/unselect for internal call.
   if (!aNotify)
     return NS_OK;
 
   // If row or cell accessible was selected then we're able to not bother about
--- a/accessible/tests/mochitest/table.js
+++ b/accessible/tests/mochitest/table.js
@@ -356,17 +356,18 @@ function testTableSelection(aIdentifier,
 
   // Columns selection tests.
   var selCols = new Array();
 
   // isColumnSelected test
   for (var colIdx = 0; colIdx < colsCount; colIdx++) {
     var isColSelected = true;
     for (var rowIdx = 0; rowIdx < rowCount; rowIdx++) {
-      if (aCellsArray[rowIdx][colIdx] == false) {
+      if (aCellsArray[rowIdx][colIdx] == false ||
+          aCellsArray[rowIdx][colIdx] == undefined) {
         isColSelected = false;
         break;
       }
     }
 
     is(acc.isColumnSelected(colIdx), isColSelected,
        msg + "Wrong selection state of " + colIdx + " column for " +
        prettyName(aIdentifier));
@@ -396,17 +397,18 @@ function testTableSelection(aIdentifier,
   // Rows selection tests.
   var selRows = new Array();
 
   // isRowSelected test
   var selrowCount = 0;
   for (var rowIdx = 0; rowIdx < rowCount; rowIdx++) {
     var isRowSelected = true;
     for (var colIdx = 0; colIdx < colsCount; colIdx++) {
-      if (aCellsArray[rowIdx][colIdx] == false) {
+      if (aCellsArray[rowIdx][colIdx] == false ||
+          aCellsArray[rowIdx][colIdx] == undefined) {
         isRowSelected = false;
         break;
       }
     }
 
     is(acc.isRowSelected(rowIdx), isRowSelected,
        msg + "Wrong selection state of " + rowIdx + " row for " +
        prettyName(aIdentifier));
@@ -437,17 +439,18 @@ function testTableSelection(aIdentifier,
   var selCells = new Array();
 
   // isCellSelected test
   for (var rowIdx = 0; rowIdx < rowCount; rowIdx++) {
     for (var colIdx = 0; colIdx < colsCount; colIdx++) {
       if (aCellsArray[rowIdx][colIdx] & kSpanned)
         continue;
 
-      is(acc.isCellSelected(rowIdx, colIdx), aCellsArray[rowIdx][colIdx],
+      var isSelected = aCellsArray[rowIdx][colIdx] == true;
+      is(acc.isCellSelected(rowIdx, colIdx), isSelected,
          msg + "Wrong selection state of cell at " + rowIdx + " row and " +
          colIdx + " column for " + prettyName(aIdentifier));
 
       if (aCellsArray[rowIdx][colIdx])
         selCells.push(acc.getCellIndexAt(rowIdx, colIdx));
     }
   }
 
@@ -491,17 +494,19 @@ function testTableSelection(aIdentifier,
   // selected states tests
   for (var rowIdx = 0; rowIdx < rowCount; rowIdx++) {
     for (var colIdx = 0; colIdx < colsCount; colIdx++) {
       if (aCellsArray[rowIdx][colIdx] & kSpanned)
         continue;
 
       var cell = acc.getCellAt(rowIdx, colIdx);
       var isSel = aCellsArray[rowIdx][colIdx];
-      if (isSel)
+      if (isSel == undefined)
+        testStates(cell, 0, 0, STATE_SELECTABLE | STATE_SELECTED);
+      else if (isSel == true)
         testStates(cell, STATE_SELECTED);
       else
         testStates(cell, STATE_SELECTABLE, 0, STATE_SELECTED);
     }
   }
 }
 
 /**
--- a/accessible/tests/mochitest/table/test_sels_ariagrid.html
+++ b/accessible/tests/mochitest/table/test_sels_ariagrid.html
@@ -49,31 +49,49 @@ https://bugzilla.mozilla.org/show_bug.cg
       ];
 
       testTableSelection("grid2", cellsArray);
       testSelectTableColumn("grid2", 0, cellsArray);
       testSelectTableRow("grid2", 0, cellsArray);
       testUnselectTableColumn("grid2", 0, cellsArray);
       testUnselectTableRow("grid2", 0, cellsArray);
 
+      //////////////////////////////////////////////////////////////////////////
+      // ARIA grid (column and row headers)
+
+      cellsArray =
+      [
+        [ undefined, true, false],
+        [ undefined, true, false]
+      ];
+
+      testTableSelection("grid3", cellsArray);
+      testSelectTableColumn("grid3", 0, cellsArray);
+      testSelectTableRow("grid3", 0, cellsArray);
+      testUnselectTableColumn("grid3", 0, cellsArray);
+      testUnselectTableRow("grid3", 0, cellsArray);
+
       SimpleTest.finish();
     }
 
     SimpleTest.waitForExplicitFinish();
     addA11yLoadEvent(doTest);
   </script>
 </head>
 <body>
 
   <a target="_blank"
      title="implement nsIAccessibleTable selection methods for ARIA grids"
-     href="https://bugzilla.mozilla.org/show_bug.cgi?id=410052">Mozilla Bug 410052</a>
+     href="https://bugzilla.mozilla.org/show_bug.cgi?id=410052">Bug 410052</a>
   <a target="_blank"
      title="nsHTMLTableCellAccessible is used in dojo's crazy ARIA grid"
-     href="https://bugzilla.mozilla.org/show_bug.cgi?id=513848">Mozilla Bug 513848</a>
+     href="https://bugzilla.mozilla.org/show_bug.cgi?id=513848">Bug 513848</a>
+  <a target="_blank"
+     title="ARIA columnheader/rowheader shouldn't be selectable by default"
+     href="https://bugzilla.mozilla.org/show_bug.cgi?id=888247">Bug 888247</a>
 
   <p id="display"></p>
   <div id="content" style="display: none"></div>
   <pre id="test">
   </pre>
 
   <div role="grid" id="table">
     <div role="row">
@@ -107,25 +125,37 @@ https://bugzilla.mozilla.org/show_bug.cg
       <span role="gridcell" aria-selected="true">cell20</span>
     </div>
   </div>
 
   <div role="grid" id="grid2">
     <div role="row">
       <table role="presentation">
         <tr>
-          <td role="columnheader">header1</td>
-          <td role="columnheader">header2</td>
+          <td role="columnheader" aria-selected="false">header1</td>
+          <td role="columnheader" aria-selected="false">header2</td>
         </tr>
       </table>
     </div>
     <div role="row">
       <table role="presentation">
         <tr>
           <td role="gridcell">cell1</td>
           <td role="gridcell" tabindex="-1">cell2</td>
         </tr>
       </table>
     </div>
   </div>
 
+  <div role="grid" id="grid3">
+    <div role="row">
+      <div role="columnheader" id="colheader_default">col header1</div>
+      <div role="columnheader" id="colheader_selected" aria-selected="true">col header2</div>
+      <div role="columnheader" id="colheader_notselected" aria-selected="false">col header3</div>
+    </div>
+    <div role="row">
+      <div role="rowheader" id="rowheader_default">row header1</div>
+      <div role="rowheader" id="rowheader_selected" aria-selected="true">row header2</div>
+      <div role="rowheader" id="rowheader_notselected" aria-selected="false">row header3</div>
+    </div>
+  </div>
 </body>
 </html>