diff --git a/LayoutTests/accessibility/body-element-aria-hidden-expected.txt b/LayoutTests/accessibility/body-element-aria-hidden-expected.txt new file mode 100644 index 0000000000000..bb6433dc4b948 --- /dev/null +++ b/LayoutTests/accessibility/body-element-aria-hidden-expected.txt @@ -0,0 +1,8 @@ +This test ensures that aria-hidden='true' is not respected on the body element. + +PASS: accessibilityController.accessibleElementById('button').role.toLowerCase().includes('button') === true + +PASS successfullyParsed is true + +TEST COMPLETE +Submit diff --git a/LayoutTests/accessibility/body-element-aria-hidden.html b/LayoutTests/accessibility/body-element-aria-hidden.html new file mode 100644 index 0000000000000..c5cfd67d1ae40 --- /dev/null +++ b/LayoutTests/accessibility/body-element-aria-hidden.html @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + diff --git a/LayoutTests/accessibility/html-element-aria-hidden-expected.txt b/LayoutTests/accessibility/html-element-aria-hidden-expected.txt new file mode 100644 index 0000000000000..b5a6333b8cbde --- /dev/null +++ b/LayoutTests/accessibility/html-element-aria-hidden-expected.txt @@ -0,0 +1,8 @@ +This test ensures that aria-hidden='true' is not respected on the html element. + +PASS: accessibilityController.accessibleElementById('button').role.toLowerCase().includes('button') === true + +PASS successfullyParsed is true + +TEST COMPLETE +Submit diff --git a/LayoutTests/accessibility/html-element-aria-hidden.html b/LayoutTests/accessibility/html-element-aria-hidden.html new file mode 100644 index 0000000000000..f94bbb86aaae5 --- /dev/null +++ b/LayoutTests/accessibility/html-element-aria-hidden.html @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + diff --git a/LayoutTests/platform/ios/TestExpectations b/LayoutTests/platform/ios/TestExpectations index f4d56e2e15c25..57aca359716c8 100644 --- a/LayoutTests/platform/ios/TestExpectations +++ b/LayoutTests/platform/ios/TestExpectations @@ -2300,6 +2300,7 @@ accessibility/aria-braillelabel.html [ Pass ] accessibility/aria-brailleroledescription.html [ Pass ] accessibility/aria-checked-mixed-value.html [ Pass ] accessibility/aria-describedby-on-input.html [ Pass ] +accessibility/body-element-aria-hidden.html [ Pass ] accessibility/display-contents/aria-hidden.html [ Pass ] accessibility/aria-multiline.html [ Pass ] accessibility/aria-readonly-updates-after-dynamic-change.html [ Pass ] @@ -2325,6 +2326,7 @@ accessibility/empty-text-under-element-cached.html [ Pass ] accessibility/heading-level.html [ Pass ] accessibility/hidden-label.html [ Pass ] accessibility/hidden-slot.html [ Pass ] +accessibility/html-element-aria-hidden.html [ Pass ] accessibility/html5-required-attribute.html [ Pass ] accessibility/iframe-tree-update-with-dirty-layout.html [ Pass ] accessibility/iframe-with-role.html [ Pass ] diff --git a/Source/WebCore/accessibility/AXCoreObject.h b/Source/WebCore/accessibility/AXCoreObject.h index 0f88f8dbbcab9..0a63e482900ba 100644 --- a/Source/WebCore/accessibility/AXCoreObject.h +++ b/Source/WebCore/accessibility/AXCoreObject.h @@ -1272,7 +1272,6 @@ class AXCoreObject : public ThreadSafeRefCountedAndCanMakeThreadSafeWeakPtr simpleRange() const = 0; virtual VisiblePositionRange visiblePositionRange() const = 0; diff --git a/Source/WebCore/accessibility/AccessibilityObject.cpp b/Source/WebCore/accessibility/AccessibilityObject.cpp index 0bce8a69d230b..15c30699caeb0 100644 --- a/Source/WebCore/accessibility/AccessibilityObject.cpp +++ b/Source/WebCore/accessibility/AccessibilityObject.cpp @@ -3987,12 +3987,19 @@ bool AccessibilityObject::isARIAHidden() const return false; auto* node = this->node(); + auto* element = dynamicDowncast(node); + AtomString tag = element ? element->localName() : nullAtom(); + // https://github.com/w3c/aria/pull/1880 + // To prevent authors from hiding all content from assistive technology users, do not respect + // aria-hidden on html, body, or document-root svg elements. + if (tag == bodyTag || tag == htmlTag || (tag == SVGNames::svgTag && !element->parentNode())) + return false; + if (auto* assignedSlot = node ? node->assignedSlot() : nullptr) { if (equalLettersIgnoringASCIICase(assignedSlot->attributeWithDefaultARIA(aria_hiddenAttr), "true"_s)) return true; } - - return equalLettersIgnoringASCIICase(getAttribute(aria_hiddenAttr), "true"_s); + return element && equalLettersIgnoringASCIICase(element->attributeWithDefaultARIA(aria_hiddenAttr), "true"_s); } // ARIA component of hidden definition. @@ -4174,10 +4181,8 @@ AccessibilityObject* AccessibilityObject::radioGroupAncestor() const AtomString AccessibilityObject::tagName() const { - if (Element* element = this->element()) - return element->localName(); - - return nullAtom(); + auto* element = this->element(); + return element ? element->localName() : nullAtom(); } bool AccessibilityObject::isStyleFormatGroup() const @@ -4441,7 +4446,7 @@ void AccessibilityObject::setIsIgnoredFromParentDataForChild(AccessibilityObject AccessibilityIsIgnoredFromParentData result = AccessibilityIsIgnoredFromParentData(this); if (!m_isIgnoredFromParentData.isNull()) { - result.isAXHidden = (m_isIgnoredFromParentData.isAXHidden || equalLettersIgnoringASCIICase(child->getAttribute(aria_hiddenAttr), "true"_s)) && !child->isFocused(); + result.isAXHidden = (m_isIgnoredFromParentData.isAXHidden || child->isARIAHidden()); result.isPresentationalChildOfAriaRole = m_isIgnoredFromParentData.isPresentationalChildOfAriaRole || ariaRoleHasPresentationalChildren(); result.isDescendantOfBarrenParent = m_isIgnoredFromParentData.isDescendantOfBarrenParent || !canHaveChildren(); } else { diff --git a/Source/WebCore/accessibility/AccessibilityObject.h b/Source/WebCore/accessibility/AccessibilityObject.h index 6b3efc9dafafb..187d866d37253 100644 --- a/Source/WebCore/accessibility/AccessibilityObject.h +++ b/Source/WebCore/accessibility/AccessibilityObject.h @@ -543,7 +543,7 @@ class AccessibilityObject : public AXCoreObject, public CanMakeWeakPtr simpleRange() const override; diff --git a/Source/WebCore/accessibility/atspi/AccessibilityObjectAtspi.cpp b/Source/WebCore/accessibility/atspi/AccessibilityObjectAtspi.cpp index 76584f84b09d0..4967939cb8325 100644 --- a/Source/WebCore/accessibility/atspi/AccessibilityObjectAtspi.cpp +++ b/Source/WebCore/accessibility/atspi/AccessibilityObjectAtspi.cpp @@ -864,7 +864,7 @@ HashMap AccessibilityObjectAtspi::attributes() const RefPtr liveObject = dynamicDowncast(m_coreObject); - String tagName = m_coreObject->tagName(); + String tagName = liveObject->tagName(); if (!tagName.isEmpty()) map.add("tag"_s, tagName); diff --git a/Source/WebCore/accessibility/isolatedtree/AXIsolatedObject.cpp b/Source/WebCore/accessibility/isolatedtree/AXIsolatedObject.cpp index a5fb14f02950b..2e5f6917c547e 100644 --- a/Source/WebCore/accessibility/isolatedtree/AXIsolatedObject.cpp +++ b/Source/WebCore/accessibility/isolatedtree/AXIsolatedObject.cpp @@ -1377,12 +1377,6 @@ void AXIsolatedObject::decrement() }); } -AtomString AXIsolatedObject::tagName() const -{ - ASSERT_NOT_REACHED(); - return AtomString(); -} - bool AXIsolatedObject::isAccessibilityRenderObject() const { ASSERT_NOT_REACHED(); diff --git a/Source/WebCore/accessibility/isolatedtree/AXIsolatedObject.h b/Source/WebCore/accessibility/isolatedtree/AXIsolatedObject.h index a89b6b15b4941..728f52db3a4d0 100644 --- a/Source/WebCore/accessibility/isolatedtree/AXIsolatedObject.h +++ b/Source/WebCore/accessibility/isolatedtree/AXIsolatedObject.h @@ -338,7 +338,6 @@ class AXIsolatedObject final : public AXCoreObject { std::optional selectedChildren() final; void setSelectedChildren(const AccessibilityChildrenVector&) final; AccessibilityChildrenVector visibleChildren() final { return tree()->objectsForIDs(vectorAttributeValue(AXPropertyName::VisibleChildren)); } - AtomString tagName() const final; void setChildrenIDs(Vector&&); void updateChildrenIfNecessary() final; bool isDetachedFromParent() final;