Commit 112c7d58 authored by Aaron Leventhal's avatar Aaron Leventhal Committed by Commit Bot

Table with role presentation should expose cells as generic containers

When screen readers traverse a <table role="presentation">, they need
generic container objects in place of the cells, to help them understand
and present formatted content. Specifically, this helps present the text
without jamming it together, as well as providing line breaks.

Bug: 787664
Cq-Include-Trybots: master.tryserver.chromium.linux:closure_compilation
Change-Id: I53b691f0ccae3f4090ca0f8ecfcbeb622bd3dfeb
Reviewed-on: https://chromium-review.googlesource.com/887599
Commit-Queue: Aaron Leventhal <aleventhal@chromium.org>
Reviewed-by: default avatarDominic Mazzoni <dmazzoni@chromium.org>
Cr-Commit-Position: refs/heads/master@{#533202}
parent 8c57f37d
...@@ -1673,6 +1673,11 @@ IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityTableLayout) { ...@@ -1673,6 +1673,11 @@ IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityTableLayout) {
RunHtmlTest(FILE_PATH_LITERAL("table-layout.html")); RunHtmlTest(FILE_PATH_LITERAL("table-layout.html"));
} }
IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest,
AccessibilityTablePresentation) {
RunHtmlTest(FILE_PATH_LITERAL("table-presentation.html"));
}
IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest,
AccessibilityTableThColHeader) { AccessibilityTableThColHeader) {
RunHtmlTest(FILE_PATH_LITERAL("table-th-colheader.html")); RunHtmlTest(FILE_PATH_LITERAL("table-th-colheader.html"));
......
...@@ -164,5 +164,6 @@ rootWebArea ...@@ -164,5 +164,6 @@ rootWebArea
++++++++++inlineTextBox name='B' ++++++++++inlineTextBox name='B'
++++column ++++column
++++tableHeaderContainer ++++tableHeaderContainer
++staticText name='Alphabet' ++genericContainer
++++inlineTextBox name='Alphabet' ++++staticText name='Alphabet'
++++++inlineTextBox name='Alphabet'
\ No newline at end of file
...@@ -131,4 +131,5 @@ AXWebArea ...@@ -131,4 +131,5 @@ AXWebArea
++++++++AXStaticText AXValue='B' ++++++++AXStaticText AXValue='B'
++++AXColumn ++++AXColumn
++++AXGroup ++++AXGroup
++AXStaticText AXValue='Alphabet' ++AXGroup
++++AXStaticText AXValue='Alphabet'
\ No newline at end of file
...@@ -131,4 +131,5 @@ ROLE_SYSTEM_DOCUMENT READONLY FOCUSABLE ...@@ -131,4 +131,5 @@ ROLE_SYSTEM_DOCUMENT READONLY FOCUSABLE
++++++++ROLE_SYSTEM_STATICTEXT name='B' ++++++++ROLE_SYSTEM_STATICTEXT name='B'
++++ROLE_SYSTEM_COLUMN ++++ROLE_SYSTEM_COLUMN
++++IA2_ROLE_SECTION ++++IA2_ROLE_SECTION
++ROLE_SYSTEM_STATICTEXT name='Alphabet' ++IA2_ROLE_SECTION
++++ROLE_SYSTEM_STATICTEXT name='Alphabet'
\ No newline at end of file
rootWebArea name='Table with role=presentation'
++genericContainer
++++staticText name='1'
++++++inlineTextBox name='1'
++genericContainer
++++staticText name='2'
++++++inlineTextBox name='2'
++genericContainer
++++staticText name='4'
++++++inlineTextBox name='4'
++genericContainer
++++staticText name='5'
++++++inlineTextBox name='5'
\ No newline at end of file
AXWebArea AXTitle='Table with role=presentation'
++AXGroup
++++AXStaticText AXValue='1'
++AXGroup
++++AXStaticText AXValue='2'
++AXGroup
++++AXStaticText AXValue='4'
++AXGroup
++++AXStaticText AXValue='5'
\ No newline at end of file
ROLE_SYSTEM_DOCUMENT name='Table with role=presentation' READONLY FOCUSABLE
++IA2_ROLE_SECTION
++++ROLE_SYSTEM_STATICTEXT name='1'
++IA2_ROLE_SECTION
++++ROLE_SYSTEM_STATICTEXT name='2'
++IA2_ROLE_SECTION
++++ROLE_SYSTEM_STATICTEXT name='4'
++IA2_ROLE_SECTION
++++ROLE_SYSTEM_STATICTEXT name='5'
\ No newline at end of file
<!--
@MAC-ALLOW:AXIndex=*
@MAC-ALLOW:AXColumnIndexRange=*
@MAC-ALLOW:AXRowIndexRange=*
-->
<!DOCTYPE html>
<html>
<head>
<title>Table with role=presentation</title>
</head>
<body>
<table role="presentation">
<tr>
<td>1</td><td>2</td>
</tr>
<tr>
<td>4</td><td>5</td>
</tr>
</table>
</body>
</html>
...@@ -47,12 +47,15 @@ AXRole: AXWebArea ...@@ -47,12 +47,15 @@ AXRole: AXWebArea
AXRole: AXGenericContainer AXRole: AXGenericContainer
AXRole: AXStaticText "These two tables have static text roles because they have presentation roles." AXRole: AXStaticText "These two tables have static text roles because they have presentation roles."
AXRole: AXInlineTextBox "These two tables have static text roles because they have presentation roles." AXRole: AXInlineTextBox "These two tables have static text roles because they have presentation roles."
AXRole: AXStaticText "Presentation th" AXRole: AXGenericContainer
AXRole: AXInlineTextBox "Presentation th" AXRole: AXStaticText "Presentation th"
AXRole: AXStaticText "Presentation th" AXRole: AXInlineTextBox "Presentation th"
AXRole: AXInlineTextBox "Presentation th" AXRole: AXGenericContainer
AXRole: AXStaticText "Presentation th" AXRole: AXStaticText "Presentation th"
AXRole: AXInlineTextBox "Presentation th" AXRole: AXInlineTextBox "Presentation th"
AXRole: AXGenericContainer
AXRole: AXStaticText "Presentation th"
AXRole: AXInlineTextBox "Presentation th"
AXRole: AXGenericContainer AXRole: AXGenericContainer
AXRole: AXStaticText "The "Presentation th" has a static text role because it has a presentation role." AXRole: AXStaticText "The "Presentation th" has a static text role because it has a presentation role."
AXRole: AXInlineTextBox "The "Presentation th" has a static text role because it has a presentation role." AXRole: AXInlineTextBox "The "Presentation th" has a static text role because it has a presentation role."
...@@ -68,8 +71,9 @@ AXRole: AXWebArea ...@@ -68,8 +71,9 @@ AXRole: AXWebArea
AXRole: AXGenericContainer AXRole: AXGenericContainer
AXRole: AXStaticText "Explicit th" AXRole: AXStaticText "Explicit th"
AXRole: AXInlineTextBox "Explicit th" AXRole: AXInlineTextBox "Explicit th"
AXRole: AXStaticText "Implicit td" AXRole: AXGenericContainer
AXRole: AXInlineTextBox "Implicit td" AXRole: AXStaticText "Implicit td"
AXRole: AXInlineTextBox "Implicit td"
AXRole: AXGenericContainer AXRole: AXGenericContainer
AXRole: AXStaticText "The menu items except button have a static text role because it has a presentation role and is disabled." AXRole: AXStaticText "The menu items except button have a static text role because it has a presentation role and is disabled."
AXRole: AXInlineTextBox "The menu items except button have a static text role because it has a presentation role and is disabled." AXRole: AXInlineTextBox "The menu items except button have a static text role because it has a presentation role and is disabled."
......
...@@ -46,7 +46,7 @@ test(function(t) { ...@@ -46,7 +46,7 @@ test(function(t) {
test(function(t) { test(function(t) {
assert_equals(axElementById('table'), undefined); assert_equals(axElementById('table'), undefined);
assert_equals(axElementById('tr1'), undefined); assert_equals(axElementById('tr1'), undefined);
assert_equals(axElementById('td1'), undefined); assert_equals(axElementById('td1').role, "AXRole: AXGenericContainer");
// Change role="presentation" // Change role="presentation"
document.getElementById('table1').removeAttribute('role'); document.getElementById('table1').removeAttribute('role');
...@@ -65,7 +65,7 @@ test(function(t) { ...@@ -65,7 +65,7 @@ test(function(t) {
assert_equals(axElementById('table'), undefined); assert_equals(axElementById('table'), undefined);
assert_equals(axElementById('tr1'), undefined); assert_equals(axElementById('tr1'), undefined);
assert_equals(axElementById('td1'), undefined); assert_equals(axElementById('td1').role, "AXRole: AXGenericContainer");
}, "Role presentation toggled on table."); }, "Role presentation toggled on table.");
test(function(t) { test(function(t) {
......
...@@ -15,12 +15,16 @@ ...@@ -15,12 +15,16 @@
<script> <script>
test(() => { test(() => {
var axContainer = accessibilityController.accessibleElementById('container'); var axTableContainer = accessibilityController.accessibleElementById('container');
assert_equals(axContainer.childrenCount, 4); assert_equals(axTableContainer.childrenCount, 4);
var axText1 = axContainer.childAtIndex(0); var axTextContainer1 = axTableContainer.childAtIndex(0);
assert_equals(axTextContainer1.role, "AXRole: AXGenericContainer");
var axText1 = axTextContainer1.childAtIndex(0);
assert_equals(axText1.role, "AXRole: AXStaticText"); assert_equals(axText1.role, "AXRole: AXStaticText");
assert_equals(axText1.name, "A"); assert_equals(axText1.name, "A");
var axText2 = axContainer.childAtIndex(1); var axTextContainer2 = axTableContainer.childAtIndex(1);
assert_equals(axTextContainer2.role, "AXRole: AXGenericContainer");
var axText2 = axTextContainer2.childAtIndex(0);
assert_equals(axText2.role, "AXRole: AXStaticText"); assert_equals(axText2.role, "AXRole: AXStaticText");
assert_equals(axText2.name, "B"); assert_equals(axText2.name, "B");
}, "ARIA presentation role on table element has no rows or cells."); }, "ARIA presentation role on table element has no rows or cells.");
......
...@@ -183,41 +183,6 @@ static bool IsListElement(Node* node) { ...@@ -183,41 +183,6 @@ static bool IsListElement(Node* node) {
IsHTMLDListElement(*node); IsHTMLDListElement(*node);
} }
static bool IsPresentationalInTable(AXObject* parent,
HTMLElement* current_element) {
if (!current_element)
return false;
Node* parent_node = parent->GetNode();
if (!parent_node || !parent_node->IsHTMLElement())
return false;
// AXTable determines the role as checking isTableXXX.
// If Table has explicit role including presentation, AXTable doesn't assign
// implicit Role to a whole Table. That's why we should check it based on
// node.
// Normal Table Tree is that
// cell(its role)-> tr(tr role)-> tfoot, tbody, thead(ignored role) ->
// table(table role).
// If table has presentation role, it will be like
// cell(group)-> tr(unknown) -> tfoot, tbody, thead(ignored) ->
// table(presentation).
if (IsHTMLTableCellElement(*current_element) &&
IsHTMLTableRowElement(*parent_node))
return parent->HasInheritedPresentationalRole();
if (IsHTMLTableRowElement(*current_element) &&
IsHTMLTableSectionElement(ToHTMLElement(*parent_node))) {
// Because TableSections have ignored role, presentation should be checked
// with its parent node.
AXObject* table_object = parent->ParentObject();
Node* table_node = table_object ? table_object->GetNode() : nullptr;
return IsHTMLTableElement(table_node) &&
table_object->HasInheritedPresentationalRole();
}
return false;
}
static bool IsRequiredOwnedElement(AXObject* parent, static bool IsRequiredOwnedElement(AXObject* parent,
AccessibilityRole current_role, AccessibilityRole current_role,
HTMLElement* current_element) { HTMLElement* current_element) {
...@@ -270,17 +235,9 @@ const AXObject* AXNodeObject::InheritsPresentationalRoleFrom() const { ...@@ -270,17 +235,9 @@ const AXObject* AXNodeObject::InheritsPresentationalRoleFrom() const {
HTMLElement* element = nullptr; HTMLElement* element = nullptr;
if (GetNode() && GetNode()->IsHTMLElement()) if (GetNode() && GetNode()->IsHTMLElement())
element = ToHTMLElement(GetNode()); element = ToHTMLElement(GetNode());
if (!parent->HasInheritedPresentationalRole()) { if (!parent->HasInheritedPresentationalRole())
if (!GetLayoutObject() || !GetLayoutObject()->IsBoxModelObject()) return nullptr;
return nullptr;
LayoutBoxModelObject* css_box = ToLayoutBoxModelObject(GetLayoutObject());
if (!css_box->IsTableCell() && !css_box->IsTableRow())
return nullptr;
if (!IsPresentationalInTable(parent, element))
return nullptr;
}
// ARIA spec says that when a parent object is presentational and this object // ARIA spec says that when a parent object is presentational and this object
// is a required owned element of that parent, then this object is also // is a required owned element of that parent, then this object is also
// presentational. // presentational.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment