commit 531786f6a1ea861b9b291c5685bc0d3298535f53
parent 2ef785703f5483ae6f308e2d8bdef57af4ab2453
Author: Eitan Isaacson <eitan@monotonous.org>
Date: Fri, 21 Nov 2025 18:48:41 +0000
Bug 1998242 - P4: Break up name calculation to allow remote subtree calc. r=morgan
LocalAccessible::Name now has 3 parts:
1. DirectName() - Gets name from aria and native attributes and labels, if
nothing retrieved:
2. nsTextEquivUtils::GetNameFromSubtree() - Walks the accessible subtree
to construct a name. If nothing retrieved:
3. Tooltip - get the name from the accessible's toolkit.
Since GetNameFromSubtree is factored out of NativeName, falling back
on alt and value in input[type=image] doesn't work anymore. But this
just brings us more in line with how regular img element names are
calculated, so I think that is fine.
Depends on D271311
Differential Revision: https://phabricator.services.mozilla.com/D271312
Diffstat:
9 files changed, 50 insertions(+), 31 deletions(-)
diff --git a/accessible/base/CssAltContent.cpp b/accessible/base/CssAltContent.cpp
@@ -17,6 +17,10 @@
namespace mozilla::a11y {
CssAltContent::CssAltContent(nsIContent* aContent) {
+ if (!aContent) {
+ return;
+ }
+
nsIFrame* frame = aContent->GetPrimaryFrame();
if (!frame) {
return;
diff --git a/accessible/generic/LocalAccessible.cpp b/accessible/generic/LocalAccessible.cpp
@@ -126,16 +126,26 @@ LocalAccessible::~LocalAccessible() {
}
ENameValueFlag LocalAccessible::DirectName(nsString& aName) const {
- aName.Truncate();
-
if (!HasOwnContent()) return eNameOK;
ENameValueFlag nameFlag = ARIAName(aName);
if (!aName.IsEmpty()) return nameFlag;
nameFlag = NativeName(aName);
+ aName.CompressWhitespace();
+
+ return nameFlag;
+}
+
+ENameValueFlag LocalAccessible::Name(nsString& aName) const {
+ aName.Truncate();
+
+ ENameValueFlag nameFlag = DirectName(aName);
if (!aName.IsEmpty()) return nameFlag;
+ nsTextEquivUtils::GetNameFromSubtree(this, aName);
+ if (!aName.IsEmpty()) return eNameFromSubtree;
+
// In the end get the name from tooltip.
if (Tooltip(aName)) {
return eNameFromTooltip;
@@ -148,11 +158,7 @@ ENameValueFlag LocalAccessible::DirectName(nsString& aName) const {
aName.SetIsVoid(true);
- return nameFlag;
-}
-
-ENameValueFlag LocalAccessible::Name(nsString& aName) const {
- return DirectName(aName);
+ return eNameOK;
}
EDescriptionValueFlag LocalAccessible::Description(
@@ -1535,13 +1541,9 @@ void LocalAccessible::DOMAttributeChanged(int32_t aNameSpaceID,
if (aAttribute == nsGkAtoms::title) {
nsAutoString name;
- ARIAName(name);
- if (name.IsEmpty()) {
- NativeName(name);
- if (name.IsEmpty()) {
- mDoc->FireDelayedEvent(nsIAccessibleEvent::EVENT_NAME_CHANGE, this);
- return;
- }
+ if (Name(name) == eNameFromTooltip || name.IsVoid()) {
+ mDoc->FireDelayedEvent(nsIAccessibleEvent::EVENT_NAME_CHANGE, this);
+ return;
}
if (!elm->HasAttr(nsGkAtoms::aria_describedby)) {
@@ -2685,16 +2687,20 @@ ENameValueFlag LocalAccessible::NativeName(nsString& aName) const {
return eNameOK;
}
- nsTextEquivUtils::GetNameFromSubtree(this, aName);
- return aName.IsEmpty() ? eNameOK : eNameFromSubtree;
+ // We return eNameFromSubtree here to indicate that if there is no native
+ // name we will calculate the name from the subtree next. This is useful for
+ // noting where the name will come from in cases like name change
+ // notifications.
+ return eNameFromSubtree;
}
if (mContent->IsXULElement()) {
XULElmName(mDoc, mContent, aName);
if (!aName.IsEmpty()) return eNameOK;
- nsTextEquivUtils::GetNameFromSubtree(this, aName);
- return aName.IsEmpty() ? eNameOK : eNameFromSubtree;
+ // We return eNameFromSubtree here to indicate that if there is no native
+ // name we will calculate the name from the subtree next. See above.
+ return eNameFromSubtree;
}
if (mContent->IsSVGElement()) {
diff --git a/accessible/html/HTMLElementAccessibles.cpp b/accessible/html/HTMLElementAccessibles.cpp
@@ -42,8 +42,7 @@ ENameValueFlag HTMLBRAccessible::NativeName(nsString& aName) const {
////////////////////////////////////////////////////////////////////////////////
ENameValueFlag HTMLLabelAccessible::NativeName(nsString& aName) const {
- nsTextEquivUtils::GetNameFromSubtree(this, aName);
- return aName.IsEmpty() ? eNameOK : eNameFromSubtree;
+ return eNameOK;
}
Relation HTMLLabelAccessible::RelationByType(RelationType aType) const {
diff --git a/accessible/html/HTMLFormControlAccessible.cpp b/accessible/html/HTMLFormControlAccessible.cpp
@@ -335,8 +335,13 @@ ENameValueFlag HTMLTextFieldAccessible::DirectName(nsString& aName) const {
ENameValueFlag nameFlag = LocalAccessible::DirectName(aName);
if (!aName.IsEmpty()) return nameFlag;
- // text inputs and textareas might have useful placeholder text
- mContent->AsElement()->GetAttr(nsGkAtoms::placeholder, aName);
+ mContent->AsElement()->GetAttr(nsGkAtoms::title, aName);
+ aName.CompressWhitespace();
+ if (aName.IsEmpty()) {
+ // text inputs and textareas might have useful placeholder text
+ mContent->AsElement()->GetAttr(nsGkAtoms::placeholder, aName);
+ }
+
return eNameOK;
}
diff --git a/accessible/tests/browser/name_and_description/browser_name_general.js b/accessible/tests/browser/name_and_description/browser_name_general.js
@@ -277,3 +277,12 @@ addAccessibleTask(
},
{ topLevel: true, chrome: true }
);
+
+addAccessibleTask(
+ `<input id="input" type="text" title="title" placeholder="placeholder"></input>`,
+ async function testInputPlaceHolder(browser, docAcc) {
+ const input = findAccessibleChildByID(docAcc, "input");
+ testName(input, "title");
+ },
+ { topLevel: true, chrome: true }
+);
diff --git a/accessible/tests/mochitest/name/markuprules.xml b/accessible/tests/mochitest/name/markuprules.xml
@@ -141,8 +141,8 @@
<ruleset id="HTMLInputImageNoValidSrc" defaultName="Submit Query">
<ruleset ref="HTMLControl:Head"/>
- <rule attr="alt" type="string" explicit-name="false"/>
- <rule attr="value" type="string" explicit-name="false"/>
+ <rule attr="alt" type="string"/>
+ <rule attr="value" type="string"/>
</ruleset>
<ruleset id="HTMLOption">
diff --git a/accessible/xul/XULElementAccessibles.cpp b/accessible/xul/XULElementAccessibles.cpp
@@ -146,10 +146,7 @@ void XULLinkAccessible::Value(nsString& aValue) const {
ENameValueFlag XULLinkAccessible::NativeName(nsString& aName) const {
mContent->AsElement()->GetAttr(nsGkAtoms::value, aName);
- if (!aName.IsEmpty()) return eNameOK;
-
- nsTextEquivUtils::GetNameFromSubtree(this, aName);
- return aName.IsEmpty() ? eNameOK : eNameFromSubtree;
+ return eNameOK;
}
role XULLinkAccessible::NativeRole() const { return roles::LINK; }
diff --git a/devtools/client/accessibility/test/browser/browser_accessibility_print_to_json.js b/devtools/client/accessibility/test/browser/browser_accessibility_print_to_json.js
@@ -166,7 +166,7 @@ const EXPECTED_SNAPSHOT = {
description: "",
indexInParent: 0,
keyboardShortcut: "",
- name: "",
+ name: null,
nodeCssSelector: "",
nodeType: 9,
role: "document",
@@ -174,7 +174,6 @@ const EXPECTED_SNAPSHOT = {
actions: [],
attributes: {
display: "block",
- "explicit-name": "true",
"margin-bottom": "8px",
"margin-left": "8px",
"margin-right": "8px",
diff --git a/devtools/client/accessibility/test/browser/browser_accessibility_tree_navigation_oop.js b/devtools/client/accessibility/test/browser/browser_accessibility_tree_navigation_oop.js
@@ -26,7 +26,7 @@ const tests = [
},
],
sidebar: {
- name: "",
+ name: null,
role: "document",
actions: [],
value: "",