diff --git a/accessible/aom/AccessibleNode.cpp b/accessible/aom/AccessibleNode.cpp index dcf5afdfdcee..7fb0f05c4854 100644 --- a/accessible/aom/AccessibleNode.cpp +++ b/accessible/aom/AccessibleNode.cpp @@ -47,6 +47,7 @@ AccessibleNode::AccessibleNode(nsINode* aNode) : mIntProperties(3), mUIntProperties(6), mBooleanProperties(0), + mRelationProperties(3), mStringProperties(16), mDOMNode(aNode) { diff --git a/accessible/aom/AccessibleNode.h b/accessible/aom/AccessibleNode.h index 774cec0d8a27..d56981b7c866 100644 --- a/accessible/aom/AccessibleNode.h +++ b/accessible/aom/AccessibleNode.h @@ -51,6 +51,17 @@ struct ParentObject; SetProperty(AOMStringProperty::e##name, a##name); \ } \ +#define ANODE_RELATION_FUNC(name) \ + already_AddRefed Get##name() \ + { \ + return GetProperty(AOMRelationProperty::e##name); \ + } \ + \ + void Set##name(AccessibleNode* a##name) \ + { \ + SetProperty(AOMRelationProperty::e##name, a##name); \ + } \ + #define ANODE_PROPS(typeName, type, ...) \ enum class AOM##typeName##Property { \ MOZ_FOR_EACH(ANODE_ENUM, (), (__VA_ARGS__)) \ @@ -63,6 +74,12 @@ struct ParentObject; }; \ MOZ_FOR_EACH(ANODE_STRING_FUNC, (), (__VA_ARGS__)) \ +#define ANODE_RELATION_PROPS(...) \ + enum class AOMRelationProperty { \ + MOZ_FOR_EACH(ANODE_ENUM, (), (__VA_ARGS__)) \ + }; \ + MOZ_FOR_EACH(ANODE_RELATION_FUNC, (), (__VA_ARGS__)) \ + #define ANODE_ACCESSOR_MUTATOR(typeName, type, defVal) \ nsDataHashtable m##typeName##Properties; \ \ @@ -164,6 +181,12 @@ public: ValueNow ) + ANODE_RELATION_PROPS( + ActiveDescendant, + Details, + ErrorMessage + ) + protected: AccessibleNode(const AccessibleNode& aCopy) = delete; AccessibleNode& operator=(const AccessibleNode& aCopy) = delete; @@ -213,9 +236,29 @@ protected: ANODE_ACCESSOR_MUTATOR(Int, int32_t, 0) ANODE_ACCESSOR_MUTATOR(UInt, uint32_t, 0) + already_AddRefed GetProperty(AOMRelationProperty aProperty) + { + RefPtr data; + if (mRelationProperties.Get(static_cast(aProperty), &data)) { + return data.forget(); + } + return nullptr; + } + + void SetProperty(AOMRelationProperty aProperty, + AccessibleNode* aValue) + { + if (!aValue) { + mRelationProperties.Remove(static_cast(aProperty)); + } else { + mRelationProperties.Put(static_cast(aProperty), aValue); + } + } + // The 2k'th bit indicates whether the k'th boolean property is used(1) or not(0) // and 2k+1'th bit contains the property's value(1:true, 0:false) uint32_t mBooleanProperties; + nsDataHashtable > mRelationProperties; nsDataHashtable mStringProperties; RefPtr mIntl; diff --git a/accessible/tests/mochitest/aom/test_general.html b/accessible/tests/mochitest/aom/test_general.html index e8a379e12f46..6ae9dc48283a 100644 --- a/accessible/tests/mochitest/aom/test_general.html +++ b/accessible/tests/mochitest/aom/test_general.html @@ -84,6 +84,13 @@ is(anode[prop], null, `anode.${prop} was assigned null`); } + function testRelationProp(anode, node, prop) { + is(anode[prop], null, `anode.${prop} should be null`); + anode[prop] = node.accessibleNode; + is(anode[prop], node.accessibleNode, `anode.${prop} was assigned AccessibleNode`); + anode[prop] = null; + is(anode[prop], null, `anode.${prop} was assigned null`); + } // Check that the WebIDL is as expected. function checkImplementation(ifrDoc) { let anode = ifrDoc.accessibleNode; @@ -188,6 +195,12 @@ let adopted_node = anotherDoc.adoptNode(node); is(anode, adopted_node.accessibleNode, "adopting node to another document doesn't change node.accessibleNode"); + const relationProps = ["activeDescendant", "details", "errorMessage"]; + + for (const relationProp of relationProps) { + testRelationProp(anode, node, relationProp); + } + finish(); } diff --git a/dom/webidl/AccessibleNode.webidl b/dom/webidl/AccessibleNode.webidl index 478fe24c94dd..f121c8bad702 100644 --- a/dom/webidl/AccessibleNode.webidl +++ b/dom/webidl/AccessibleNode.webidl @@ -61,6 +61,11 @@ interface AccessibleNode { attribute DOMString? live; attribute DOMString? relevant; + // Other relationships + attribute AccessibleNode? activeDescendant; + attribute AccessibleNode? details; + attribute AccessibleNode? errorMessage; + // Collections. attribute long? colCount; attribute unsigned long? colIndex;