Skip to content
Permalink
Browse files
AX: Implement the ARIA 1.3 mark role, which provides parity with the …
…<mark> tag.

https://bugs.webkit.org/show_bug.cgi?id=206251
rdar://58577388

Reviewed by Andres Gonzalez.

This patch exposes the new ARIA 1.3 mark role. This will allow AX clients to access and convey this content to users.

* LayoutTests/accessibility/display-contents-element-roles-expected.txt
* LayoutTests/accessibility/roles-computedRoleString.html
* LayoutTests/platform/mac-wk2/accessibility/aria-visible-element-roles-expected.txt
* LayoutTests/platform/mac/accessibility/roles-computedRoleString-expected.txt
* LayoutTests/platform/glib/accessibility/display-contents-element-roles-expected.txt:
* LayoutTests/platform/mac-wk1/accessibility/aria-visible-element-roles-expected.txt:
* LayoutTests/platform/glib/accessibility/aria-visible-element-roles-expected.txt

Updated old layouttests and expectations to correspond with the new "mark" role mapping.

* LayoutTests/accessibility/ios-simulator/mark-role-expected.txt: Added.
* LayoutTests/accessibility/ios-simulator/mark-role.html: Added.
* LayoutTests/accessibility/mac/mark-role-expected.txt: Added.
* LayoutTests/accessibility/mac/mark-role.html: Added.

New layout tests.

* Source/WebCore/accessibility/ios/WebAccessibilityObjectWrapperIOS.mm:
(-[WebAccessibilityObjectWrapper accessibilityIsMarkAnnotation]):
* Source/WebCore/accessibility/mac/WebAccessibilityObjectWrapperMac.mm:
(AXAttributeStringSetStyle):

Set's an "AXHighlight" attribute on strings that have an ancestor with a mark role.

* Source/WebCore/accessibility/AccessibilityObject.cpp
* Source/WebCore/accessibility/AccessibilityNodeObject.cpp

Add condition to check for roleAttr = "mark".

* Tools/DumpRenderTree/AccessibilityUIElement.cpp:
(getIsMarkAnnotationCallback):
(AccessibilityUIElement::getJSClass):
* Tools/DumpRenderTree/AccessibilityUIElement.h:
* Tools/DumpRenderTree/ios/AccessibilityUIElementIOS.mm:
(AccessibilityUIElement::isMarkAnnotation const):
* Tools/WebKitTestRunner/InjectedBundle/AccessibilityUIElement.cpp:
(WTR::AccessibilityUIElement::isMarkAnnotation const):
* Tools/WebKitTestRunner/InjectedBundle/AccessibilityUIElement.h:
* Tools/WebKitTestRunner/InjectedBundle/Bindings/AccessibilityUIElement.idl:
* Tools/WebKitTestRunner/InjectedBundle/ios/AccessibilityUIElementIOS.mm:
(WTR::AccessibilityUIElement::isMarkAnnotation const):

New methods to check if an element has a mark-role ancestor.

Canonical link: https://commits.webkit.org/254008@main
  • Loading branch information
hoffmanjoshua authored and AndresGonzalezApple committed Aug 31, 2022
1 parent 321c28b commit 335a5587c31289a3a8043e4c460f7488c59e947b
Show file tree
Hide file tree
Showing 22 changed files with 119 additions and 3 deletions.
@@ -95,6 +95,7 @@ This test ensures elements with CSS display: contents have the correct role.

<mark class="testcase" id="mark"></mark>
AXRole: AXGroup
computedRoleString: mark

<menu class="testcase" type="toolbar" id="menu-toolbar"></menu>
AXRole: AXToolbar
@@ -0,0 +1,9 @@
This test makes sure that the mark role exposes the right attributes.
PASS: highlight1.isMarkAnnotation === true

PASS successfullyParsed is true

TEST COMPLETE
This is some
highlighted
text.
@@ -0,0 +1,25 @@
<!DOCTYPE HTML PUBLIC>
<html>
<head>
<script src="../../resources/js-test.js"></script>
<script src="../../resources/accessibility-helper.js"></script>
</head>
<body>

<div>This is some <div id="highlight1" role="mark">highlighted</div> text.</div>

<script>

if (window.accessibilityController) {
let output = "This test makes sure that the mark role exposes the right attributes.\n";

var highlight1 = accessibilityController.accessibleElementById("highlight1").childAtIndex(0);
output += expect("highlight1.isMarkAnnotation", "true");

debug(output);
}

</script>

</body>
</html>
@@ -0,0 +1,11 @@
This test makes sure that the mark role exposes the right attributes in the attriubuted string.
PASS: highlight1.attributedStringForTextMarkerRangeContainsAttribute('AXHighlight', markerRange) === true
PASS: highlight2.attributedStringForTextMarkerRangeContainsAttribute('AXHighlight', markerRange) === true

PASS successfullyParsed is true

