Bug 1001637 - Make math tables implement the nsIAccessibleTable interface. r=surkov
authorFrédéric Wang <fred.wang@free.fr>
Thu, 19 Mar 2015 12:45:59 -0400
changeset 263326 be4f8924a7ce2cc465e393e080b17089a473f349
parent 263325 2cbe6a336b82be50f8ab4b5aaf7b3d38a21fd1f5
child 263327 f974fcf50cedaa6a03282f3bb2cc20b496a3f192
push id4718
push userraliiev@mozilla.com
push dateMon, 11 May 2015 18:39:53 +0000
treeherdermozilla-beta@c20c4ef55f08 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssurkov
bugs1001637
milestone39.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 1001637 - Make math tables implement the nsIAccessibleTable interface. r=surkov
accessible/base/MarkupMap.h
accessible/base/nsAccessibilityService.cpp
accessible/html/HTMLTableAccessible.cpp
accessible/tests/mochitest/table.js
accessible/tests/mochitest/table/a11y.ini
accessible/tests/mochitest/table/test_mtable.html
accessible/tests/mochitest/table/test_struct_ariatreegrid.html
--- a/accessible/base/MarkupMap.h
+++ b/accessible/base/MarkupMap.h
@@ -200,32 +200,32 @@ MARKUPMAP(munderover_,
           AttrFromDOM(accentunder_, accentunder_),
           AttrFromDOM(align, align))
 
 MARKUPMAP(mmultiscripts_,
           New_HyperText,
           roles::MATHML_MULTISCRIPTS)
 
 MARKUPMAP(mtable_,
-          New_HyperText,
+          New_HTMLTableAccessible,
           roles::MATHML_TABLE,
           AttrFromDOM(align, align),
           AttrFromDOM(columnlines_, columnlines_),
           AttrFromDOM(rowlines_, rowlines_))
 
 MARKUPMAP(mlabeledtr_,
-          New_HyperText,
+          New_HTMLTableRowAccessible,
           roles::MATHML_LABELED_ROW)
 
 MARKUPMAP(mtr_,
-          New_HyperText,
+          New_HTMLTableRowAccessible,
           roles::MATHML_TABLE_ROW)
 
 MARKUPMAP(mtd_,
-          New_HyperText,
+          New_HTMLTableCellAccessible,
           roles::MATHML_CELL)
 
 MARKUPMAP(maction_,
           New_HyperText,
           roles::MATHML_ACTION,
           AttrFromDOM(actiontype_, actiontype_),
           AttrFromDOM(selection_, selection_))
 
