0

[A11y] Better error message for aria-hidden problems

Make sure that logs capturing the console error also get the
ancestor in the logs. When logging the elements, provide the
class name and id as well. Elements will look something like:
<div.myclass#some_id>, which will help authors find them.

Bug: none
Change-Id: I1e4acd6eaba417600bcf6a82343f90e8b2d13e04
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6330418
Reviewed-by: Mark Schillaci <mschillaci@google.com>
Auto-Submit: Aaron Leventhal <aleventhal@chromium.org>
Commit-Queue: Aaron Leventhal <aleventhal@chromium.org>
Commit-Queue: Mark Schillaci <mschillaci@google.com>
Cr-Commit-Position: refs/heads/main@{#1428563}
This commit is contained in:
Aaron leventhal
2025-03-05 13:49:16 -08:00
committed by Chromium LUCI CQ
parent 47b29aaf67
commit 0b509547c3
4 changed files with 42 additions and 37 deletions
content/test/data/accessibility/aria
third_party/blink/renderer/modules/accessibility

@ -7,7 +7,7 @@
<!-- Focusing previously unincluded aria-hidden node adds it to the tree -->
<html>
<body>
<div class="hidden" aria-hidden="true">
<div class="hidden" id="some-id" aria-hidden="true">
<span>
<span class="takes-focus" tabindex="-1" role="group">
xyz

@ -212,40 +212,6 @@ String GetIgnoredReasonsDebugString(AXObject::IgnoredReasons& reasons) {
#endif
String GetNodeString(Node* node) {
if (node->IsTextNode()) {
String string_builder = "\"";
string_builder = string_builder + node->nodeValue();
string_builder = string_builder + "\"";
return string_builder;
}
Element* element = DynamicTo<Element>(node);
if (!element) {
return To<Document>(node)->IsLoadCompleted() ? "#document"
: "#document (loading)";
}
String string_builder = "<";
string_builder = string_builder + element->tagName().LowerASCII();
// Cannot safely get @class from SVG elements.
if (!element->IsSVGElement() &&
element->FastHasAttribute(html_names::kClassAttr)) {
string_builder = string_builder + "." +
element->FastGetAttribute(html_names::kClassAttr);
}
if (element->FastHasAttribute(html_names::kIdAttr)) {
string_builder =
string_builder + "#" + element->FastGetAttribute(html_names::kIdAttr);
}
if (element->FastHasAttribute(html_names::kSlotAttr)) {
string_builder = string_builder + " slot=" +
element->FastGetAttribute(html_names::kSlotAttr);
}
return string_builder + ">";
}
#if DCHECK_IS_ON()
bool IsValidRole(ax::mojom::blink::Role role) {
// Check for illegal roles that should not be assigned in Blink.
@ -8411,6 +8377,41 @@ void AXObject::PreSerializationConsistencyCheck() const{
#endif
}
// static
String AXObject::GetNodeString(Node* node) {
if (node->IsTextNode()) {
String string_builder = "\"";
string_builder = string_builder + node->nodeValue();
string_builder = string_builder + "\"";
return string_builder;
}
Element* element = DynamicTo<Element>(node);
if (!element) {
return To<Document>(node)->IsLoadCompleted() ? "#document"
: "#document (loading)";
}
String string_builder = "<";
string_builder = string_builder + element->tagName().LowerASCII();
// Cannot safely get @class from SVG elements.
if (!element->IsSVGElement() &&
element->FastHasAttribute(html_names::kClassAttr)) {
string_builder = string_builder + "." +
element->FastGetAttribute(html_names::kClassAttr);
}
if (element->FastHasAttribute(html_names::kIdAttr)) {
string_builder =
string_builder + "#" + element->FastGetAttribute(html_names::kIdAttr);
}
if (element->FastHasAttribute(html_names::kSlotAttr)) {
string_builder = string_builder + " slot=" +
element->FastGetAttribute(html_names::kSlotAttr);
}
return string_builder + ">";
}
String AXObject::ToString(bool verbose) const {
#if DCHECK_IS_ON()
CHECK(is_initialized_) << "Init() must be called before ToString().";

@ -1478,6 +1478,7 @@ class MODULES_EXPORT AXObject : public GarbageCollected<AXObject> {
// Returns a string representation of this object.
// Must only be used after `init()`has been called.
virtual String ToString(bool verbose = true) const;
static String GetNodeString(Node* node);
void PopulateAXRelativeBounds(ui::AXRelativeBounds& bounds,
bool* clips_children) const;

@ -2319,8 +2319,11 @@ void AXObjectCacheImpl::DiscardBadAriaHiddenBecauseOfFocus(AXObject& obj) {
"also prevent focus. For more details, see the aria-hidden section "
"of the WAI-ARIA specification at "
"https://w3c.github.io/aria/#aria-hidden.\n"
"Element with focus: %s\nAncestor with aria-hidden: ",
focused_element.TagQName().ToString().Ascii().c_str()));
"Element with focus: %s\nAncestor with aria-hidden: %s",
AXObject::GetNodeString(&focused_element).Ascii().c_str(),
AXObject::GetNodeString(bad_aria_hidden_ancestor->GetElement())
.Ascii()
.c_str()));
#if AX_FAIL_FAST_BUILD()
LOG(ERROR) << "Parent chain for focused node's AXObject:\n"
<< ParentChainToStringHelper(&obj);