TEST COMPLETE
This is some
highlighted
text.
This is some highlighted text.
@@ -0,0 +1,31 @@
<!DOCTYPE HTML PUBLIC>
<html>
<head>
<script src="../../resources/js-test.js"></script>
<script src="../../resources/accessibility-helper.js"></script>
</head>
<body>

<div>This is some <div id="highlight1" role="mark">highlighted</div> text.</div>
<div>This is some <mark id="highlight2">highlighted</mark> text.</div>

<script>

if (window.accessibilityController) {
let output = "This test makes sure that the mark role exposes the right attributes in the attriubuted string.\n";

var highlight1 = accessibilityController.accessibleElementById("highlight1").childAtIndex(0);
var markerRange = highlight1.textMarkerRangeForElement(highlight1);
output += expect("highlight1.attributedStringForTextMarkerRangeContainsAttribute('AXHighlight', markerRange)", "true");

var highlight2 = accessibilityController.accessibleElementById("highlight2").childAtIndex(0);
var markerRange = highlight2.textMarkerRangeForElement(highlight2);
output += expect("highlight2.attributedStringForTextMarkerRangeContainsAttribute('AXHighlight', markerRange)", "true");

debug(output);
}

</script>

</body>
</html>
@@ -55,7 +55,7 @@ <h5 data-role="heading" data-platform="atspi,mac" class="ex">X</h6>
<input type="url" value="X" data-role="" data-platform="atspi,mac" class="ex" data-note="[type='url']">
<input type="week" value="X" data-role="" data-platform="atspi,mac" class="ex" data-note="[type='week']">
<ins data-role="insertion" data-platform="atspi,mac" class="ex">X</ins>
<mark data-role="" data-platform="atspi,mac" class="ex">X</mark>
<mark data-role="mark" data-platform="atspi,mac" class="ex">X</mark>
<math data-role="math" data-platform="atspi,mac" class="ex">X</math>
<!-- skipped <menu> -->
<!-- skipped <meta> -->
@@ -161,6 +161,7 @@ This test ensures ARIA visible elements (e.g. those with both `hidden` and `aria

<mark hidden="" aria-hidden="false" id="mark"></mark>

computedRoleString: mark

<pre hidden="" aria-hidden="false" id="pre"></pre>
AXRole: AXSection
@@ -81,6 +81,7 @@ This test ensures elements with CSS display: contents have the correct role.

<mark class="testcase" id="mark"></mark>

computedRoleString: mark

<menu class="testcase" type="toolbar" id="menu-toolbar"></menu>
AXRole: AXToolbar
@@ -179,6 +179,7 @@ This test ensures ARIA visible elements (e.g. those with both `hidden` and `aria

<mark hidden="" aria-hidden="false" id="mark"></mark>
AXRole: AXGroup
computedRoleString: mark

<pre hidden="" aria-hidden="false" id="pre"></pre>
AXRole: AXGroup
@@ -179,6 +179,7 @@ This test ensures ARIA visible elements (e.g. those with both `hidden` and `aria

<mark hidden="" aria-hidden="false" id="mark"></mark>
AXRole: AXGroup
computedRoleString: mark

<pre hidden="" aria-hidden="false" id="pre"></pre>
AXRole: AXGroup
@@ -43,7 +43,7 @@ PASS input[type='time'] -> .
PASS input[type='url'] -> .
PASS input[type='week'] -> .
PASS ins -> insertion.
PASS mark -> .
PASS mark -> mark.
PASS math -> math.
PASS meter -> meter.
PASS nav -> navigation.
@@ -375,7 +375,7 @@ AccessibilityRole AccessibilityNodeObject::determineAccessibilityRoleFromNode(Tr
return AccessibilityRole::Caption;
if (node()->hasTagName(dialogTag))
return AccessibilityRole::ApplicationDialog;
if (node()->hasTagName(markTag))
if (node()->hasTagName(markTag) || equalLettersIgnoringASCIICase(getAttribute(roleAttr), "mark"_s))
return AccessibilityRole::Mark;
if (node()->hasTagName(preTag))
return AccessibilityRole::Pre;
@@ -2554,6 +2554,7 @@ static void initializeRoleMap()
{ "main"_s, AccessibilityRole::LandmarkMain },
{ "marquee"_s, AccessibilityRole::ApplicationMarquee },
{ "math"_s, AccessibilityRole::DocumentMath },
{ "mark"_s, AccessibilityRole::Mark },
{ "menu"_s, AccessibilityRole::Menu },
{ "menubar"_s, AccessibilityRole::MenuBar },
{ "menuitem"_s, AccessibilityRole::MenuItem },
@@ -2827,6 +2827,14 @@ - (BOOL)accessibilityIsLastItemInSuggestion
return NO;
}

- (BOOL)accessibilityIsMarkAnnotation
{
if (![self _prepareAccessibilityCall])
return NO;

return ancestorWithRole(*self.axBackingObject, { AccessibilityRole::Mark }) != nullptr;
}

- (NSArray<NSString *> *)accessibilitySpeechHint
{
if (![self _prepareAccessibilityCall])
@@ -865,6 +865,8 @@ static void AXAttributeStringSetStyle(NSMutableAttributedString* attrString, Ren
AXAttributeStringSetNumber(attrString, @"AXIsSuggestedDeletion", @YES, range);
else if (equalLettersIgnoringASCIICase(roleValue, "suggestion"_s))
AXAttributeStringSetNumber(attrString, @"AXIsSuggestion", @YES, range);
else if (equalLettersIgnoringASCIICase(roleValue, "mark"_s))
AXAttributeStringSetNumber(attrString, @"AXHighlight", @YES, range);
}
}
}
@@ -1660,6 +1660,11 @@ static JSValueRef getIsLastItemInSuggestionCallback(JSContextRef context, JSObje
return JSValueMakeBoolean(context, toAXElement(thisObject)->isLastItemInSuggestion());
}

static JSValueRef getIsMarkAnnotationCallback(JSContextRef context, JSObjectRef thisObject, JSStringRef propertyName, JSValueRef* exception)
{
return JSValueMakeBoolean(context, toAXElement(thisObject)->isMarkAnnotation());
}

#endif // PLATFORM(IOS_FAMILY)

#if PLATFORM(MAC) && !PLATFORM(IOS_FAMILY)
@@ -2023,6 +2028,7 @@ JSClassRef AccessibilityUIElement::getJSClass()
{ "isDeletion", getIsDeletionCallback, 0 , kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
{ "isFirstItemInSuggesiton", getIsFirstItemInSuggestionCallback, 0 , kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
{ "isLastItemInSuggesiton", getIsLastItemInSuggestionCallback, 0 , kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
{ "isMarkAnnotation", getIsMarkAnnotationCallback, 0 , kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
#endif // PLATFORM(IOS_FAMILY)
#if PLATFORM(MAC) && !PLATFORM(IOS_FAMILY)
{ "supportedActions", supportedActionsCallback, 0, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
@@ -327,6 +327,8 @@ class AccessibilityUIElement {
bool isTextArea() const;
bool isSearchField() const;

bool isMarkAnnotation() const;

AccessibilityTextMarkerRange textMarkerRangeMatchesTextNearMarkers(JSStringRef, AccessibilityTextMarker*, AccessibilityTextMarker*);
#endif // PLATFORM(IOS_FAMILY)

@@ -106,6 +106,7 @@ - (BOOL)accessibilityIsInsertion;
- (BOOL)accessibilityIsDeletion;
- (BOOL)accessibilityIsFirstItemInSuggestion;
- (BOOL)accessibilityIsLastItemInSuggestion;
- (BOOL)accessibilityIsMarkAnnotation;

// TextMarker related
- (NSArray *)textMarkerRange;
@@ -1304,3 +1305,8 @@ static void _CGPathEnumerationIteration(void *info, const CGPathElement *element
{
return [m_element accessibilityIsLastItemInSuggestion];
}

bool AccessibilityUIElement::isMarkAnnotation() const
{
return [m_element accessibilityIsMarkAnnotation];
}
@@ -89,6 +89,7 @@ JSRetainPtr<JSStringRef> AccessibilityUIElement::attributedStringForElement() {
bool AccessibilityUIElement::isInTable() const { return false; }
bool AccessibilityUIElement::isInLandmark() const { return false; }
bool AccessibilityUIElement::isInList() const { return false; }
bool AccessibilityUIElement::isMarkAnnotation() const { return false; }
#endif

// Unsupported methods on various platforms. As they're implemented on other platforms this list should be modified.
@@ -407,6 +407,8 @@ class AccessibilityUIElement : public JSWrappable {
bool isDeletion() const;
bool isFirstItemInSuggestion() const;
bool isLastItemInSuggestion() const;

bool isMarkAnnotation() const;
private:
AccessibilityUIElement(PlatformUIElement);
AccessibilityUIElement(const AccessibilityUIElement&);
@@ -294,6 +294,7 @@
undefined assistiveTechnologySimulatedFocus();
readonly attribute boolean isSearchField;
readonly attribute boolean isTextArea;
readonly attribute boolean isMarkAnnotation;

readonly attribute boolean hasDocumentRoleAncestor;
readonly attribute boolean hasWebApplicationAncestor;
@@ -125,6 +125,7 @@ - (BOOL)accessibilityIsDeletion;
- (BOOL)accessibilityIsInsertion;
- (BOOL)accessibilityIsFirstItemInSuggestion;
- (BOOL)accessibilityIsLastItemInSuggestion;
- (BOOL)accessibilityIsMarkAnnotation;

// TextMarker related
- (NSArray *)textMarkerRange;
@@ -1522,4 +1523,9 @@ static void _CGPathEnumerationIteration(void *info, const CGPathElement *element
return [m_element accessibilityIsLastItemInSuggestion];
}

bool AccessibilityUIElement::isMarkAnnotation() const
{
return [m_element accessibilityIsMarkAnnotation];
}

} // namespace WTR

0 comments on commit 335a558

Please sign in to comment.