--- a/accessible/base/nsAccessibilityService.cpp
+++ b/accessible/base/nsAccessibilityService.cpp
@@ -196,16 +196,28 @@ static Accessible* New_HTMLLabel(nsICont
 
 static Accessible* New_HTMLOutput(nsIContent* aContent, Accessible* aContext)
   { return new HTMLOutputAccessible(aContent, aContext->Document()); }
 
 static Accessible* New_HTMLProgress(nsIContent* aContent, Accessible* aContext)
   { return new HTMLProgressMeterAccessible(aContent, aContext->Document()); }
 
 static Accessible*
+New_HTMLTableAccessible(nsIContent* aContent, Accessible* aContext)
+  { return new HTMLTableAccessible(aContent, aContext->Document()); }
+
+static Accessible*
+New_HTMLTableRowAccessible(nsIContent* aContent, Accessible* aContext)
+  { return new HTMLTableRowAccessible(aContent, aContext->Document()); }
+
+static Accessible*
+New_HTMLTableCellAccessible(nsIContent* aContent, Accessible* aContext)
+  { return new HTMLTableCellAccessible(aContent, aContext->Document()); }
+
+static Accessible*
 New_HTMLTableHeaderCell(nsIContent* aContent, Accessible* aContext)
 {
   if (aContext->IsTableRow() && aContext->GetContent() == aContent->GetParent())
     return new HTMLTableHeaderCellAccessibleWrap(aContent, aContext->Document());
   return nullptr;
 }
 
 static Accessible*
--- a/accessible/html/HTMLTableAccessible.cpp
+++ b/accessible/html/HTMLTableAccessible.cpp
@@ -55,16 +55,19 @@ HTMLTableCellAccessible::
 NS_IMPL_ISUPPORTS_INHERITED0(HTMLTableCellAccessible, HyperTextAccessible)
 
 ////////////////////////////////////////////////////////////////////////////////
 // HTMLTableCellAccessible: Accessible implementation
 
 role
 HTMLTableCellAccessible::NativeRole()
 {
+  if (mContent->IsMathMLElement(nsGkAtoms::mtd_)) {
+    return roles::MATHML_CELL;
+  }
   return roles::CELL;
 }
 
 uint64_t
 HTMLTableCellAccessible::NativeState()
 {
   uint64_t state = HyperTextAccessibleWrap::NativeState();
 
@@ -143,18 +146,17 @@ HTMLTableCellAccessible::NativeAttribute
 ////////////////////////////////////////////////////////////////////////////////
 // HTMLTableCellAccessible: TableCellAccessible implementation
 
 TableAccessible*
 HTMLTableCellAccessible::Table() const
 {
   Accessible* parent = const_cast<HTMLTableCellAccessible*>(this);
   while ((parent = parent->Parent())) {
-    roles::Role role = parent->Role();
-    if (role == roles::TABLE || role == roles::TREE_TABLE)
+    if (parent->IsTable())
       return parent->AsTable();
   }
 
   return nullptr;
 }
 
 uint32_t
 HTMLTableCellAccessible::ColIdx() const
@@ -344,16 +346,21 @@ HTMLTableHeaderCellAccessible::NativeRol
 // HTMLTableRowAccessible
 ////////////////////////////////////////////////////////////////////////////////
 
 NS_IMPL_ISUPPORTS_INHERITED0(HTMLTableRowAccessible, Accessible)
 
 role
 HTMLTableRowAccessible::NativeRole()
 {
+  if (mContent->IsMathMLElement(nsGkAtoms::mtr_)) {
+    return roles::MATHML_TABLE_ROW;
+  } else if (mContent->IsMathMLElement(nsGkAtoms::mlabeledtr_)) {
+    return roles::MATHML_LABELED_ROW;
+  }
   return roles::ROW;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // HTMLTableAccessible
 ////////////////////////////////////////////////////////////////////////////////
 
 NS_IMPL_ISUPPORTS_INHERITED0(HTMLTableAccessible, Accessible)
@@ -379,16 +386,19 @@ HTMLTableAccessible::CacheChildren()
     }
     AppendChild(child);
   }
 }
 
 role
 HTMLTableAccessible::NativeRole()
 {
+  if (mContent->IsMathMLElement(nsGkAtoms::mtable_)) {
+    return roles::MATHML_TABLE;
+  }
   return roles::TABLE;
 }
 
 uint64_t
 HTMLTableAccessible::NativeState()
 {
   return Accessible::NativeState() | states::READONLY;
 }
@@ -416,16 +426,21 @@ HTMLTableAccessible::NativeName(nsString
   return eNameOK;
 }
 
 already_AddRefed<nsIPersistentProperties>
 HTMLTableAccessible::NativeAttributes()
 {
   nsCOMPtr<nsIPersistentProperties> attributes =
     AccessibleWrap::NativeAttributes();
+
+  if (mContent->IsMathMLElement(nsGkAtoms::mtable_)) {
+    GetAccService()->MarkupAttributes(mContent, attributes);
+  }
+
   if (IsProbablyLayoutTable()) {
     nsAutoString unused;
     attributes->SetStringProperty(NS_LITERAL_CSTRING("layout-guess"),
                                   NS_LITERAL_STRING("true"), unused);
   }
 
   return attributes.forget();
 }
