Skip to content

Commit bbbfca6

Browse files
author
Rahim Abdi
committed
WebDriver: Add support for GetAccessibilityPropertiesForElement, GetAccessibilityPropertiesForAccessibilityNode commands
https://bugs.webkit.org/show_bug.cgi?id=299508 rdar://161303091 Reviewed by NOBODY (OOPS!). This patch implements two new WebDriver automation commands used to support more robust WPT accessibility testing: - GetAccessibilityPropertiesForElement - GetAccessibilityPropertiesForAccessibilityNode For this initial implementation, test_driver.get_accessibility_properties...() will return an accessibility property bag containing the following computed properties: - accessibilityNodeId - role - label - checked - pressed - children (array of serialized AXIDs) - parent (serialized AXID) As these new WebDriver commands are test-only interfaces, there's been in-depth discussion around how to treat computed AX properties when a property is missing and supported, or present & unsupported; see WICG/aom#203. Some additional resources: - WebDriver PR for the new commands: w3c/webdriver#1960 - ARIA PR for the initial set of computed accessibility properties, and treatment of undefined/missing/unsupported values: w3c/aria#2800. At a high level, the WebDriver client (i.e., Web Platform Tests' testdriver.js) initiates these new commands which is then dispatched to the UI Process (WebAutomationSession). The WebAutomationSession then parses the payload and extracts the protocol-specific element or accessibility node, after which it identifies the target (WebPageProxy) which invokes an asynchronous IPC message to the corresponding Web Process. Note that GetAccessibilityPropertiesForElement uses the same DOM node/frame-based approach as many other WebDriver commands however, GetAccessibilityPropertiesForAXNode does not require frame-based process routing (it retrieves computed accessibility properties using the page's axObjectCache, rather than a specific frame tied to a DOM node); thus, GetAccessibilityPropertiesForAccessibilityNode has a different message signature. Note that to fully support these new WebDriver commands, corresponding WebDriver HTTP endpoints must be implemented in Webdriver for Safari (safaridriver): - session/{session_id}/element/{elId}/accessibilityproperties: Returns accessibility properties for DOM element {elId} - session/{session_id}/accessibility/properties/{accessibilityId}: Returns accessibility properties for accessibility node {accessibilityId} Due to the existence of two AccessibilityProperties protocol object definitions, documentation for each has been updated: - Source/WebKit/UIProcess/Automation/Automation.json — specification conformance and interoperability testing - Source/JavaScriptCore/inspector/protocol/DOM.json — Web Inspector DOM element inspection As an unrelated small fix, the return type for GetComputedLabel (WebAutomationSessionProxy IPC message) incorrectly names the first string parameter as "role" instead of "label" so this patch also corrects the tuple to return (label, errorType). * LayoutTests/resources/testdriver-vendor.js: (window.test_driver_internal.get_accessibility_properties_for_element): (window.test_driver_internal.get_accessibility_properties_for_accessibility_node): * Source/JavaScriptCore/inspector/protocol/DOM.json * Source/WebKit/UIProcess/Automation/Automation.json: * Source/WebKit/UIProcess/Automation/WebAutomationSession.cpp: (Ref<JSON::ArrayOf<String>> buildArrayForAXChildren) (WebKit::WebAutomationSession::getAccessibilityPropertiesForElement): (WebKit::WebAutomationSession::getAccessibilityPropertiesForAccessibilityNode): * Source/WebKit/UIProcess/Automation/WebAutomationSession.h: * Source/WebKit/UIProcess/WebPageProxy.cpp: * Source/WebKit/WebProcess/Automation/WebAutomationSessionProxy.cpp: (WebKit::WebAutomationSessionProxy::getAccessibilityPropertiesForElement): (WebKit::WebAutomationSessionProxy::getAccessibilityPropertiesForAccessibilityNode): (WebKit::WebAutomationSessionProxy::getAccessibilityObjectForAXNode) (WebAutomationSessionProxy::ComputedAXProperties getComputedAccessibilityProperties) * Source/WebKit/WebProcess/Automation/WebAutomationSessionProxy.h: * Source/WebKit/WebProcess/Automation/WebAutomationSessionProxy.messages.in:
1 parent 7a5ee54 commit bbbfca6

9 files changed

Lines changed: 237 additions & 2 deletions

File tree

