Commit 73bf1f34 authored by Victor Fei's avatar Victor Fei Committed by Commit Bot

A11y: Exposed Hierarchial Level for tablist.

This change exposes hierarchical level for tablist in the accessibility
tree. Hierarchical level is determined from `aria-level` or the DOM
structure of the tablist in relation to its parent tablist.

https://www.w3.org/TR/wai-aria-1.1/#tablist
https://www.w3.org/TR/wai-aria-1.1/#aria-level

Change-Id: I1d6aba1bf47b3998a7622a98ec75dae1e41c9452
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1996263
Commit-Queue: Victor Fei <vicfei@microsoft.com>
Reviewed-by: default avatarIan Prest <iapres@microsoft.com>
Reviewed-by: default avatarAaron Leventhal <aleventhal@chromium.org>
Cr-Commit-Position: refs/heads/master@{#738049}
parent 498332e8
......@@ -1040,6 +1040,11 @@ IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest, AccessibilityAriaTabList) {
RunAriaTest(FILE_PATH_LITERAL("aria-tablist.html"));
}
IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest,
AccessibilityAriaTabListAriaLevel) {
RunAriaTest(FILE_PATH_LITERAL("aria-tablist-aria-level.html"));
}
IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest, AccessibilityAriaTabPanel) {
RunAriaTest(FILE_PATH_LITERAL("aria-tabpanel.html"));
}
......
......@@ -871,10 +871,7 @@ void BlinkAXTreeSource::SerializeNode(WebAXObject src,
if (ui::IsHeading(dst->role) && src.HeadingLevel()) {
dst->AddIntAttribute(ax::mojom::IntAttribute::kHierarchicalLevel,
src.HeadingLevel());
} else if ((dst->role == ax::mojom::Role::kTreeItem ||
dst->role == ax::mojom::Role::kComment ||
dst->role == ax::mojom::Role::kListItem ||
dst->role == ax::mojom::Role::kRow) &&
} else if (ui::SupportsHierarchicalLevel(dst->role) &&
src.HierarchicalLevel()) {
dst->AddIntAttribute(ax::mojom::IntAttribute::kHierarchicalLevel,
src.HierarchicalLevel());
......
rootWebArea
++genericContainer ignored
++++tabList horizontal setSize=2
++++tabList horizontal hierarchicalLevel=1 setSize=2
++++++tab name='Tab 1' setSize=2 posInSet=1 selected=false
++++++tab name='Tab 2' setSize=2 posInSet=2 selected=false
ROLE_SYSTEM_DOCUMENT READONLY FOCUSABLE
++ROLE_SYSTEM_PAGETABLIST IA2_STATE_HORIZONTAL xml-roles:tablist
++ROLE_SYSTEM_PAGETABLIST IA2_STATE_HORIZONTAL xml-roles:tablist level:1
++++ROLE_SYSTEM_PAGETAB name='Tab 1' xml-roles:tab
++++ROLE_SYSTEM_PAGETAB name='Tab 2' xml-roles:tab
......@@ -2,11 +2,13 @@
@MAC-ALLOW:AXRole*
@WIN-ALLOW:xml-roles*
@WIN-ALLOW:IA2_STATE_HORIZONTAL
@WIN-ALLOW:level*
@AURALINUX-ALLOW:xml-roles*
@AURALINUX-ALLOW:horizontal
@AURALINUX-ALLOW:vertical
@AURALINUX-ALLOW:posinset*
@AURALINUX-ALLOW:setsize*
@BLINK-ALLOW:hierarchicalLevel*
@BLINK-ALLOW:horizontal
@BLINK-ALLOW:setSize*
@BLINK-ALLOW:posInSet*
......
android.webkit.WebView focusable focused scrollable
++android.widget.TabWidget role_description='tab list'
++++android.view.View role_description='tab' clickable name='Tab 1 of 2, level 1'
++++android.view.View role_description='tab' clickable name='Tab 2 of 2, level 1' item_index=1 row_index=1
++android.widget.TabWidget role_description='tab list'
++++android.view.View role_description='tab' clickable name='Tab 1 of 3, level 2'
++++android.view.View role_description='tab' clickable name='Tab 2 of 3, level 2' item_index=1 row_index=1
++++android.widget.TabWidget role_description='tab list'
++++++android.view.View role_description='tab' clickable name='Tab 1 of 1, level 3'
++++android.view.View role_description='tab' clickable name='Tab 3 of 3, level 2' item_index=2 row_index=2
++android.widget.TabWidget role_description='tab list'
++++android.view.View role_description='tab' clickable name='Tab 1 of 1, level 2'
++android.widget.TabWidget role_description='tab list'
++++android.view.View role_description='tab' clickable name='Tab 1 of 1, level 1'
[document web]
++[page tab list] horizontal level:1 setsize:2
++++[page tab] name='Tab 1 of 2, level 1' selectable posinset:1 setsize:2
++++[page tab] name='Tab 2 of 2, level 1' selectable posinset:2 setsize:2
++[page tab list] horizontal level:2 setsize:3
++++[page tab] name='Tab 1 of 3, level 2' selectable posinset:1 setsize:3
++++[page tab] name='Tab 2 of 3, level 2' selectable posinset:2 setsize:3
++++[page tab list] horizontal level:3 setsize:1
++++++[page tab] name='Tab 1 of 1, level 3' selectable posinset:1 setsize:1
++++[page tab] name='Tab 3 of 3, level 2' selectable posinset:3 setsize:3
++[page tab list] horizontal level:2 setsize:1
++++[page tab] name='Tab 1 of 1, level 2' selectable posinset:1 setsize:1
++[page tab list] horizontal level:1 setsize:1
++++[page tab] name='Tab 1 of 1, level 1' selectable posinset:1 setsize:1
rootWebArea
++genericContainer ignored
++++tabList horizontal hierarchicalLevel=1 setSize=2
++++++tab name='Tab 1 of 2, level 1' setSize=2 posInSet=1 selected=false
++++++tab name='Tab 2 of 2, level 1' setSize=2 posInSet=2 selected=false
++++tabList horizontal hierarchicalLevel=2 setSize=3
++++++tab name='Tab 1 of 3, level 2' setSize=3 posInSet=1 selected=false
++++++tab name='Tab 2 of 3, level 2' setSize=3 posInSet=2 selected=false
++++++tabList horizontal hierarchicalLevel=3 setSize=1
++++++++tab name='Tab 1 of 1, level 3' setSize=1 posInSet=1 selected=false
++++++tab name='Tab 3 of 3, level 2' setSize=3 posInSet=3 selected=false
++++tabList horizontal hierarchicalLevel=2 setSize=1
++++++tab name='Tab 1 of 1, level 2' setSize=1 posInSet=1 selected=false
++++tabList horizontal hierarchicalLevel=1 setSize=1
++++++tab name='Tab 1 of 1, level 1' setSize=1 posInSet=1 selected=false
AXWebArea AXRoleDescription='HTML content'
++AXTabGroup AXRoleDescription='tab group'
++++AXRadioButton AXRoleDescription='tab' AXTitle='Tab 1 of 2, level 1' AXValue='0'
++++AXRadioButton AXRoleDescription='tab' AXTitle='Tab 2 of 2, level 1' AXValue='0'
++AXTabGroup AXRoleDescription='tab group'
++++AXRadioButton AXRoleDescription='tab' AXTitle='Tab 1 of 3, level 2' AXValue='0'
++++AXRadioButton AXRoleDescription='tab' AXTitle='Tab 2 of 3, level 2' AXValue='0'
++++AXTabGroup AXRoleDescription='tab group'
++++++AXRadioButton AXRoleDescription='tab' AXTitle='Tab 1 of 1, level 3' AXValue='0'
++++AXRadioButton AXRoleDescription='tab' AXTitle='Tab 3 of 3, level 2' AXValue='0'
++AXTabGroup AXRoleDescription='tab group'
++++AXRadioButton AXRoleDescription='tab' AXTitle='Tab 1 of 1, level 2' AXValue='0'
++AXTabGroup AXRoleDescription='tab group'
++++AXRadioButton AXRoleDescription='tab' AXTitle='Tab 1 of 1, level 1' AXValue='0'
ROLE_SYSTEM_DOCUMENT READONLY FOCUSABLE
++ROLE_SYSTEM_PAGETABLIST IA2_STATE_HORIZONTAL xml-roles:tablist level:1 setsize:2
++++ROLE_SYSTEM_PAGETAB name='Tab 1 of 2, level 1' xml-roles:tab setsize:2 posinset:1
++++ROLE_SYSTEM_PAGETAB name='Tab 2 of 2, level 1' xml-roles:tab setsize:2 posinset:2
++ROLE_SYSTEM_PAGETABLIST IA2_STATE_HORIZONTAL xml-roles:tablist level:2 setsize:3
++++ROLE_SYSTEM_PAGETAB name='Tab 1 of 3, level 2' xml-roles:tab setsize:3 posinset:1
++++ROLE_SYSTEM_PAGETAB name='Tab 2 of 3, level 2' xml-roles:tab setsize:3 posinset:2
++++ROLE_SYSTEM_PAGETABLIST IA2_STATE_HORIZONTAL xml-roles:tablist level:3 setsize:1
++++++ROLE_SYSTEM_PAGETAB name='Tab 1 of 1, level 3' xml-roles:tab setsize:1 posinset:1
++++ROLE_SYSTEM_PAGETAB name='Tab 3 of 3, level 2' xml-roles:tab setsize:3 posinset:3
++ROLE_SYSTEM_PAGETABLIST IA2_STATE_HORIZONTAL xml-roles:tablist level:2 setsize:1
++++ROLE_SYSTEM_PAGETAB name='Tab 1 of 1, level 2' xml-roles:tab setsize:1 posinset:1
++ROLE_SYSTEM_PAGETABLIST IA2_STATE_HORIZONTAL xml-roles:tablist level:1 setsize:1
++++ROLE_SYSTEM_PAGETAB name='Tab 1 of 1, level 1' xml-roles:tab setsize:1 posinset:1
<!--
@MAC-ALLOW:AXRole*
@WIN-ALLOW:xml-roles*
@WIN-ALLOW:level*
@WIN-ALLOW:setsize*
@WIN-ALLOW:posinset*
@AURALINUX-ALLOW:level:*
@AURALINUX-ALLOW:posinset*
@AURALINUX-ALLOW:setsize*
@BLINK-ALLOW:hierarchicalLevel*
@BLINK-ALLOW:posInSet*
@BLINK-ALLOW:setSize*
-->
<!DOCTYPE html>
<html>
<body>
<div role="tablist" aria-level="1">
<div role="tab">Tab 1 of 2, level 1</div>
<div role="tab">Tab 2 of 2, level 1</div>
</div>
<div role="tablist" aria-level="2">
<div role="tab">Tab 1 of 3, level 2</div>
<div role="tab">Tab 2 of 3, level 2</div>
<div role="tablist" aria-level="3">
<div role="tab">Tab 1 of 1, level 3</div>
</div>
<div role="tab">Tab 3 of 3, level 2</div>
</div>
<div role="tablist" aria-level="2">
<div role="tab">Tab 1 of 1, level 2</div>
</div>
<div role="tablist" aria-level="1">
<div role="tab">Tab 1 of 1, level 1</div>
</div>
</body>
</html>
android.webkit.WebView focusable focused scrollable
++android.widget.TabWidget role_description='tab list'
++++android.view.View role_description='tab' clickable name='Tab 1'
++++android.view.View role_description='tab' clickable name='Tab 2' item_index=1 row_index=1
++++android.view.View role_description='tab' clickable name='Tab 1, level 1'
++++android.view.View role_description='tab' clickable name='Tab 2, level 1' item_index=1 row_index=1
++++android.widget.TabWidget role_description='tab list'
++++++android.view.View role_description='tab' clickable name='Tab 1, level 2'
++++++android.view.View role_description='tab' clickable name='Tab 2, level 2' item_index=1 row_index=1
++++++++android.widget.TextView name='Tab 2, level 2'
++++++++android.widget.TabWidget role_description='tab list'
++++++++++android.view.View role_description='tab' clickable name='Tab 1, level 3'
++++android.view.View role_description='tab' clickable name='Tab 3, level 1' item_index=2 row_index=2
[document web]
++[page tab list] horizontal setsize:2
++++[page tab] name='Tab 1' selectable posinset:1 setsize:2
++++[page tab] name='Tab 2' selectable posinset:2 setsize:2
++[page tab list] horizontal setsize:3
++++[page tab] name='Tab 1, level 1' selectable posinset:1 setsize:3
++++[page tab] name='Tab 2, level 1' selectable posinset:2 setsize:3
++++[page tab list] horizontal setsize:2
++++++[page tab] name='Tab 1, level 2' selectable posinset:1 setsize:2
++++++[page tab] name='Tab 2, level 2' selectable posinset:2 setsize:2
++++++++[static] name='Tab 2, level 2'
++++++++[page tab list] horizontal setsize:1
++++++++++[page tab] name='Tab 1, level 3' selectable posinset:1 setsize:1
++++[page tab] name='Tab 3, level 1' selectable posinset:3 setsize:3
rootWebArea
++genericContainer ignored
++++tabList horizontal
++++++tab name='Tab 1' selected=false
++++++tab name='Tab 2' selected=false
++++tabList horizontal hierarchicalLevel=1 setSize=3
++++++tab name='Tab 1, level 1' setSize=3 posInSet=1 selected=false
++++++tab name='Tab 2, level 1' setSize=3 posInSet=2 selected=false
++++++tabList horizontal hierarchicalLevel=2 setSize=2
++++++++tab name='Tab 1, level 2' setSize=2 posInSet=1 selected=false
++++++++tab name='Tab 2, level 2' setSize=2 posInSet=2 selected=false
++++++++++staticText name='Tab 2, level 2'
++++++++++++inlineTextBox name='Tab 2, level 2'
++++++++++tabList horizontal hierarchicalLevel=3 setSize=1
++++++++++++tab name='Tab 1, level 3' setSize=1 posInSet=1 selected=false
++++++tab name='Tab 3, level 1' setSize=3 posInSet=3 selected=false
<-- End-of-file -->
AXWebArea AXRoleDescription='HTML content'
++AXTabGroup AXRoleDescription='tab group'
++++AXRadioButton AXRoleDescription='tab' AXTitle='Tab 1' AXValue='0'
++++AXRadioButton AXRoleDescription='tab' AXTitle='Tab 2' AXValue='0'
++++AXRadioButton AXRoleDescription='tab' AXTitle='Tab 1, level 1' AXValue='0'
++++AXRadioButton AXRoleDescription='tab' AXTitle='Tab 2, level 1' AXValue='0'
++++AXTabGroup AXRoleDescription='tab group'
++++++AXRadioButton AXRoleDescription='tab' AXTitle='Tab 1, level 2' AXValue='0'
++++++AXRadioButton AXRoleDescription='tab' AXTitle='Tab 2, level 2' AXValue='0'
++++++++AXStaticText AXRoleDescription='text' AXValue='Tab 2, level 2'
++++++++AXTabGroup AXRoleDescription='tab group'
++++++++++AXRadioButton AXRoleDescription='tab' AXTitle='Tab 1, level 3' AXValue='0'
++++AXRadioButton AXRoleDescription='tab' AXTitle='Tab 3, level 1' AXValue='0'
ROLE_SYSTEM_DOCUMENT READONLY FOCUSABLE
++ROLE_SYSTEM_PAGETABLIST IA2_STATE_HORIZONTAL xml-roles:tablist
++++ROLE_SYSTEM_PAGETAB name='Tab 1' xml-roles:tab
++++ROLE_SYSTEM_PAGETAB name='Tab 2' xml-roles:tab
++ROLE_SYSTEM_PAGETABLIST IA2_STATE_HORIZONTAL xml-roles:tablist level:1
++++ROLE_SYSTEM_PAGETAB name='Tab 1, level 1' xml-roles:tab
++++ROLE_SYSTEM_PAGETAB name='Tab 2, level 1' xml-roles:tab
++++ROLE_SYSTEM_PAGETABLIST IA2_STATE_HORIZONTAL xml-roles:tablist level:2
++++++ROLE_SYSTEM_PAGETAB name='Tab 1, level 2' xml-roles:tab
++++++ROLE_SYSTEM_PAGETAB name='Tab 2, level 2' xml-roles:tab
++++++++ROLE_SYSTEM_STATICTEXT name='Tab 2, level 2'
++++++++ROLE_SYSTEM_PAGETABLIST IA2_STATE_HORIZONTAL xml-roles:tablist level:3
++++++++++ROLE_SYSTEM_PAGETAB name='Tab 1, level 3' xml-roles:tab
++++ROLE_SYSTEM_PAGETAB name='Tab 3, level 1' xml-roles:tab
<-- End-of-file -->
......@@ -2,18 +2,37 @@
@MAC-ALLOW:AXRole*
@WIN-ALLOW:xml-roles*
@WIN-ALLOW:IA2_STATE_HORIZONTAL
@WIN-ALLOW:level*
@BLINK-ALLOW:hierarchicalLevel*
@BLINK-ALLOW:horizontal
@AURALINUX-ALLOW:horizontal
@AURALINUX-ALLOW:vertical
@AURALINUX-ALLOW:posinset*
@AURALINUX-ALLOW:setsize*
@BLINK-ALLOW:setSize*
@BLINK-ALLOW:posInSet*
-->
<!DOCTYPE html>
<html>
<body>
<div role="tablist">
<div role="tab" id="tab1">Tab 1</div>
<div role="tab" id="tab2">Tab 2</div>
<div role="tab">Tab 1, level 1</div>
<div role="tab">Tab 2, level 1</div>
<ul role="tablist">
<li role="tab">Tab 1, level 2</li>
<li role="tab">Tab 2, level 2
<ul role="tablist">
<li role="tab">Tab 1, level 3</li>
</ul>
</li>
</ul>
<div role="tab">Tab 3, level 1</div>
</div>
<style>
li {
list-style-type: none;
}
</style>
</body>
</html>
EVENT_OBJECT_STATECHANGE on <div> role=ROLE_SYSTEM_LIST MULTISELECTABLE,EXTSELECTABLE IA2_STATE_VERTICAL
EVENT_OBJECT_STATECHANGE on <div> role=ROLE_SYSTEM_OUTLINE
EVENT_OBJECT_STATECHANGE on <div> role=ROLE_SYSTEM_OUTLINE IA2_STATE_VERTICAL
EVENT_OBJECT_STATECHANGE on <div> role=ROLE_SYSTEM_PAGETABLIST MULTISELECTABLE,EXTSELECTABLE IA2_STATE_HORIZONTAL
EVENT_OBJECT_STATECHANGE on <div> role=ROLE_SYSTEM_PAGETABLIST MULTISELECTABLE,EXTSELECTABLE IA2_STATE_HORIZONTAL level=1
EVENT_OBJECT_STATECHANGE on <div> role=ROLE_SYSTEM_TABLE MULTISELECTABLE,EXTSELECTABLE
......@@ -1506,44 +1506,47 @@ unsigned AXNodeObject::HierarchicalLevel() const {
return level;
}
// Only tree item and list item will calculate its level through the DOM
// currently.
if (RoleValue() == ax::mojom::Role::kTreeItem) {
// Hierarchy leveling starts at 1, to match the aria-level spec.
// We measure tree hierarchy by the number of groups that the item is
// within.
level = 1;
// Helper lambda for calculating hierarchical levels by counting ancestor
// nodes that match a target role.
auto accumulateLevel = [&](int initial_level, ax::mojom::Role target_role) {
int level = initial_level;
for (AXObject* parent = ParentObject(); parent;
parent = parent->ParentObject()) {
ax::mojom::Role parent_role = parent->RoleValue();
if (parent_role == ax::mojom::Role::kGroup)
if (parent->RoleValue() == target_role)
level++;
else if (parent_role == ax::mojom::Role::kTree)
break;
}
return level;
} else if (RoleValue() == ax::mojom::Role::kListItem) {
level = 0;
for (AXObject* parent = ParentObject(); parent;
parent = parent->ParentObject()) {
ax::mojom::Role parent_role = parent->RoleValue();
if (parent_role == ax::mojom::Role::kList)
level++;
}
};
// When level count is 0 due to this list item not having an ancestor of
// Role::kList, not nested in list groups, this list item has a level of 1.
return level == 0 ? 1 : level;
} else if (RoleValue() == ax::mojom::Role::kComment) {
// Comment: level is based on counting comment ancestors until the root.
level = 1;
for (AXObject* parent = ParentObject(); parent;
parent = parent->ParentObject()) {
ax::mojom::Role parent_role = parent->RoleValue();
if (parent_role == ax::mojom::Role::kComment)
level++;
switch (RoleValue()) {
case ax::mojom::Role::kComment:
// Comment: level is based on counting comment ancestors until the root.
return accumulateLevel(1, ax::mojom::Role::kComment);
case ax::mojom::Role::kListItem:
level = accumulateLevel(0, ax::mojom::Role::kList);
// When level count is 0 due to this list item not having an ancestor of
// Role::kList, not nested in list groups, this list item has a level
// of 1.
return level == 0 ? 1 : level;
case ax::mojom::Role::kTabList:
return accumulateLevel(1, ax::mojom::Role::kTabList);
case ax::mojom::Role::kTreeItem: {
// Hierarchy leveling starts at 1, to match the aria-level spec.
// We measure tree hierarchy by the number of groups that the item is
// within.
level = 1;
for (AXObject* parent = ParentObject(); parent;
parent = parent->ParentObject()) {
ax::mojom::Role parent_role = parent->RoleValue();
if (parent_role == ax::mojom::Role::kGroup)
level++;
else if (parent_role == ax::mojom::Role::kTree)
break;
}
return level;
}
return level;
default:
return 0;
}
return 0;
......
......@@ -617,6 +617,19 @@ bool SupportsExpandCollapse(const ax::mojom::Role role) {
}
}
bool SupportsHierarchicalLevel(const ax::mojom::Role role) {
switch (role) {
case ax::mojom::Role::kComment:
case ax::mojom::Role::kListItem:
case ax::mojom::Role::kRow:
case ax::mojom::Role::kTabList:
case ax::mojom::Role::kTreeItem:
return true;
default:
return false;
}
}
bool SupportsOrientation(const ax::mojom::Role role) {
switch (role) {
case ax::mojom::Role::kComboBoxGrouping:
......
......@@ -133,6 +133,9 @@ AX_EXPORT bool IsTextOrLineBreak(ax::mojom::Role role);
// Returns true if the role supports expand/collapse.
AX_EXPORT bool SupportsExpandCollapse(const ax::mojom::Role role);
// Returns true if the role supports hierarchical level.
AX_EXPORT bool SupportsHierarchicalLevel(const ax::mojom::Role role);
// Returns true if the provided role can have an orientation.
AX_EXPORT bool SupportsOrientation(const ax::mojom::Role role);
......
......@@ -12,6 +12,34 @@
namespace ui {
TEST(AXRolePropertiesTest, TestSupportsHierarchicalLevel) {
// Test for iterating through all roles and validate if a role supports
// hierarchical level.
std::unordered_set<ax::mojom::Role>
roles_expected_supports_hierarchical_level = {
ax::mojom::Role::kComment, ax::mojom::Role::kListItem,
ax::mojom::Role::kRow, ax::mojom::Role::kTabList,
ax::mojom::Role::kTreeItem};
for (int role_idx = static_cast<int>(ax::mojom::Role::kMinValue);
role_idx <= static_cast<int>(ax::mojom::Role::kMaxValue); role_idx++) {
ax::mojom::Role role = static_cast<ax::mojom::Role>(role_idx);
bool supports_hierarchical_level = SupportsHierarchicalLevel(role);
SCOPED_TRACE(testing::Message() << "ax::mojom::Role=" << ToString(role)
<< ", Actual: supportsHierarchicalLevel="
<< supports_hierarchical_level
<< ", Expected: supportsHierarchicalLevel="
<< !supports_hierarchical_level);
if (roles_expected_supports_hierarchical_level.find(role) !=
roles_expected_supports_hierarchical_level.end())
EXPECT_TRUE(supports_hierarchical_level);
else
EXPECT_FALSE(supports_hierarchical_level);
}
}
TEST(AXRolePropertiesTest, TestSupportsToggle) {
// Test for iterating through all roles and validate if a role supports
// toggle.
......@@ -36,5 +64,4 @@ TEST(AXRolePropertiesTest, TestSupportsToggle) {
EXPECT_FALSE(supports_toggle);
}
}
} // namespace ui
......@@ -1914,7 +1914,15 @@ void AXTree::RecursivelyPopulateOrderedSetItems(
// If the hierarchical level of |child| and the level of |original_node|
// differ, we do not add child to |items_to_be_populated| and we do not
// recurse into |child| and populate its order set item descendants.
if (child_level != original_node_min_level) {
// Additionally, as an exception, we always add tab items to the set,
// because according to WAI-ARIA spec, tab does not support hierarchical
// level, while tab's set container tablist supports hierarchical level.
// Due to this, we always assume sibling tabs are always on the same
// level, and always add tab child item to |items_to_be_populated|.
// https://www.w3.org/WAI/PF/aria/roles#tab
// https://www.w3.org/WAI/PF/aria/roles#tablist
if (child_level != original_node_min_level &&
child->data().role != ax::mojom::Role::kTab) {
if (child_level < original_node_min_level &&
original_node.GetUnignoredParent() == child->GetUnignoredParent()) {
// For a flattened structure, where |original_node| and |child| share
......
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