<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[188203] trunk</title>
</head>
<body>
<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; }
#msg dl a { font-weight: bold}
#msg dl a:link { color:#fc3; }
#msg dl a:active { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/188203">188203</a></dd>
<dt>Author</dt> <dd>commit-queue@webkit.org</dd>
<dt>Date</dt> <dd>2015-08-09 18:53:10 -0700 (Sun, 09 Aug 2015)</dd>
</dl>
<h3>Log Message</h3>
<pre>AX: CSS table display styles can cause malformed, inaccessible AXTables to be exposed to the AX tree
https://bugs.webkit.org/show_bug.cgi?id=136415
<rdar://problem/22026625>
Patch by Nan Wang <n_wang@apple.com> on 2015-08-09
Reviewed by Chris Fleizach.
Source/WebCore:
Applying CSS display styles to tables can end up inserting anonymous RenderTableRows, which is not handled well by the
accessibility code, which treats these as the actual rows. We can address this by diving deeper into anonymous nodes
and finding the real rows and cells we want. In addition, another thing also causing malformed tables is that "grid"
roles are being exposed as AXGrid instead of AXTable.
Test: accessibility/mac/malformed-table.html
* accessibility/AccessibilityARIAGrid.cpp:
(WebCore::AccessibilityARIAGrid::addRowDescendant):
* accessibility/AccessibilityTable.cpp:
(WebCore::AccessibilityTable::addChildren):
(WebCore::AccessibilityTable::addTableCellChild):
(WebCore::AccessibilityTable::addChildrenFromSection):
* accessibility/AccessibilityTable.h:
* accessibility/AccessibilityTableCell.cpp:
(WebCore::AccessibilityTableCell::parentTable):
(WebCore::AccessibilityTableCell::rowIndexRange):
* accessibility/AccessibilityTableRow.cpp:
(WebCore::AccessibilityTableRow::parentTable):
* accessibility/mac/WebAccessibilityObjectWrapperMac.mm:
(createAccessibilityRoleMap):
LayoutTests:
* accessibility/aria-table-with-presentational-elements-expected.txt:
* accessibility/aria-table-with-presentational-elements.html:
* accessibility/mac/malformed-table-expected.txt: Added.
* accessibility/mac/malformed-table.html: Added.
* platform/mac-mavericks/accessibility/roles-exposed-expected.txt:
* platform/mac/accessibility/aria-table-hierarchy-expected.txt:
* platform/mac/accessibility/aria-tables-expected.txt:
* platform/mac/accessibility/roles-exposed-expected.txt:</pre>
<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsChangeLog">trunk/LayoutTests/ChangeLog</a></li>
<li><a href="#trunkLayoutTestsaccessibilityariatablewithpresentationalelementsexpectedtxt">trunk/LayoutTests/accessibility/aria-table-with-presentational-elements-expected.txt</a></li>
<li><a href="#trunkLayoutTestsaccessibilityariatablewithpresentationalelementshtml">trunk/LayoutTests/accessibility/aria-table-with-presentational-elements.html</a></li>
<li><a href="#trunkLayoutTestsplatformmacaccessibilityariatablehierarchyexpectedtxt">trunk/LayoutTests/platform/mac/accessibility/aria-table-hierarchy-expected.txt</a></li>
<li><a href="#trunkLayoutTestsplatformmacaccessibilityariatablesexpectedtxt">trunk/LayoutTests/platform/mac/accessibility/aria-tables-expected.txt</a></li>
<li><a href="#trunkLayoutTestsplatformmacaccessibilityrolesexposedexpectedtxt">trunk/LayoutTests/platform/mac/accessibility/roles-exposed-expected.txt</a></li>
<li><a href="#trunkLayoutTestsplatformmacmavericksaccessibilityrolesexposedexpectedtxt">trunk/LayoutTests/platform/mac-mavericks/accessibility/roles-exposed-expected.txt</a></li>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoreaccessibilityAccessibilityARIAGridcpp">trunk/Source/WebCore/accessibility/AccessibilityARIAGrid.cpp</a></li>
<li><a href="#trunkSourceWebCoreaccessibilityAccessibilityTablecpp">trunk/Source/WebCore/accessibility/AccessibilityTable.cpp</a></li>
<li><a href="#trunkSourceWebCoreaccessibilityAccessibilityTableh">trunk/Source/WebCore/accessibility/AccessibilityTable.h</a></li>
<li><a href="#trunkSourceWebCoreaccessibilityAccessibilityTableCellcpp">trunk/Source/WebCore/accessibility/AccessibilityTableCell.cpp</a></li>
<li><a href="#trunkSourceWebCoreaccessibilityAccessibilityTableRowcpp">trunk/Source/WebCore/accessibility/AccessibilityTableRow.cpp</a></li>
<li><a href="#trunkSourceWebCoreaccessibilitymacWebAccessibilityObjectWrapperMacmm">trunk/Source/WebCore/accessibility/mac/WebAccessibilityObjectWrapperMac.mm</a></li>
</ul>
<h3>Added Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsaccessibilitymacmalformedtableexpectedtxt">trunk/LayoutTests/accessibility/mac/malformed-table-expected.txt</a></li>
<li><a href="#trunkLayoutTestsaccessibilitymacmalformedtablehtml">trunk/LayoutTests/accessibility/mac/malformed-table.html</a></li>
</ul>
</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (188202 => 188203)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog        2015-08-10 00:10:01 UTC (rev 188202)
+++ trunk/LayoutTests/ChangeLog        2015-08-10 01:53:10 UTC (rev 188203)
</span><span class="lines">@@ -1,3 +1,20 @@
</span><ins>+2015-08-09 Nan Wang <n_wang@apple.com>
+
+ AX: CSS table display styles can cause malformed, inaccessible AXTables to be exposed to the AX tree
+ https://bugs.webkit.org/show_bug.cgi?id=136415
+ <rdar://problem/22026625>
+
+ Reviewed by Chris Fleizach.
+
+ * accessibility/aria-table-with-presentational-elements-expected.txt:
+ * accessibility/aria-table-with-presentational-elements.html:
+ * accessibility/mac/malformed-table-expected.txt: Added.
+ * accessibility/mac/malformed-table.html: Added.
+ * platform/mac-mavericks/accessibility/roles-exposed-expected.txt:
+ * platform/mac/accessibility/aria-table-hierarchy-expected.txt:
+ * platform/mac/accessibility/aria-tables-expected.txt:
+ * platform/mac/accessibility/roles-exposed-expected.txt:
+
</ins><span class="cx"> 2015-08-08 Darin Adler <darin@apple.com>
</span><span class="cx">
</span><span class="cx"> Remove -webkit-color-correction CSS property
</span></span></pre></div>
<a id="trunkLayoutTestsaccessibilityariatablewithpresentationalelementsexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/accessibility/aria-table-with-presentational-elements-expected.txt (188202 => 188203)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/accessibility/aria-table-with-presentational-elements-expected.txt        2015-08-10 00:10:01 UTC (rev 188202)
+++ trunk/LayoutTests/accessibility/aria-table-with-presentational-elements-expected.txt        2015-08-10 01:53:10 UTC (rev 188203)
</span><span class="lines">@@ -4,7 +4,7 @@
</span><span class="cx">
</span><span class="cx">
</span><span class="cx"> PASS row.role is 'AXRole: AXRow'
</span><del>-PASS row.parentElement().role is 'AXRole: AXGrid'
</del><ins>+PASS row.parentElement().role is 'AXRole: AXTable'
</ins><span class="cx"> PASS successfullyParsed is true
</span><span class="cx">
</span><span class="cx"> TEST COMPLETE
</span></span></pre></div>
<a id="trunkLayoutTestsaccessibilityariatablewithpresentationalelementshtml"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/accessibility/aria-table-with-presentational-elements.html (188202 => 188203)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/accessibility/aria-table-with-presentational-elements.html        2015-08-10 00:10:01 UTC (rev 188202)
+++ trunk/LayoutTests/accessibility/aria-table-with-presentational-elements.html        2015-08-10 01:53:10 UTC (rev 188203)
</span><span class="lines">@@ -32,7 +32,7 @@
</span><span class="cx"> var table = accessibilityController.accessibleElementById("table");
</span><span class="cx"> var row = table.rowAtIndex(0);
</span><span class="cx"> shouldBe("row.role", "'AXRole: AXRow'");
</span><del>- shouldBe("row.parentElement().role", "'AXRole: AXGrid'");
</del><ins>+ shouldBe("row.parentElement().role", "'AXRole: AXTable'");
</ins><span class="cx">
</span><span class="cx"> document.getElementById("content").style.visibility = "hidden";
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkLayoutTestsaccessibilitymacmalformedtableexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/accessibility/mac/malformed-table-expected.txt (0 => 188203)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/accessibility/mac/malformed-table-expected.txt         (rev 0)
+++ trunk/LayoutTests/accessibility/mac/malformed-table-expected.txt        2015-08-10 01:53:10 UTC (rev 188203)
</span><span class="lines">@@ -0,0 +1,53 @@
</span><ins>+Table with CSS and ARIA
+Heading one        Heading two
+a        b
+Table with CSS and no ARIA
+Heading one        Heading two
+a        b
+This tests that contents in malformed tables are accessible.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS table1.role is 'AXRole: AXTable'
+PASS table2.role is 'AXRole: AXTable'
+PASS table1ColumnCount is 2
+PASS table1RowCount is 2
+PASS table2ColumnCount is 2
+PASS table2RowCount is 2
+
+Check rows for Table1
+PASS rowa.isEqual(rowb) is true
+PASS rowa.role is 'AXRole: AXRow'
+PASS rowa.isEqual(rowb) is true
+PASS rowa.role is 'AXRole: AXRow'
+
+Check rows for Table2
+PASS rowa.isEqual(rowb) is true
+PASS rowa.role is 'AXRole: AXRow'
+PASS rowa.isEqual(rowb) is true
+PASS rowa.role is 'AXRole: AXRow'
+
+Check cells for Table1
+PASS cella.isEqual(cellb) is true
+PASS cella.role is 'AXRole: AXCell'
+PASS cella.isEqual(cellb) is true
+PASS cella.role is 'AXRole: AXCell'
+PASS cella.isEqual(cellb) is true
+PASS cella.role is 'AXRole: AXCell'
+PASS cella.isEqual(cellb) is true
+PASS cella.role is 'AXRole: AXCell'
+
+Check cells for Table2
+PASS cella.isEqual(cellb) is true
+PASS cella.role is 'AXRole: AXCell'
+PASS cella.isEqual(cellb) is true
+PASS cella.role is 'AXRole: AXCell'
+PASS cella.isEqual(cellb) is true
+PASS cella.role is 'AXRole: AXCell'
+PASS cella.isEqual(cellb) is true
+PASS cella.role is 'AXRole: AXCell'
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
</ins></span></pre></div>
<a id="trunkLayoutTestsaccessibilitymacmalformedtablehtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/accessibility/mac/malformed-table.html (0 => 188203)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/accessibility/mac/malformed-table.html         (rev 0)
+++ trunk/LayoutTests/accessibility/mac/malformed-table.html        2015-08-10 01:53:10 UTC (rev 188203)
</span><span class="lines">@@ -0,0 +1,107 @@
</span><ins>+<!DOCTYPE>
+<html>
+<script src="../../resources/js-test-pre.js"></script>
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ <title>Table test</title>
+ <style>
+ table {border: 1px solid;}
+ table th {background-color: #eeeeee;}
+ table td {background-color: #dddddd;}
+ .table thead {display:block;}
+ .table tbody {display:block;}
+ .table2 thead {display:block;}
+ .table2 tbody {display:block;}
+ </style>
+</head>
+<body id="body">
+
+<table role="grid" class="table" id="table">
+ <caption>Table with CSS and ARIA</caption>
+ <thead>
+ <tr role="row">
+ <th role="gridcell">Heading one</th>
+ <th role="gridcell">Heading two</th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr role="row">
+ <td role="gridcell">a</td>
+ <td role="gridcell">b</td>
+ </tr>
+ </tbody>
+</table>
+
+<table class="table2" id="table2">
+ <caption>Table with CSS and no ARIA</caption>
+ <thead>
+ <tr>
+ <th>Heading one</th>
+ <th>Heading two</th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr>
+ <td>a</td>
+ <td>b</td>
+ </tr>
+ <tbody>
+</table>
+
+<p id="description"></p>
+<div id="console"></div>
+
+<script>
+
+ description("This tests that contents in malformed tables are accessible.");
+
+ if (window.accessibilityController) {
+ var table1 = accessibilityController.accessibleElementById("table");
+ var table2 = accessibilityController.accessibleElementById("table2");
+ var tableArray = [table1, table2];
+ // check for table role
+ shouldBe("table1.role", "'AXRole: AXTable'");
+ shouldBe("table2.role", "'AXRole: AXTable'");
+
+ // check for correct column and row count
+ var table1ColumnCount = table1.numberAttributeValue("AXColumnCount");
+ var table1RowCount = table1.numberAttributeValue("AXRowCount");
+ var table2ColumnCount = table2.numberAttributeValue("AXColumnCount");
+ var table2RowCount = table2.numberAttributeValue("AXRowCount");
+ shouldBe("table1ColumnCount", "2");
+ shouldBe("table1RowCount", "2");
+ shouldBe("table2ColumnCount", "2");
+ shouldBe("table2RowCount", "2");
+
+ // check rows
+ for (var tableIndex = 0; tableIndex < 2; tableIndex++) {
+ debug("\nCheck rows for Table" + (tableIndex+1));
+ var table = tableArray[tableIndex];
+ for (var i = 0; i < 2; i++) {
+ var rowa = table.rowAtIndex(i);
+ var rowb = table.childAtIndex(i);
+ shouldBeTrue("rowa.isEqual(rowb)");
+ shouldBe("rowa.role", "'AXRole: AXRow'");
+ }
+ }
+
+ // check cells
+ for (var tableIndex = 0; tableIndex < 2; tableIndex++) {
+ debug("\nCheck cells for Table" + (tableIndex+1));
+ var table = tableArray[tableIndex];
+ for (var i = 0; i < 2; i++) {
+ for (var j = 0; j < 2; j++) {
+ var cella = table.cellForColumnAndRow(i, j);
+ var cellb = table.childAtIndex(j).childAtIndex(i);
+ shouldBeTrue("cella.isEqual(cellb)");
+ shouldBe("cella.role", "'AXRole: AXCell'");
+ }
+ }
+ }
+ }
+
+</script>
+
+<script src="../../resources/js-test-post.js"></script>
+</body>
+</html>
</ins></span></pre></div>
<a id="trunkLayoutTestsplatformmacaccessibilityariatablehierarchyexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/platform/mac/accessibility/aria-table-hierarchy-expected.txt (188202 => 188203)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/platform/mac/accessibility/aria-table-hierarchy-expected.txt        2015-08-10 00:10:01 UTC (rev 188202)
+++ trunk/LayoutTests/platform/mac/accessibility/aria-table-hierarchy-expected.txt        2015-08-10 01:53:10 UTC (rev 188203)
</span><span class="lines">@@ -25,7 +25,7 @@
</span><span class="cx">
</span><span class="cx">
</span><span class="cx"> AXRole: AXWebArea AXValue:
</span><del>- AXRole: AXGrid AXValue:
</del><ins>+ AXRole: AXTable AXValue:
</ins><span class="cx"> AXRole: AXRow AXValue:
</span><span class="cx"> AXRole: AXCell AXValue:
</span><span class="cx"> AXRole: AXStaticText AXValue: foo
</span><span class="lines">@@ -38,7 +38,7 @@
</span><span class="cx"> AXRole: AXCell AXValue:
</span><span class="cx"> AXRole: AXStaticText AXValue: bar
</span><span class="cx"> AXRole: AXGroup AXValue:
</span><del>- AXRole: AXGrid AXValue:
</del><ins>+ AXRole: AXTable AXValue:
</ins><span class="cx"> AXRole: AXRow AXValue:
</span><span class="cx"> AXRole: AXCell AXValue:
</span><span class="cx"> AXRole: AXStaticText AXValue: Odd
</span><span class="lines">@@ -73,7 +73,7 @@
</span><span class="cx"> AXRole: AXStaticText AXValue: Odd
</span><span class="cx"> AXRole: AXCell AXValue:
</span><span class="cx"> AXRole: AXStaticText AXValue: Even
</span><del>- AXRole: AXGrid AXValue:
</del><ins>+ AXRole: AXTable AXValue:
</ins><span class="cx"> AXRole: AXRow AXValue:
</span><span class="cx"> AXRole: AXCell AXValue:
</span><span class="cx"> AXRole: AXStaticText AXValue: hello
</span><span class="lines">@@ -86,7 +86,7 @@
</span><span class="cx"> AXRole: AXCell AXValue:
</span><span class="cx"> AXRole: AXStaticText AXValue: world
</span><span class="cx"> AXRole: AXGroup AXValue:
</span><del>- AXRole: AXGrid AXValue:
</del><ins>+ AXRole: AXTable AXValue:
</ins><span class="cx"> AXRole: AXRow AXValue:
</span><span class="cx"> AXRole: AXCell AXValue:
</span><span class="cx"> AXRole: AXStaticText AXValue: Odd
</span></span></pre></div>
<a id="trunkLayoutTestsplatformmacaccessibilityariatablesexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/platform/mac/accessibility/aria-tables-expected.txt (188202 => 188203)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/platform/mac/accessibility/aria-tables-expected.txt        2015-08-10 00:10:01 UTC (rev 188202)
+++ trunk/LayoutTests/platform/mac/accessibility/aria-tables-expected.txt        2015-08-10 01:53:10 UTC (rev 188203)
</span><span class="lines">@@ -10,8 +10,8 @@
</span><span class="cx"> header 1        header 2        header 2
</span><span class="cx"> cell        cell        cell
</span><span class="cx"> cell
</span><del>-AXRole: AXGrid
-AXRole: AXGrid
</del><ins>+AXRole: AXTable
+AXRole: AXTable
</ins><span class="cx"> AXRole: AXCell
</span><span class="cx"> AXRole: AXCell
</span><span class="cx"> AXRole: AXCell
</span></span></pre></div>
<a id="trunkLayoutTestsplatformmacaccessibilityrolesexposedexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/platform/mac/accessibility/roles-exposed-expected.txt (188202 => 188203)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/platform/mac/accessibility/roles-exposed-expected.txt        2015-08-10 00:10:01 UTC (rev 188202)
+++ trunk/LayoutTests/platform/mac/accessibility/roles-exposed-expected.txt        2015-08-10 01:53:10 UTC (rev 188203)
</span><span class="lines">@@ -875,9 +875,9 @@
</span><span class="cx"> AXRoleDescription: group
</span><span class="cx">
</span><span class="cx"> div[role=grid]
</span><del>- AXRole: AXGrid
</del><ins>+ AXRole: AXTable
</ins><span class="cx"> AXSubrole:
</span><del>- AXRoleDescription: grid
</del><ins>+ AXRoleDescription: table
</ins><span class="cx">
</span><span class="cx"> div[role=rowgroup]
</span><span class="cx"> AXRole:
</span><span class="lines">@@ -1135,9 +1135,9 @@
</span><span class="cx"> AXRoleDescription: outline row
</span><span class="cx">
</span><span class="cx"> div[role=treegrid]
</span><del>- AXRole: AXGrid
</del><ins>+ AXRole: AXTable
</ins><span class="cx"> AXSubrole:
</span><del>- AXRoleDescription: grid
</del><ins>+ AXRoleDescription: table
</ins><span class="cx">
</span><span class="cx"> div[role=rowgroup]
</span><span class="cx"> AXRole:
</span></span></pre></div>
<a id="trunkLayoutTestsplatformmacmavericksaccessibilityrolesexposedexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/platform/mac-mavericks/accessibility/roles-exposed-expected.txt (188202 => 188203)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/platform/mac-mavericks/accessibility/roles-exposed-expected.txt        2015-08-10 00:10:01 UTC (rev 188202)
+++ trunk/LayoutTests/platform/mac-mavericks/accessibility/roles-exposed-expected.txt        2015-08-10 01:53:10 UTC (rev 188203)
</span><span class="lines">@@ -875,9 +875,9 @@
</span><span class="cx"> AXRoleDescription: group
</span><span class="cx">
</span><span class="cx"> div[role=grid]
</span><del>- AXRole: AXGrid
</del><ins>+ AXRole: AXTable
</ins><span class="cx"> AXSubrole:
</span><del>- AXRoleDescription: grid
</del><ins>+ AXRoleDescription: table
</ins><span class="cx">
</span><span class="cx"> div[role=rowgroup]
</span><span class="cx"> AXRole:
</span><span class="lines">@@ -1135,9 +1135,9 @@
</span><span class="cx"> AXRoleDescription: outline row
</span><span class="cx">
</span><span class="cx"> div[role=treegrid]
</span><del>- AXRole: AXGrid
</del><ins>+ AXRole: AXTable
</ins><span class="cx"> AXSubrole:
</span><del>- AXRoleDescription: grid
</del><ins>+ AXRoleDescription: table
</ins><span class="cx">
</span><span class="cx"> div[role=rowgroup]
</span><span class="cx"> AXRole:
</span></span></pre></div>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (188202 => 188203)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2015-08-10 00:10:01 UTC (rev 188202)
+++ trunk/Source/WebCore/ChangeLog        2015-08-10 01:53:10 UTC (rev 188203)
</span><span class="lines">@@ -1,3 +1,33 @@
</span><ins>+2015-08-09 Nan Wang <n_wang@apple.com>
+
+ AX: CSS table display styles can cause malformed, inaccessible AXTables to be exposed to the AX tree
+ https://bugs.webkit.org/show_bug.cgi?id=136415
+ <rdar://problem/22026625>
+
+ Reviewed by Chris Fleizach.
+
+ Applying CSS display styles to tables can end up inserting anonymous RenderTableRows, which is not handled well by the
+ accessibility code, which treats these as the actual rows. We can address this by diving deeper into anonymous nodes
+ and finding the real rows and cells we want. In addition, another thing also causing malformed tables is that "grid"
+ roles are being exposed as AXGrid instead of AXTable.
+
+ Test: accessibility/mac/malformed-table.html
+
+ * accessibility/AccessibilityARIAGrid.cpp:
+ (WebCore::AccessibilityARIAGrid::addRowDescendant):
+ * accessibility/AccessibilityTable.cpp:
+ (WebCore::AccessibilityTable::addChildren):
+ (WebCore::AccessibilityTable::addTableCellChild):
+ (WebCore::AccessibilityTable::addChildrenFromSection):
+ * accessibility/AccessibilityTable.h:
+ * accessibility/AccessibilityTableCell.cpp:
+ (WebCore::AccessibilityTableCell::parentTable):
+ (WebCore::AccessibilityTableCell::rowIndexRange):
+ * accessibility/AccessibilityTableRow.cpp:
+ (WebCore::AccessibilityTableRow::parentTable):
+ * accessibility/mac/WebAccessibilityObjectWrapperMac.mm:
+ (createAccessibilityRoleMap):
+
</ins><span class="cx"> 2015-08-08 Darin Adler <darin@apple.com>
</span><span class="cx">
</span><span class="cx"> Remove -webkit-color-correction CSS property
</span></span></pre></div>
<a id="trunkSourceWebCoreaccessibilityAccessibilityARIAGridcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/accessibility/AccessibilityARIAGrid.cpp (188202 => 188203)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/accessibility/AccessibilityARIAGrid.cpp        2015-08-10 00:10:01 UTC (rev 188202)
+++ trunk/Source/WebCore/accessibility/AccessibilityARIAGrid.cpp        2015-08-10 01:53:10 UTC (rev 188203)
</span><span class="lines">@@ -87,9 +87,9 @@
</span><span class="cx"> if (!rowChild)
</span><span class="cx"> return;
</span><span class="cx">
</span><del>- if (!rowChild->isTableRow()) {
</del><ins>+ if (!rowChild->isTableRow() || !rowChild->node()) {
</ins><span class="cx"> // Although a "grid" should have rows as its direct descendants, if this is not a table row,
</span><del>- // dive deeper into the descendants to try to find a valid row.
</del><ins>+ // or this row is anonymous, dive deeper into the descendants to try to find a valid row.
</ins><span class="cx"> for (const auto& child : rowChild->children())
</span><span class="cx"> addRowDescendant(child.get(), appendedRows, columnCount);
</span><span class="cx"> } else
</span></span></pre></div>
<a id="trunkSourceWebCoreaccessibilityAccessibilityTablecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/accessibility/AccessibilityTable.cpp (188202 => 188203)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/accessibility/AccessibilityTable.cpp        2015-08-10 00:10:01 UTC (rev 188202)
+++ trunk/Source/WebCore/accessibility/AccessibilityTable.cpp        2015-08-10 01:53:10 UTC (rev 188203)
</span><span class="lines">@@ -44,6 +44,8 @@
</span><span class="cx"> #include "RenderTableCell.h"
</span><span class="cx"> #include "RenderTableSection.h"
</span><span class="cx">
</span><ins>+#include <wtf/Deque.h>
+
</ins><span class="cx"> namespace WebCore {
</span><span class="cx">
</span><span class="cx"> using namespace HTMLNames;
</span><span class="lines">@@ -421,6 +423,29 @@
</span><span class="cx">
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+void AccessibilityTable::addTableCellChild(AccessibilityObject* rowObject, HashSet<AccessibilityObject*>& appendedRows, unsigned& columnCount)
+{
+ if (!rowObject || !is<AccessibilityTableRow>(*rowObject))
+ return;
+
+ auto& row = downcast<AccessibilityTableRow>(*rowObject);
+ // We need to check every cell for a new row, because cell spans
+ // can cause us to miss rows if we just check the first column.
+ if (appendedRows.contains(&row))
+ return;
+
+ row.setRowIndex(static_cast<int>(m_rows.size()));
+ m_rows.append(&row);
+ if (!row.accessibilityIsIgnored())
+ m_children.append(&row);
+ appendedRows.add(&row);
+
+ // store the maximum number of columns
+ unsigned rowCellCount = row.children().size();
+ if (rowCellCount > columnCount)
+ columnCount = rowCellCount;
+}
+
</ins><span class="cx"> void AccessibilityTable::addChildrenFromSection(RenderTableSection* tableSection, unsigned& maxColumnCount)
</span><span class="cx"> {
</span><span class="cx"> ASSERT(tableSection);
</span><span class="lines">@@ -437,20 +462,23 @@
</span><span class="cx"> continue;
</span><span class="cx">
</span><span class="cx"> AccessibilityObject& rowObject = *axCache->getOrCreate(renderRow);
</span><del>- if (!is<AccessibilityTableRow>(rowObject))
- continue;
</del><span class="cx">
</span><del>- auto& row = downcast<AccessibilityTableRow>(rowObject);
- // We need to check every cell for a new row, because cell spans
- // can cause us to miss rows if we just check the first column.
- if (appendedRows.contains(&row))
- continue;
-
- row.setRowIndex(static_cast<int>(m_rows.size()));
- m_rows.append(&row);
- if (!row.accessibilityIsIgnored())
- m_children.append(&row);
- appendedRows.add(&row);
</del><ins>+ // If the row is anonymous, we should dive deeper into the descendants to try to find a valid row.
+ if (renderRow->isAnonymous()) {
+ Deque<AccessibilityObject*> queue;
+ queue.append(&rowObject);
+
+ while (!queue.isEmpty()) {
+ AccessibilityObject* obj = queue.takeFirst();
+ if (obj->node() && is<AccessibilityTableRow>(*obj)) {
+ addTableCellChild(obj, appendedRows, maxColumnCount);
+ continue;
+ }
+ for (auto child = obj->firstChild(); child; child = child->nextSibling())
+ queue.append(child);
+ }
+ } else
+ addTableCellChild(&rowObject, appendedRows, maxColumnCount);
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> maxColumnCount = std::max(tableSection->numColumns(), maxColumnCount);
</span></span></pre></div>
<a id="trunkSourceWebCoreaccessibilityAccessibilityTableh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/accessibility/AccessibilityTable.h (188202 => 188203)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/accessibility/AccessibilityTable.h        2015-08-10 00:10:01 UTC (rev 188202)
+++ trunk/Source/WebCore/accessibility/AccessibilityTable.h        2015-08-10 01:53:10 UTC (rev 188203)
</span><span class="lines">@@ -98,6 +98,7 @@
</span><span class="cx"> virtual void titleElementText(Vector<AccessibilityText>&) const override final;
</span><span class="cx"> HTMLTableElement* tableElement() const;
</span><span class="cx"> void addChildrenFromSection(RenderTableSection*, unsigned& maxColumnCount);
</span><ins>+ void addTableCellChild(AccessibilityObject*, HashSet<AccessibilityObject*>& appendedRows, unsigned& columnCount);
</ins><span class="cx"> };
</span><span class="cx">
</span><span class="cx"> } // namespace WebCore
</span></span></pre></div>
<a id="trunkSourceWebCoreaccessibilityAccessibilityTableCellcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/accessibility/AccessibilityTableCell.cpp (188202 => 188203)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/accessibility/AccessibilityTableCell.cpp        2015-08-10 00:10:01 UTC (rev 188202)
+++ trunk/Source/WebCore/accessibility/AccessibilityTableCell.cpp        2015-08-10 01:53:10 UTC (rev 188203)
</span><span class="lines">@@ -93,6 +93,24 @@
</span><span class="cx"> AccessibilityObject* parentTable = axObjectCache()->get(downcast<RenderTableCell>(*m_renderer).table());
</span><span class="cx"> if (!is<AccessibilityTable>(parentTable))
</span><span class="cx"> return nullptr;
</span><ins>+
+ // The RenderTableCell's table() object might be anonymous sometimes. We should handle it gracefully
+ // by finding the right table.
+ if (!parentTable->node()) {
+ for (AccessibilityObject* parent = parentObject(); parent; parent = parent->parentObject()) {
+ // If this is a non-anonymous table object, but not an accessibility table, we should stop because
+ // we don't want to choose another ancestor table as this cell's table.
+ if (is<AccessibilityTable>(*parent)) {
+ auto& parentTable = downcast<AccessibilityTable>(*parent);
+ if (parentTable.isExposableThroughAccessibility())
+ return &parentTable;
+ if (parentTable.node())
+ break;
+ }
+ }
+ return nullptr;
+ }
+
</ins><span class="cx"> return downcast<AccessibilityTable>(parentTable);
</span><span class="cx"> }
</span><span class="cx">
</span><span class="lines">@@ -306,8 +324,15 @@
</span><span class="cx"> // Don't add row offsets for bottom sections that are placed in before the body section.
</span><span class="cx"> if (tableSection == footerSection)
</span><span class="cx"> continue;
</span><del>- if (tableSection == section)
</del><ins>+ if (tableSection == section) {
+ // If the table section is anonymous, we should to use the parent row's API to get the rowIndex
+ if (tableSection->isAnonymous()) {
+ AccessibilityObject* parent = parentObjectUnignored();
+ if (is<AccessibilityTableRow>(*parent))
+ rowOffset = downcast<AccessibilityTableRow>(*parent).rowIndex();
+ }
</ins><span class="cx"> break;
</span><ins>+ }
</ins><span class="cx"> rowOffset += tableSection->numRows();
</span><span class="cx"> }
</span><span class="cx">
</span></span></pre></div>
<a id="trunkSourceWebCoreaccessibilityAccessibilityTableRowcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/accessibility/AccessibilityTableRow.cpp (188202 => 188203)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/accessibility/AccessibilityTableRow.cpp        2015-08-10 00:10:01 UTC (rev 188202)
+++ trunk/Source/WebCore/accessibility/AccessibilityTableRow.cpp        2015-08-10 01:53:10 UTC (rev 188203)
</span><span class="lines">@@ -98,13 +98,14 @@
</span><span class="cx"> // The parent table might not be the direct ancestor of the row unfortunately. ARIA states that role="grid" should
</span><span class="cx"> // only have "row" elements, but if not, we still should handle it gracefully by finding the right table.
</span><span class="cx"> for (AccessibilityObject* parent = parentObject(); parent; parent = parent->parentObject()) {
</span><del>- // If this is a table object, but not an accessibility table, we should stop because we don't want to
</del><ins>+ // If this is a non-anonymous table object, but not an accessibility table, we should stop because we don't want to
</ins><span class="cx"> // choose another ancestor table as this row's table.
</span><span class="cx"> if (is<AccessibilityTable>(*parent)) {
</span><span class="cx"> auto& parentTable = downcast<AccessibilityTable>(*parent);
</span><span class="cx"> if (parentTable.isExposableThroughAccessibility())
</span><span class="cx"> return &parentTable;
</span><del>- break;
</del><ins>+ if (parentTable.node())
+ break;
</ins><span class="cx"> }
</span><span class="cx"> }
</span><span class="cx">
</span></span></pre></div>
<a id="trunkSourceWebCoreaccessibilitymacWebAccessibilityObjectWrapperMacmm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/accessibility/mac/WebAccessibilityObjectWrapperMac.mm (188202 => 188203)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/accessibility/mac/WebAccessibilityObjectWrapperMac.mm        2015-08-10 00:10:01 UTC (rev 188202)
+++ trunk/Source/WebCore/accessibility/mac/WebAccessibilityObjectWrapperMac.mm        2015-08-10 01:53:10 UTC (rev 188203)
</span><span class="lines">@@ -1918,7 +1918,7 @@
</span><span class="cx"> { RulerMarkerRole, NSAccessibilityRulerMarkerRole },
</span><span class="cx"> { LinkRole, NSAccessibilityLinkRole },
</span><span class="cx"> { DisclosureTriangleRole, NSAccessibilityDisclosureTriangleRole },
</span><del>- { GridRole, NSAccessibilityGridRole },
</del><ins>+ { GridRole, NSAccessibilityTableRole },
</ins><span class="cx"> { WebCoreLinkRole, NSAccessibilityLinkRole },
</span><span class="cx"> { ImageMapLinkRole, NSAccessibilityLinkRole },
</span><span class="cx"> { ImageMapRole, @"AXImageMap" },
</span></span></pre>
</div>
</div>
</body>
</html>