LayoutTests/resources/testdriver-vendor.js

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -713,6 +713,32 @@ window.test_driver_internal.get_computed_role = async function (element, context
713713
return context.internals.getComputedRole(element);
714714
}
715715

716+
/**
717+
*
718+
* @param {Element} element
719+
* @returns {Promise<Object>}
720+
*/
721+
window.test_driver_internal.get_accessibility_properties_for_element = async function (element, context=null) {
722+
if (!element)
723+
return {};
724+
context = context ?? window;
725+
726+
return context.internals.getAccessibilityPropertiesForElement(element);
727+
}
728+
729+
/**
730+
*
731+
* @param {string} accessibilityNodeId
732+
* @returns {Promise<Object>}
733+
*/
734+
window.test_driver_internal.get_accessibility_properties_for_accessibility_node = async function (accessibilityNodeId, context=null) {
735+
if (!element)
736+
return {};
737+
context = context ?? window;
738+
739+
return context.internals.getAccessibilityPropertiesForAccessibilityNode(accessibilityNodeId);
740+
}
741+
716742
/**
717743
*
718744
* @param {string} origin

Source/JavaScriptCore/inspector/protocol/DOM.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@
101101
},
102102
{
103103
"id": "AccessibilityProperties",
104-
"description": "A structure holding accessibility properties.",
104+
"description": "A structure holding accessibility properties, either forwarded to the DOM Element from its backing Accessibility Node, and/or some local properties (e.g., ignored) that may clarify other characteristics, such as why a backing Accessibility Node is not available for this DOM Element.",
105105
"type": "object",
106106
"properties": [
107107
{ "name": "activeDescendantNodeId", "$ref": "NodeId", "optional": true, "description": "<code>DOMNode</code> id of the accessibility object referenced by aria-activedescendant." },

Source/WebKit/UIProcess/Automation/Automation.json

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,20 @@
22
"domain": "Automation",
33
"description": "Automation domain exposes commands for automating user interactions with the browser.",
44
"types": [
5+
{
6+
"id": "AccessibilityProperties",
7+
"type": "object",
8+
"description": "Snapshot of a DOM node's computed accessibility properties used in WebDriver contexts.",
9+
"properties": [
10+
{ "name": "accessibilityNodeId", "type": "string" },
11+
{ "name": "role", "type": "string" },
12+
{ "name": "label", "type": "string" },
13+
{ "name": "checked", "type": "string" },
14+
{ "name": "pressed", "type": "string" },
15+
{ "name": "parent", "type": "string" },
16+
{ "name": "children", "type": "array", "items": { "type": "string" } }
17+
]
18+
},
519
{
620
"id": "Point",
721
"type": "object",
@@ -713,6 +727,32 @@
713727
],
714728
"async": true
715729
},
730+
{
731+
"name": "getAccessibilityPropertiesForElement",
732+
"description": "Get computed accessibility properties for a DOM element.",
733+
"parameters": [
734+
{ "name": "browsingContextHandle", "$ref": "BrowsingContextHandle", "description": "The handle for the browsing context." },
735+
{ "name": "frameHandle", "$ref": "FrameHandle", "optional": true, "description": "The handle for the frame that contains the element. The main frame is used if this parameter is empty string or excluded." },
736+
{ "name": "nodeHandle", "$ref": "NodeHandle", "description": "The handle of the element to get the accessibility properties for." }
737+
],
738+
"returns": [
739+
{ "name": "properties", "$ref": "AccessibilityProperties" }
740+
],
741+
"async": true
742+
},
743+
{
744+
"name": "getAccessibilityPropertiesForAccessibilityNode",
745+
"description": "Get computed accessibility properties for an accessibility node from WebKit's accessibility tree.",
746+
"parameters": [
747+
{ "name": "browsingContextHandle", "$ref": "BrowsingContextHandle", "description": "The handle for the browsing context." },
748+
{ "name": "accessibilityNodeHandle", "type": "string", "description": "The handle of the accessibility node to get the accessibility properties for." }
749+
],
750+
"returns": [
751+
{ "name": "properties", "$ref": "AccessibilityProperties" }
752+
],
753+
"async": true
754+
755+
},
716756
{
717757
"name": "selectOptionElement",
718758
"description": "Selects the given option element. In case of container with multiple options enabled, the element selectedness is toggled.",

Source/WebKit/UIProcess/Automation/WebAutomationSession.cpp

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1683,6 +1683,59 @@ void WebAutomationSession::getComputedLabel(const Inspector::Protocol::Automatio
16831683
page->sendWithAsyncReplyToProcessContainingFrameWithoutDestinationIdentifier(frameID, Messages::WebAutomationSessionProxy::GetComputedLabel(page->webPageIDInMainFrameProcess(), frameID, nodeHandle), WTF::move(completionHandler));
16841684
}
16851685

1686+
static Ref<JSON::ArrayOf<String>> buildArrayForAXChildren(Vector<String>& axChildren)
1687+
{
1688+
auto childrenArray = JSON::ArrayOf<String>::create();
1689+
1690+
for (const auto& child : axChildren)
1691+
childrenArray->addItem(child);
1692+
1693+
return childrenArray;
1694+
}
1695+
1696+
static WTF::CompletionHandler<void(std::optional<String>&&, std::optional<String>&&, std::optional<String>&&, std::optional<String>&&, std::optional<String>&&, std::optional<String>&&, std::optional<String>&&, Vector<String>&&)>
1697+
makeAccessibilityPropertiesCompletionHandler(Inspector::CommandCallback<Ref<Inspector::Protocol::Automation::AccessibilityProperties>>&& callback)
1698+
{
1699+
return [callback = WTF::move(callback)](std::optional<String>&& optionalError, std::optional<String>&& accessibilityNodeId, std::optional<String>&& role, std::optional<String>&& label, std::optional<String>&& checked, std::optional<String>&& pressed, std::optional<String>&& parent, Vector<String>&& children) mutable {
1700+
ASYNC_FAIL_WITH_PREDEFINED_ERROR_IF_SET(optionalError);
1701+
auto axProperties = Inspector::Protocol::Automation::AccessibilityProperties::create()
1702+
.setAccessibilityNodeId(*accessibilityNodeId)
1703+
.setRole(*role)
1704+
.setLabel(*label)
1705+
.setChecked(*checked)
1706+
.setPressed(*pressed)
1707+
.setParent(*parent)
1708+
.setChildren(buildArrayForAXChildren(children))
1709+
.release();
1710+
callback({ WTF::move(axProperties) });
1711+
};
1712+
}
1713+
1714+
void WebAutomationSession::getAccessibilityPropertiesForElement(const Inspector::Protocol::Automation::BrowsingContextHandle& browsingContextHandle, const Inspector::Protocol::Automation::FrameHandle& frameHandle, const Inspector::Protocol::Automation::NodeHandle& nodeHandle, Inspector::CommandCallback<Ref<Inspector::Protocol::Automation::AccessibilityProperties>>&& callback)
1715+
{
1716+
auto page = webPageProxyForHandle(browsingContextHandle);
1717+
ASYNC_FAIL_WITH_PREDEFINED_ERROR_IF(!page, WindowNotFound);
1718+
1719+
bool frameNotFound = false;
1720+
auto frameID = webFrameIDForHandle(frameHandle, frameNotFound);
1721+
ASYNC_FAIL_WITH_PREDEFINED_ERROR_IF(frameNotFound, FrameNotFound);
1722+
1723+
page->sendWithAsyncReplyToProcessContainingFrameWithoutDestinationIdentifier(
1724+
frameID,
1725+
Messages::WebAutomationSessionProxy::GetAccessibilityPropertiesForElement(page->webPageIDInMainFrameProcess(), frameID, nodeHandle),
1726+
makeAccessibilityPropertiesCompletionHandler(WTF::move(callback)));
1727+
}
1728+
1729+
void WebAutomationSession::getAccessibilityPropertiesForAccessibilityNode(const Inspector::Protocol::Automation::BrowsingContextHandle& browsingContextHandle, const String& accessibilityNodeHandle, Inspector::CommandCallback<Ref<Inspector::Protocol::Automation::AccessibilityProperties>>&& callback)
1730+
{
1731+
RefPtr page = webPageProxyForHandle(browsingContextHandle);
1732+
ASYNC_FAIL_WITH_PREDEFINED_ERROR_IF(!page, WindowNotFound);
1733+
1734+
page->legacyMainFrameProcess().sendWithAsyncReply(
1735+
Messages::WebAutomationSessionProxy::GetAccessibilityPropertiesForAccessibilityNode(page->webPageIDInMainFrameProcess(), accessibilityNodeHandle),
1736+
makeAccessibilityPropertiesCompletionHandler(WTF::move(callback)));
1737+
}
1738+
16861739
void WebAutomationSession::selectOptionElement(const Inspector::Protocol::Automation::BrowsingContextHandle& browsingContextHandle, const Inspector::Protocol::Automation::FrameHandle& frameHandle, const Inspector::Protocol::Automation::NodeHandle& nodeHandle, CommandCallback<void>&& callback)
16871740
{
16881741
auto page = webPageProxyForHandle(browsingContextHandle);

Source/WebKit/UIProcess/Automation/WebAutomationSession.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,8 @@ friend class InspectorPassthroughChannel;
272272
void computeElementLayout(const Inspector::Protocol::Automation::BrowsingContextHandle&, const Inspector::Protocol::Automation::FrameHandle&, const Inspector::Protocol::Automation::NodeHandle&, std::optional<bool>&& scrollIntoViewIfNeeded, Inspector::Protocol::Automation::CoordinateSystem, Inspector::CommandCallbackOf<Ref<Inspector::Protocol::Automation::Rect>, RefPtr<Inspector::Protocol::Automation::Point>, bool>&&) override;
273273
void getComputedRole(const Inspector::Protocol::Automation::BrowsingContextHandle&, const Inspector::Protocol::Automation::FrameHandle&, const Inspector::Protocol::Automation::NodeHandle&, Inspector::CommandCallback<String>&&) override;
274274
void getComputedLabel(const Inspector::Protocol::Automation::BrowsingContextHandle&, const Inspector::Protocol::Automation::FrameHandle&, const Inspector::Protocol::Automation::NodeHandle&, Inspector::CommandCallback<String>&&) override;
275+
void getAccessibilityPropertiesForElement(const Inspector::Protocol::Automation::BrowsingContextHandle&, const Inspector::Protocol::Automation::FrameHandle&, const Inspector::Protocol::Automation::NodeHandle&, Inspector::CommandCallback<Ref<Inspector::Protocol::Automation::AccessibilityProperties>>&&) override;
276+
void getAccessibilityPropertiesForAccessibilityNode(const Inspector::Protocol::Automation::BrowsingContextHandle&, const String& accessibilityNodeHandle, Inspector::CommandCallback<Ref<Inspector::Protocol::Automation::AccessibilityProperties>>&&) override;
275277
void selectOptionElement(const Inspector::Protocol::Automation::BrowsingContextHandle&, const Inspector::Protocol::Automation::FrameHandle&, const Inspector::Protocol::Automation::NodeHandle&, Inspector::CommandCallback<void>&&) override;
276278
Inspector::CommandResult<bool> isShowingJavaScriptDialog(const Inspector::Protocol::Automation::BrowsingContextHandle&) override;
277279
Inspector::CommandResult<void> dismissCurrentJavaScriptDialog(const Inspector::Protocol::Automation::BrowsingContextHandle&) override;

Source/WebKit/UIProcess/WebPageProxy.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18557,6 +18557,7 @@ INSTANTIATE_SEND_WITH_ASYNC_REPLY_TO_PROCESS_CONTAINING_FRAME_WITHOUT_DESTINATIO
1855718557
INSTANTIATE_SEND_WITH_ASYNC_REPLY_TO_PROCESS_CONTAINING_FRAME_WITHOUT_DESTINATION_ID(WebAutomationSessionProxy::FocusFrame);
1855818558
INSTANTIATE_SEND_WITH_ASYNC_REPLY_TO_PROCESS_CONTAINING_FRAME_WITHOUT_DESTINATION_ID(WebAutomationSessionProxy::GetComputedRole);
1855918559
INSTANTIATE_SEND_WITH_ASYNC_REPLY_TO_PROCESS_CONTAINING_FRAME_WITHOUT_DESTINATION_ID(WebAutomationSessionProxy::GetComputedLabel);
18560+
INSTANTIATE_SEND_WITH_ASYNC_REPLY_TO_PROCESS_CONTAINING_FRAME_WITHOUT_DESTINATION_ID(WebAutomationSessionProxy::GetAccessibilityPropertiesForElement);
1856018561
INSTANTIATE_SEND_WITH_ASYNC_REPLY_TO_PROCESS_CONTAINING_FRAME_WITHOUT_DESTINATION_ID(WebAutomationSessionProxy::ResolveParentFrame);
1856118562
INSTANTIATE_SEND_WITH_ASYNC_REPLY_TO_PROCESS_CONTAINING_FRAME_WITHOUT_DESTINATION_ID(WebAutomationSessionProxy::SelectOptionElement);
1856218563
INSTANTIATE_SEND_WITH_ASYNC_REPLY_TO_PROCESS_CONTAINING_FRAME_WITHOUT_DESTINATION_ID(WebAutomationSessionProxy::ResolveChildFrameWithName);

Source/WebKit/WebProcess/Automation/WebAutomationSessionProxy.cpp

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
#include <JavaScriptCore/JSStringRefPrivate.h>
4848
#include <JavaScriptCore/OpaqueJSString.h>
4949
#include <JavaScriptCore/SourceTaintedOrigin.h>
50+
#include <WebCore/AXID.h>
5051
#include <WebCore/AXObjectCache.h>
5152
#include <WebCore/AccessibilityObject.h>
5253
#include <WebCore/ContainerNodeInlines.h>
@@ -76,6 +77,7 @@
7677
#include <WebCore/RenderElement.h>
7778
#include <WebCore/ScriptController.h>
7879
#include <wtf/StdLibExtras.h>
80+
#include <wtf/text/StringToIntegerConversion.h>
7981
#include <wtf/TZoneMallocInlines.h>
8082
#include <wtf/UUID.h>
8183

@@ -383,6 +385,48 @@ WebCore::AccessibilityObject* WebAutomationSessionProxy::getAccessibilityObjectF
383385
return nullptr;
384386
}
385387

388+
WebCore::AccessibilityObject* WebAutomationSessionProxy::getAccessibilityObjectForAXNode(WebCore::PageIdentifier pageID, String accessibilityNodeHandle, String& errorType)
389+
{
390+
RefPtr page = WebProcess::singleton().webPage(pageID);
391+
if (!page) {
392+
errorType = Inspector::Protocol::AutomationHelpers::getEnumConstantValue(Inspector::Protocol::Automation::ErrorMessage::WindowNotFound);
393+
return nullptr;
394+
}
395+
396+
WeakPtr frame = &page->mainWebFrame();
397+
if (!frame) {
398+
errorType = Inspector::Protocol::AutomationHelpers::getEnumConstantValue(Inspector::Protocol::Automation::ErrorMessage::WindowNotFound);
399+
return nullptr;
400+
}
401+
ASSERT(frame->coreLocalFrame());
402+
if (!frame->coreLocalFrame()->view()) {
403+
errorType = Inspector::Protocol::AutomationHelpers::getEnumConstantValue(Inspector::Protocol::Automation::ErrorMessage::WindowNotFound);
404+
return nullptr;
405+
}
406+
407+
WebCore::AXObjectCache::enableAccessibility();
408+
409+
if (CheckedPtr axObjectCache = protect(frame->coreLocalFrame()->document()->axObjectCache())) {
410+
// Force a layout and cache update. If we don't, and this request has come in before the render tree was built,
411+
// the accessibility object for this element will not be created (because it doesn't yet have its renderer).
412+
axObjectCache->performDeferredCacheUpdate(ForceLayout::Yes);
413+
414+
auto parsedAXID = parseInteger<uint64_t>(accessibilityNodeHandle);
415+
if (!parsedAXID) {
416+
errorType = Inspector::Protocol::AutomationHelpers::getEnumConstantValue(
417+
Inspector::Protocol::Automation::ErrorMessage::NodeNotFound);
418+
return nullptr;
419+
}
420+
auto axID = WebCore::AXID { *parsedAXID };
421+
422+
if (auto* axObject = axObjectCache->objectForID(axID))
423+
return axObject;
424+
}
425+
426+
errorType = Inspector::Protocol::AutomationHelpers::getEnumConstantValue(Inspector::Protocol::Automation::ErrorMessage::InternalError);
427+
return nullptr;
428+
}
429+
386430
void WebAutomationSessionProxy::ensureObserverForFrame(WebFrame& frame)
387431
{
388432
// If the frame and LocalDOMWindow have become disconnected, then frame is already being destroyed
@@ -912,6 +956,59 @@ void WebAutomationSessionProxy::getComputedLabel(WebCore::PageIdentifier pageID,
912956
completionHandler(std::nullopt, axObject->computedLabel());
913957
}
914958

959+
static WebAutomationSessionProxy::ComputedAXProperties getComputedAccessibilityProperties(WebCore::AccessibilityObject& axObject)
960+
{
961+
String accessibilityNodeId = String::number(axObject.objectID().toUInt64());
962+
String role = axObject.computedRoleString();
963+
String label = axObject.computedLabel();
964+
965+
String isChecked;
966+
if (axObject.supportsCheckedState())
967+
isChecked = axObject.isChecked() ? "true"_s : "false"_s;
968+
969+
String isPressed;
970+
if (axObject.isToggleButton())
971+
isPressed = axObject.isPressed() ? "true"_s : "false"_s;
972+
973+
String parentAXID;
974+
if (auto* parent = axObject.parentObject())
975+
parentAXID = String::number(parent->objectID().toUInt64());
976+
977+
Vector<String> childrenAXIDs;
978+
for (auto& child : axObject.stitchedUnignoredChildren())
979+
childrenAXIDs.append(String::number(child->objectID().toUInt64()));
980+
981+
return { accessibilityNodeId, role, label, isChecked, isPressed, parentAXID, WTF::move(childrenAXIDs) };
982+
}
983+
984+
void WebAutomationSessionProxy::getAccessibilityPropertiesForElement(WebCore::PageIdentifier pageID, std::optional<WebCore::FrameIdentifier> frameID, String nodeHandle, CompletionHandler<void(std::optional<String>&&, std::optional<String>&&, std::optional<String>&&, std::optional<String>&&, std::optional<String>&&, std::optional<String>&&, std::optional<String>&&, Vector<String>&&)>&& completionHandler)
985+
{
986+
String errorType;
987+
RefPtr axObject = getAccessibilityObjectForNode(pageID, frameID, nodeHandle, errorType);
988+
989+
if (!errorType.isNull()) {
990+
completionHandler(errorType, std::nullopt, std::nullopt, std::nullopt, std::nullopt, std::nullopt, std::nullopt, Vector<String> { });
991+
return;
992+
}
993+
994+
auto properties = getComputedAccessibilityProperties(*axObject);
995+
completionHandler(std::nullopt, WTF::move(properties.accessibilityNodeId), WTF::move(properties.role), WTF::move(properties.label), WTF::move(properties.checked), WTF::move(properties.pressed), WTF::move(properties.parent), WTF::move(properties.children));
996+
}
997+
998+
void WebAutomationSessionProxy::getAccessibilityPropertiesForAccessibilityNode(WebCore::PageIdentifier pageID, String accessibilityNodeHandle, CompletionHandler<void(std::optional<String>&&, std::optional<String>&&, std::optional<String>&&, std::optional<String>&&, std::optional<String>&&, std::optional<String>&&, std::optional<String>&&, Vector<String>&&)>&& completionHandler)
999+
{
1000+
String errorType;
1001+
RefPtr axObject = getAccessibilityObjectForAXNode(pageID, accessibilityNodeHandle, errorType);
1002+
1003+
if (!errorType.isNull()) {
1004+
completionHandler(errorType, std::nullopt, std::nullopt, std::nullopt, std::nullopt, std::nullopt, std::nullopt, Vector<String> { });
1005+
return;
1006+
}
1007+
1008+
auto properties = getComputedAccessibilityProperties(*axObject);
1009+
completionHandler(std::nullopt, WTF::move(properties.accessibilityNodeId), WTF::move(properties.role), WTF::move(properties.label), WTF::move(properties.checked), WTF::move(properties.pressed), WTF::move(properties.parent), WTF::move(properties.children));
1010+
}
1011+
9151012
void WebAutomationSessionProxy::selectOptionElement(WebCore::PageIdentifier pageID, std::optional<WebCore::FrameIdentifier> frameID, String nodeHandle, CompletionHandler<void(std::optional<String>)>&& completionHandler)
9161013
{
9171014
RefPtr page = WebProcess::singleton().webPage(pageID);

0 commit comments

Comments
 (0)