--- a/accessible/tests/mochitest/table.js
+++ b/accessible/tests/mochitest/table.js
@@ -23,43 +23,61 @@ const kSpanned = kRowSpanned | kColSpann
 /**
  * Constants to define column header type.
  */
 const kNoColumnHeader = 0;
 const kListboxColumnHeader = 1;
 const kTreeColumnHeader = 2;
 
 /**
+ * Constants to define table type.
+ */
+const kTable = 0;
+const kTreeTable = 1;
+const kMathTable = 2;
+
+/**
  * Test table structure and related methods.
  *
  * @param  aIdentifier     [in] table accessible identifier
  * @param  aCellsArray     [in] two dimensional array (row X columns) of
  *                          cell types (see constants defined above).
  * @param  aColHeaderType  [in] specifies wether column header cells are
  *                          arranged into the list.
  * @param  aCaption        [in] caption text if any
  * @param  aSummary        [in] summary text if any
- * @param  aIsTreeTable    [in] specifies whether given table is tree table
+ * @param  aTableType      [in] specifies the table type.
+ * @param  aRowRoles       [in] array of row roles.
  */
 function testTableStruct(aIdentifier, aCellsArray, aColHeaderType,
-                         aCaption, aSummary, aIsTreeTable)
+                         aCaption, aSummary, aTableType, aRowRoles)
 {
   var tableNode = getNode(aIdentifier);
   var isGrid = tableNode.getAttribute("role") == "grid" ||
     tableNode.getAttribute("role") == "treegrid" ||
     tableNode.localName == "tree";
 
   var rowCount = aCellsArray.length;
   var colsCount = aCellsArray[0] ? aCellsArray[0].length : 0;
 
   // Test table accessible tree.
   var tableObj = {
-    role: aIsTreeTable ? ROLE_TREE_TABLE : ROLE_TABLE,
     children: []
   };
+  switch (aTableType) {
+    case kTable:
+      tableObj.role = ROLE_TABLE;
+      break;
+    case kTreeTable:
+      tableObj.role = ROLE_TREE_TABLE;
+      break;
+    case kMathTable:
+      tableObj.role = ROLE_MATHML_TABLE;
+      break;
+  }
 
   // caption accessible handling
   if (aCaption) {
     var captionObj = {
       role: ROLE_CAPTION,
       children: [
         {
           role: ROLE_TEXT_LEAF,
@@ -94,27 +112,28 @@ function testTableStruct(aIdentifier, aC
     }
 
     tableObj.children.push(headersObj);
   }
 
   // rows and cells accessibles
   for (var rowIdx = 0; rowIdx < rowCount; rowIdx++) {
     var rowObj = {
-      role: ROLE_ROW,
+      role: aRowRoles ? aRowRoles[rowIdx] : ROLE_ROW,
       children: []
     };
 
     for (var colIdx = 0; colIdx < colsCount; colIdx++) {
       var celltype = aCellsArray[rowIdx][colIdx];
 
       var role = ROLE_NOTHING;
       switch (celltype) {
         case kDataCell:
-          role = (isGrid ? ROLE_GRID_CELL : ROLE_CELL);
+          role = (aTableType == kMathTable ? ROLE_MATHML_CELL :
+                  (isGrid ? ROLE_GRID_CELL : ROLE_CELL));
           break;
         case kRowHeaderCell:
           role = ROLE_ROWHEADER;
           break;
         case kColHeaderCell:
           role = ROLE_COLUMNHEADER;
           break;
       }
--- a/accessible/tests/mochitest/table/a11y.ini
+++ b/accessible/tests/mochitest/table/a11y.ini
@@ -4,16 +4,17 @@
 [test_headers_listbox.xul]
 [test_headers_table.html]
 [test_headers_tree.xul]
 [test_indexes_ariagrid.html]
 [test_indexes_listbox.xul]
 [test_indexes_table.html]
 [test_indexes_tree.xul]
 [test_layoutguess.html]
+[test_mtable.html]
 [test_sels_ariagrid.html]
 [test_sels_listbox.xul]
 [test_sels_table.html]
 [test_sels_tree.xul]
 [test_struct_ariagrid.html]
 [test_struct_ariatreegrid.html]
 [test_struct_listbox.xul]
 [test_struct_table.html]
new file mode 100644
--- /dev/null
+++ b/accessible/tests/mochitest/table/test_mtable.html
@@ -0,0 +1,128 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <title>MathML table tests</title>
+  <link rel="stylesheet" type="text/css"
+        href="chrome://mochikit/content/tests/SimpleTest/test.css" />
+
+  <script type="application/javascript"
+          src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+
+  <script type="application/javascript"
+          src="../common.js"></script>
+  <script type="application/javascript"
+          src="../role.js"></script>
+  <script type="application/javascript"
+          src="../table.js"></script>
+
+  <script type="application/javascript">
+    function doTest()
+    {
+      // 'Simple' table
+      var idxes = [
+        [0, 1],
+        [2, 3]
+      ];
+      testTableIndexes("simple", idxes);
+      var cellsArray = [
+        [kDataCell, kDataCell],
+        [kDataCell, kDataCell]
+      ];
+      var rowsArray = [ROLE_MATHML_TABLE_ROW, ROLE_MATHML_TABLE_ROW];
+      testTableStruct("simple", cellsArray, kNoColumnHeader,
+                      "", "", kMathTable, rowsArray);
+
+      // 'Complex' table
+      idxes = [
+        [0, 0, 0],
+        [1, 1, 2],
+        [1, 1, 3]
+      ];
+      testTableIndexes("complex", idxes);
+      cellsArray = [
+        [kDataCell,   kColSpanned, kColSpanned],
+        [kDataCell,   kColSpanned, kDataCell],
+        [kRowSpanned, kSpanned,    kDataCell],
+      ];
+      rowsArray = [
+        ROLE_MATHML_TABLE_ROW,
+        ROLE_MATHML_TABLE_ROW,
+        ROLE_MATHML_TABLE_ROW
+      ];
+      testTableStruct("complex", cellsArray, kNoColumnHeader,
+                      "", "", kMathTable, rowsArray);
+
+      // 'Simple' table with mlabeledtr
+      // At the moment we do not implement mlabeledtr but just hide the label
+      // with display: none. Thus we just test the role for now. See bug 689641.
+      var idxes = [[0]];
+      testTableIndexes("simple_label", idxes);
+      var cellsArray = [[kDataCell]];
+      rowsArray = [ROLE_MATHML_LABELED_ROW];
+      testTableStruct("simple_label", cellsArray, kNoColumnHeader,
+                      "", "", kMathTable, rowsArray);
+
+      SimpleTest.finish();
+    }
+
+    SimpleTest.waitForExplicitFinish();
+    addA11yLoadEvent(doTest);
+  </script>
+</head>
+<body>
+  <p id="display"></p>
+  <div id="content" style="display: none"></div>
+  <pre id="test">
+  </pre>
+
+  <math>
+    <mtable id="simple">
+      <mtr>
+        <mtd>
+          <mn>1</mn>
+        </mtd>
+        <mtd>
+          <mn>0</mn>
+        </mtd>
+      </mtr>
+      <mtr>
+        <mtd>
+          <mn>0</mn>
+        </mtd>
+        <mtd>
+          <mn>1</mn>
+        </mtd>
+      </mtr>
+    </mtable>
+
+    <mtable id="complex">
+      <mtr>
+        <mtd columnspan="3">
+          <mtext>1 x 3</mtext>
+        </mtd>
+      </mtr>
+      <mtr>
+        <mtd rowspan="2" columnspan="2">
+          <mtext>2 x 2</mtext>
+        </mtd>
+        <mtd>
+          <mtext>1 x 1</mtext>
+        </mtd>
+      </mtr>
+      <mtr>
+        <mtd>
+          <mtext>1 x 1</mtext>
+        </mtd>
+      </mtr>
+    </mtable>
+
+    <mtable id="simple_label">
+      <mlabeledtr>
+        <mtd><mtext>1</mtext></mtd>
+        <mtd><mtext>label</mtext></mtd>
+      </mlabeledtr>
+    </mtable>
+  </math>
+
+</body>
+</html>
--- a/accessible/tests/mochitest/table/test_struct_ariatreegrid.html
+++ b/accessible/tests/mochitest/table/test_struct_ariatreegrid.html
@@ -23,17 +23,18 @@
       // HTML based ARIA tree grid
 
       var cellsArray = [
         [kColHeaderCell, kColHeaderCell, kColHeaderCell],
         [kDataCell,      kDataCell,      kDataCell],
         [kDataCell,      kDataCell,      kDataCell]
       ];
 
-      testTableStruct("treegrid", cellsArray, kNoColumnHeader, "", "", true);
+      testTableStruct("treegrid", cellsArray, kNoColumnHeader, "", "",
+                      kTreeTable);
 
       SimpleTest.finish();
     }
 
     SimpleTest.waitForExplicitFinish();
     addA11yLoadEvent(doTest);
   </script>
 </head>