commit 9de5df00a5ebee8a62b4995d4c5dfbc8f2aa927a
parent bf600905d4f6c85ba67e232635cbe3864b5a3acf
Author: Eitan Isaacson <eitan@monotonous.org>
Date: Wed, 15 Oct 2025 17:15:10 +0000
Bug 1994028 - Introduce ACTION/ACTION_FOR relationship. r=Jamie
This is how we will expose aria-actions internally. It does not map to IA2/ATK relationships, but it is still useful because UIA and MacOS will need to show these actions as a distinct list that is not appended to the standard actions list.
Using relationships also lets us take advantage of a tried-and-true code path for caching and change notification.
Differential Revision: https://phabricator.services.mozilla.com/D268440
Diffstat:
10 files changed, 38 insertions(+), 3 deletions(-)
diff --git a/accessible/base/ARIAMap.cpp b/accessible/base/ARIAMap.cpp
@@ -1447,6 +1447,7 @@ struct AttrCharacteristics {
static const AttrCharacteristics gWAIUnivAttrMap[] = {
// clang-format off
+ {nsGkAtoms::aria_actions, ATTR_BYPASSOBJ | ATTR_GLOBAL | ATTR_REFLECT_ELEMENTS },
{nsGkAtoms::aria_activedescendant, ATTR_BYPASSOBJ },
{nsGkAtoms::aria_atomic, ATTR_BYPASSOBJ_IF_FALSE | ATTR_VALTOKEN | ATTR_GLOBAL },
{nsGkAtoms::aria_busy, ATTR_VALTOKEN | ATTR_GLOBAL },
diff --git a/accessible/base/CacheConstants.h b/accessible/base/CacheConstants.h
@@ -95,6 +95,8 @@ static constexpr RelationData kRelationTypeAtoms[] = {
RelationType::DETAILS_FOR},
{nsGkAtoms::aria_errormessage, nullptr, RelationType::ERRORMSG,
RelationType::ERRORMSG_FOR},
+ {nsGkAtoms::aria_actions, nullptr, RelationType::ACTION,
+ RelationType::ACTION_FOR},
};
// The count of numbers needed to serialize an nsRect. This is used when
diff --git a/accessible/base/RelationTypeMap.h b/accessible/base/RelationTypeMap.h
@@ -88,3 +88,9 @@ RELATIONTYPE(ERRORMSG_FOR, "error for", ATK_RELATION_ERROR_FOR,
RELATIONTYPE(LINKS_TO, "links to", ATK_RELATION_NULL, NAVRELATION_LINKS_TO,
IA2_RELATION_NULL)
+
+RELATIONTYPE(ACTION, "action", ATK_RELATION_NULL, NAVRELATION_ACTION,
+ IA2_RELATION_NULL)
+
+RELATIONTYPE(ACTION_FOR, "action for", ATK_RELATION_NULL,
+ NAVRELATION_ACTION_FOR, IA2_RELATION_NULL)
diff --git a/accessible/generic/DocAccessible.cpp b/accessible/generic/DocAccessible.cpp
@@ -68,7 +68,8 @@ static nsStaticAtom* const kRelationAttrs[] = {
nsGkAtoms::aria_controls, nsGkAtoms::aria_flowto,
nsGkAtoms::aria_errormessage, nsGkAtoms::_for,
nsGkAtoms::control, nsGkAtoms::popovertarget,
- nsGkAtoms::commandfor, nsGkAtoms::aria_activedescendant};
+ nsGkAtoms::commandfor, nsGkAtoms::aria_activedescendant,
+ nsGkAtoms::aria_actions};
static const uint32_t kRelationAttrsLen = std::size(kRelationAttrs);
diff --git a/accessible/generic/LocalAccessible.cpp b/accessible/generic/LocalAccessible.cpp
@@ -1516,7 +1516,8 @@ void LocalAccessible::DOMAttributeChanged(int32_t aNameSpaceID,
if (aAttribute == nsGkAtoms::aria_controls ||
aAttribute == nsGkAtoms::aria_flowto ||
- aAttribute == nsGkAtoms::aria_errormessage) {
+ aAttribute == nsGkAtoms::aria_errormessage ||
+ aAttribute == nsGkAtoms::aria_actions) {
mDoc->QueueCacheUpdate(this, CacheDomain::Relations);
}
@@ -2433,6 +2434,14 @@ Relation LocalAccessible::RelationByType(RelationType aType) const {
return Relation(
new RelatedAccIterator(mDoc, mContent, nsGkAtoms::aria_errormessage));
+ case RelationType::ACTION:
+ return Relation(new AssociatedElementsIterator(mDoc, mContent,
+ nsGkAtoms::aria_actions));
+
+ case RelationType::ACTION_FOR:
+ return Relation(
+ new RelatedAccIterator(mDoc, mContent, nsGkAtoms::aria_actions));
+
default:
return Relation();
}
diff --git a/accessible/interfaces/nsIAccessibleRelation.idl b/accessible/interfaces/nsIAccessibleRelation.idl
@@ -161,6 +161,16 @@ interface nsIAccessibleRelation : nsISupports
const unsigned long RELATION_LINKS_TO = 0x19;
/**
+ * This object is has an action associated with the target object.
+ */
+ const unsigned long RELATION_ACTION = 0x20;
+
+ /**
+ * This object is has an action that operates on the target object.
+ */
+ const unsigned long RELATION_ACTION_FOR = 0x21;
+
+ /**
* Returns the type of the relation.
*/
readonly attribute unsigned long relationType;
diff --git a/accessible/tests/browser/relations/browser_relations_general.js b/accessible/tests/browser/relations/browser_relations_general.js
@@ -20,6 +20,7 @@ const attrRelationsSpec = [
["aria-flowto", RELATION_FLOWS_TO, RELATION_FLOWS_FROM],
["aria-details", RELATION_DETAILS, RELATION_DETAILS_FOR],
["aria-errormessage", RELATION_ERRORMSG, RELATION_ERRORMSG_FOR],
+ ["aria-actions", RELATION_ACTION, RELATION_ACTION_FOR],
];
/**
diff --git a/accessible/tests/mochitest/relations.js b/accessible/tests/mochitest/relations.js
@@ -31,6 +31,8 @@ const RELATION_DETAILS_FOR = nsIAccessibleRelation.RELATION_DETAILS_FOR;
const RELATION_ERRORMSG = nsIAccessibleRelation.RELATION_ERRORMSG;
const RELATION_ERRORMSG_FOR = nsIAccessibleRelation.RELATION_ERRORMSG_FOR;
const RELATION_LINKS_TO = nsIAccessibleRelation.RELATION_LINKS_TO;
+const RELATION_ACTION = nsIAccessibleRelation.RELATION_ACTION;
+const RELATION_ACTION_FOR = nsIAccessibleRelation.RELATION_ACTION_FOR;
// //////////////////////////////////////////////////////////////////////////////
// General
diff --git a/accessible/windows/msaa/MsaaAccessible.h b/accessible/windows/msaa/MsaaAccessible.h
@@ -185,7 +185,9 @@ class MsaaAccessible : public ia2Accessible,
NAVRELATION_DETAILS_FOR = 0x1016,
NAVRELATION_ERROR = 0x1017,
NAVRELATION_ERROR_FOR = 0x1018,
- NAVRELATION_LINKS_TO = 0x1019
+ NAVRELATION_LINKS_TO = 0x1019,
+ NAVRELATION_ACTION = 0x1020,
+ NAVRELATION_ACTION_FOR = 0x1021
};
private:
diff --git a/xpcom/ds/StaticAtoms.py b/xpcom/ds/StaticAtoms.py
@@ -119,6 +119,7 @@ STATIC_ATOMS = [
Atom("archive", "archive"),
Atom("area", "area"),
Atom("aria", "aria"),
+ Atom("aria_actions", "aria-actions"),
Atom("aria_activedescendant", "aria-activedescendant"),
Atom("aria_atomic", "aria-atomic"),
Atom("aria_autocomplete", "aria-autocomplete"),