Skip to content

Commit 5ffa3f0

Browse files
committed
AX: aria-controls and aria-expanded keeps elements with hidden attribute visible in Voice Over's Form Control menu
https://bugs.webkit.org/show_bug.cgi?id=300899 rdar://162783041 Reviewed by Joshua Hoffman. Elements with the HTML hidden attribute were incorrectly appearing in VoiceOver's Form Control rotor when they had certain ARIA attributes. This happened because defaultObjectInclusion() only checked for display:none on ancestor elements, not on the element itself. This commit fixes that. Test: accessibility/hidden-elements-with-aria-attributes.html * LayoutTests/accessibility/hidden-elements-with-aria-attributes-expected.txt: Added. * LayoutTests/accessibility/hidden-elements-with-aria-attributes.html: Added. * LayoutTests/platform/ios/TestExpectations: * Source/WebCore/accessibility/AccessibilityObject.cpp: (WebCore::AccessibilityObject::defaultObjectInclusion const): Canonical link: https://commits.webkit.org/305902@main
1 parent 34d4f27 commit 5ffa3f0

File tree

4 files changed

+77
-0
lines changed

4 files changed

+77
-0
lines changed
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
This test ensures that elements with the HTML hidden attribute are not exposed to assistive technologies, even when they have ARIA relationship attributes like aria-controls or aria-expanded.
2+
3+
PASS: visibleWithControls.role.toLowerCase().includes('button') === true
4+
PASS: visibleWithControls.isIgnored === false
5+
PASS: hiddenWithControls === null
6+
PASS: hiddenWithNonexistentControls === null
7+
PASS: hiddenWithExpanded === null
8+
PASS: visibleWithExpanded.role.toLowerCase().includes('button') === true
9+
PASS: visibleWithExpanded.isIgnored === false
10+
PASS: dynamicButton.isIgnored === false
11+
PASS: accessibilityController.accessibleElementById('dynamic-button') === null
12+
13+
PASS successfullyParsed is true
14+
15+
TEST COMPLETE
16+
Visible button with aria-controls Visible button with aria-expanded
17+
Panel content
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head>
4+
<script src="../resources/accessibility-helper.js"></script>
5+
<script src="../resources/js-test.js"></script>
6+
</head>
7+
<body>
8+
9+
<button id="visible-with-controls" aria-controls="panel">Visible button with aria-controls</button>
10+
<button id="hidden-with-controls" hidden aria-controls="panel">Hidden button with aria-controls</button>
11+
<button id="hidden-with-nonexistent-controls" hidden aria-controls="nonexistent">Hidden button with aria-controls referencing nonexistent element</button>
12+
<button id="hidden-with-expanded" hidden aria-expanded="false">Hidden button with aria-expanded</button>
13+
<button id="visible-with-expanded" aria-expanded="false">Visible button with aria-expanded</button>
14+
<button id="dynamic-button" aria-controls="panel">Button that will become hidden</button>
15+
16+
<div id="panel">Panel content</div>
17+
18+
<script>
19+
var output = "This test ensures that elements with the HTML hidden attribute are not exposed to assistive technologies, even when they have ARIA relationship attributes like aria-controls or aria-expanded.\n\n";
20+
21+
if (window.accessibilityController) {
22+
window.jsTestIsAsync = true;
23+
24+
var visibleWithControls = accessibilityController.accessibleElementById("visible-with-controls");
25+
output += expect("visibleWithControls.role.toLowerCase().includes('button')", "true");
26+
output += expect("visibleWithControls.isIgnored", "false");
27+
28+
var hiddenWithControls = accessibilityController.accessibleElementById("hidden-with-controls");
29+
output += expect("hiddenWithControls", "null");
30+
31+
var hiddenWithNonexistentControls = accessibilityController.accessibleElementById("hidden-with-nonexistent-controls");
32+
output += expect("hiddenWithNonexistentControls", "null");
33+
34+
var hiddenWithExpanded = accessibilityController.accessibleElementById("hidden-with-expanded");
35+
output += expect("hiddenWithExpanded", "null");
36+
37+
var visibleWithExpanded = accessibilityController.accessibleElementById("visible-with-expanded");
38+
output += expect("visibleWithExpanded.role.toLowerCase().includes('button')", "true");
39+
output += expect("visibleWithExpanded.isIgnored", "false");
40+
41+
var dynamicButton = accessibilityController.accessibleElementById("dynamic-button");
42+
output += expect("dynamicButton.isIgnored", "false");
43+
44+
document.getElementById("dynamic-button").setAttribute("hidden", "");
45+
setTimeout(async function() {
46+
output += await expectAsync("accessibilityController.accessibleElementById('dynamic-button')", "null");
47+
48+
debug(output);
49+
finishJSTest();
50+
}, 0);
51+
}
52+
</script>
53+
</body>
54+
</html>

LayoutTests/platform/ios/TestExpectations

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2383,6 +2383,7 @@ accessibility/editable-webpage-focused-ui-element.html [ Pass ]
23832383
accessibility/element-haspopup.html [ Pass ]
23842384
accessibility/empty-text-under-element-cached.html [ Pass ]
23852385
accessibility/heading-level.html [ Pass ]
2386+
accessibility/hidden-elements-with-aria-attributes.html [ Pass ]
23862387
accessibility/hidden-label.html [ Pass ]
23872388
accessibility/hidden-slot.html [ Pass ]
23882389
accessibility/html-element-aria-hidden.html [ Pass ]

Source/WebCore/accessibility/AccessibilityObject.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3976,6 +3976,11 @@ AccessibilityObjectInclusion AccessibilityObject::defaultObjectInclusion() const
39763976
}
39773977
}
39783978

3979+
if (CheckedPtr style = this->style()) {
3980+
if (style->display() == DisplayType::None && !isImageMapLink())
3981+
return AccessibilityObjectInclusion::IgnoreObject;
3982+
}
3983+
39793984
bool useParentData = !m_isIgnoredFromParentData.isNull();
39803985
if (useParentData && (m_isIgnoredFromParentData.isAXHidden || m_isIgnoredFromParentData.isPresentationalChildOfAriaRole))
39813986
return AccessibilityObjectInclusion::IgnoreObject;

0 commit comments

Comments
 (0)