Title: [287387] trunk
Revision
287387
Author
[email protected]
Date
2021-12-23 00:53:38 -0800 (Thu, 23 Dec 2021)

Log Message

[GTK][a11y] WTR: add support for notifications when building with ATSPI
https://bugs.webkit.org/show_bug.cgi?id=234550

Reviewed by Adrian Perez de Castro.

Source/WebCore:

Add private API for WTR notifications.

* accessibility/atspi/AccessibilityAtspi.cpp:
(WebCore::AccessibilityAtspi::childrenChanged):
(WebCore::AccessibilityAtspi::stateChanged):
(WebCore::AccessibilityAtspi::textChanged):
(WebCore::AccessibilityAtspi::textCaretMoved):
(WebCore::AccessibilityAtspi::valueChanged):
(WebCore::AccessibilityAtspi::selectionChanged):
(WebCore::AccessibilityAtspi::loadEvent):
(WebCore::AccessibilityAtspi::addNotificationObserver):
(WebCore::AccessibilityAtspi::removeNotificationObserver):
(WebCore::AccessibilityAtspi::notifyStateChanged const):
(WebCore::AccessibilityAtspi::notifySelectionChanged const):
(WebCore::AccessibilityAtspi::notifyTextChanged const):
(WebCore::AccessibilityAtspi::notifyTextCaretMoved const):
(WebCore::AccessibilityAtspi::notifyChildrenChanged const):
(WebCore::AccessibilityAtspi::notifyValueChanged const):
(WebCore::AccessibilityAtspi::notifyLoadEvent const):
* accessibility/atspi/AccessibilityAtspi.h:

Tools:

Add AccessibilityNotificationHandler class to handle the ATSPI notifications.

* WebKitTestRunner/InjectedBundle/AccessibilityController.cpp:
* WebKitTestRunner/InjectedBundle/AccessibilityController.h:
* WebKitTestRunner/InjectedBundle/AccessibilityUIElement.h:
* WebKitTestRunner/InjectedBundle/atspi/AccessibilityControllerAtspi.cpp:
(WTR::AccessibilityController::resetToConsistentState): Remove the global event listener if there's one active.
(WTR::AccessibilityController::addNotificationListener): Create a global event listener.
(WTR::AccessibilityController::removeNotificationListener): Remove the global event listener.
* WebKitTestRunner/InjectedBundle/atspi/AccessibilityNotificationHandler.cpp: Added.
(WTR::AccessibilityNotificationHandler::AccessibilityNotificationHandler):
(WTR::AccessibilityNotificationHandler::~AccessibilityNotificationHandler):
* WebKitTestRunner/InjectedBundle/atspi/AccessibilityNotificationHandler.h: Added.
* WebKitTestRunner/InjectedBundle/atspi/AccessibilityUIElementAtspi.cpp:
(WTR::AccessibilityUIElement::addNotificationListener): Create the element event listener.
(WTR::AccessibilityUIElement::removeNotificationListener): Remove the element event listener.
* WebKitTestRunner/PlatformGTK.cmake:

Modified Paths

Added Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (287386 => 287387)


--- trunk/Source/WebCore/ChangeLog	2021-12-23 08:46:14 UTC (rev 287386)
+++ trunk/Source/WebCore/ChangeLog	2021-12-23 08:53:38 UTC (rev 287387)
@@ -1,3 +1,31 @@
+2021-12-23  Carlos Garcia Campos  <[email protected]>
+
+        [GTK][a11y] WTR: add support for notifications when building with ATSPI
+        https://bugs.webkit.org/show_bug.cgi?id=234550
+
+        Reviewed by Adrian Perez de Castro.
+
+        Add private API for WTR notifications.
+
+        * accessibility/atspi/AccessibilityAtspi.cpp:
+        (WebCore::AccessibilityAtspi::childrenChanged):
+        (WebCore::AccessibilityAtspi::stateChanged):
+        (WebCore::AccessibilityAtspi::textChanged):
+        (WebCore::AccessibilityAtspi::textCaretMoved):
+        (WebCore::AccessibilityAtspi::valueChanged):
+        (WebCore::AccessibilityAtspi::selectionChanged):
+        (WebCore::AccessibilityAtspi::loadEvent):
+        (WebCore::AccessibilityAtspi::addNotificationObserver):
+        (WebCore::AccessibilityAtspi::removeNotificationObserver):
+        (WebCore::AccessibilityAtspi::notifyStateChanged const):
+        (WebCore::AccessibilityAtspi::notifySelectionChanged const):
+        (WebCore::AccessibilityAtspi::notifyTextChanged const):
+        (WebCore::AccessibilityAtspi::notifyTextCaretMoved const):
+        (WebCore::AccessibilityAtspi::notifyChildrenChanged const):
+        (WebCore::AccessibilityAtspi::notifyValueChanged const):
+        (WebCore::AccessibilityAtspi::notifyLoadEvent const):
+        * accessibility/atspi/AccessibilityAtspi.h:
+
 2021-12-23  Philippe Normand  <[email protected]>
 
         [GStreamer] test fast/mediastream/get-display-media-settings.html fails

Modified: trunk/Source/WebCore/accessibility/atspi/AccessibilityAtspi.cpp (287386 => 287387)


--- trunk/Source/WebCore/accessibility/atspi/AccessibilityAtspi.cpp	2021-12-23 08:46:14 UTC (rev 287386)
+++ trunk/Source/WebCore/accessibility/atspi/AccessibilityAtspi.cpp	2021-12-23 08:53:38 UTC (rev 287387)
@@ -345,6 +345,11 @@
 void AccessibilityAtspi::childrenChanged(AccessibilityObjectAtspi& atspiObject, AccessibilityObjectAtspi& child, ChildrenChanged change)
 {
     RELEASE_ASSERT(isMainThread());
+
+#if ENABLE(DEVELOPER_MODE)
+    notifyChildrenChanged(atspiObject, child, change);
+#endif
+
     m_queue->dispatch([this, atspiObject = Ref { atspiObject }, child = Ref { child }, change] {
         if (!m_connection)
             return;
@@ -362,6 +367,11 @@
 void AccessibilityAtspi::stateChanged(AccessibilityObjectAtspi& atspiObject, const char* name, bool value)
 {
     RELEASE_ASSERT(isMainThread());
+
+#if ENABLE(DEVELOPER_MODE)
+    notifyStateChanged(atspiObject, name, value);
+#endif
+
     m_queue->dispatch([this, atspiObject = Ref { atspiObject }, name = CString(name), value] {
         if (!m_connection)
             return;
@@ -377,6 +387,11 @@
 void AccessibilityAtspi::textChanged(AccessibilityObjectAtspi& atspiObject, const char* changeType, CString&& text, unsigned offset, unsigned length)
 {
     RELEASE_ASSERT(isMainThread());
+
+#if ENABLE(DEVELOPER_MODE)
+    notifyTextChanged(atspiObject);
+#endif
+
     m_queue->dispatch([this, atspiObject = Ref { atspiObject }, changeType = CString(changeType), text = WTFMove(text), offset, length] {
         if (!m_connection)
             return;
@@ -407,6 +422,11 @@
 void AccessibilityAtspi::textCaretMoved(AccessibilityObjectAtspi& atspiObject, unsigned caretOffset)
 {
     RELEASE_ASSERT(isMainThread());
+
+#if ENABLE(DEVELOPER_MODE)
+    notifyTextCaretMoved(atspiObject, caretOffset);
+#endif
+
     m_queue->dispatch([this, atspiObject = Ref { atspiObject }, caretOffset] {
         if (!m_connection)
             return;
@@ -437,6 +457,11 @@
 void AccessibilityAtspi::valueChanged(AccessibilityObjectAtspi& atspiObject, double value)
 {
     RELEASE_ASSERT(isMainThread());
+
+#if ENABLE(DEVELOPER_MODE)
+    notifyValueChanged(atspiObject);
+#endif
+
     m_queue->dispatch([this, atspiObject = Ref { atspiObject }, value] {
         if (!m_connection)
             return;
@@ -452,6 +477,11 @@
 void AccessibilityAtspi::selectionChanged(AccessibilityObjectAtspi& atspiObject)
 {
     RELEASE_ASSERT(isMainThread());
+
+#if ENABLE(DEVELOPER_MODE)
+    notifySelectionChanged(atspiObject);
+#endif
+
     m_queue->dispatch([this, atspiObject = Ref { atspiObject }] {
         if (!m_connection)
             return;
@@ -467,6 +497,11 @@
 void AccessibilityAtspi::loadEvent(AccessibilityObjectAtspi& atspiObject, CString&& event)
 {
     RELEASE_ASSERT(isMainThread());
+
+#if ENABLE(DEVELOPER_MODE)
+    notifyLoadEvent(atspiObject, event);
+#endif
+
     m_queue->dispatch([this, atspiObject = Ref { atspiObject }, event = WTFMove(event)] {
         if (!m_connection)
             return;
@@ -713,6 +748,99 @@
 
 } // namespace Accessibility
 
+#if ENABLE(DEVELOPER_MODE)
+void AccessibilityAtspi::addNotificationObserver(void* context, NotificationObserver&& observer)
+{
+    m_notificationObservers.add(context, WTFMove(observer));
+}
+
+void AccessibilityAtspi::removeNotificationObserver(void* context)
+{
+    m_notificationObservers.remove(context);
+}
+
+void AccessibilityAtspi::notifyStateChanged(AccessibilityObjectAtspi& atspiObject, const char* name, bool value) const
+{
+    if (m_notificationObservers.isEmpty())
+        return;
+
+    auto notificationName = [&](const char* name) -> const char* {
+        if (!g_strcmp0(name, "checked"))
+            return "CheckedStateChanged";
+        if (!g_strcmp0(name, "invalid-entry"))
+            return "AXInvalidStatusChanged";
+        if (!g_strcmp0(name, "active"))
+            return "ActiveStateChanged";
+        if (!g_strcmp0(name, "busy"))
+            return "AXElementBusyChanged";
+        if (!g_strcmp0(name, "enabled"))
+            return "AXDisabledStateChanged";
+        if (!g_strcmp0(name, "expanded"))
+            return "AXExpandedChanged";
+        if (!g_strcmp0(name, "pressed"))
+            return "AXPressedStateChanged";
+        if (!g_strcmp0(name, "read-only"))
+            return "AXReadOnlyStatusChanged";
+        if (!g_strcmp0(name, "required"))
+            return "AXRequiredStatusChanged";
+        if (!g_strcmp0(name, "sensitive"))
+            return "AXSensitiveStateChanged";
+        if (!g_strcmp0(name, "focused") && value)
+            return "AXFocusedUIElementChanged";
+
+        return nullptr;
+    };
+
+    const char* notification = notificationName(name);
+    if (!notification)
+        return;
+
+    for (const auto& observer : m_notificationObservers.values())
+        observer(atspiObject, notification, value);
+}
+
+void AccessibilityAtspi::notifySelectionChanged(AccessibilityObjectAtspi& atspiObject) const
+{
+    for (const auto& observer : m_notificationObservers.values())
+        observer(atspiObject, "AXSelectedChildrenChanged", nullptr);
+}
+
+void AccessibilityAtspi::notifyTextChanged(AccessibilityObjectAtspi& atspiObject) const
+{
+    for (const auto& observer : m_notificationObservers.values())
+        observer(atspiObject, "AXTextChanged", nullptr);
+}
+
+void AccessibilityAtspi::notifyTextCaretMoved(AccessibilityObjectAtspi& atspiObject, unsigned caretOffset) const
+{
+    for (const auto& observer : m_notificationObservers.values())
+        observer(atspiObject, "AXTextCaretMoved", caretOffset);
+}
+
+void AccessibilityAtspi::notifyChildrenChanged(AccessibilityObjectAtspi& atspiObject, AccessibilityObjectAtspi& child, ChildrenChanged change) const
+{
+    const char* notification = change == ChildrenChanged::Added ? "AXChildrenAdded" : "AXChildrenRemoved";
+    for (const auto& observer : m_notificationObservers.values())
+        observer(atspiObject, notification, child);
+}
+
+void AccessibilityAtspi::notifyValueChanged(AccessibilityObjectAtspi& atspiObject) const
+{
+    for (const auto& observer : m_notificationObservers.values())
+        observer(atspiObject, "AXValueChanged", nullptr);
+}
+
+void AccessibilityAtspi::notifyLoadEvent(AccessibilityObjectAtspi& atspiObject, const CString& event) const
+{
+    if (event != "LoadComplete")
+        return;
+
+    for (const auto& observer : m_notificationObservers.values())
+        observer(atspiObject, "AXLoadComplete", nullptr);
+}
+
+#endif
+
 } // namespace WebCore
 
 #endif // ENABLE(ACCESSIBILITY) && USE(ATSPI)

Modified: trunk/Source/WebCore/accessibility/atspi/AccessibilityAtspi.h (287386 => 287387)


--- trunk/Source/WebCore/accessibility/atspi/AccessibilityAtspi.h	2021-12-23 08:46:14 UTC (rev 287386)
+++ trunk/Source/WebCore/accessibility/atspi/AccessibilityAtspi.h	2021-12-23 08:53:38 UTC (rev 287387)
@@ -78,6 +78,13 @@
 
     void addAccessible(AccessibilityObjectAtspi&);
 
+#if ENABLE(DEVELOPER_MODE)
+    using NotificationObserverParameter = std::variant<std::nullptr_t, String, bool, unsigned, Ref<AccessibilityObjectAtspi>>;
+    using NotificationObserver = Function<void(AccessibilityObjectAtspi&, const char*, NotificationObserverParameter)>;
+    WEBCORE_EXPORT void addNotificationObserver(void*, NotificationObserver&&);
+    WEBCORE_EXPORT void removeNotificationObserver(void*);
+#endif
+
 private:
     void registerTrees() const;
     void initializeRegistry();
@@ -89,6 +96,16 @@
 
     bool shouldEmitSignal(const char* interface, const char* name, const char* detail = "");
 
+#if ENABLE(DEVELOPER_MODE)
+    void notifyStateChanged(AccessibilityObjectAtspi&, const char*, bool) const;
+    void notifySelectionChanged(AccessibilityObjectAtspi&) const;
+    void notifyTextChanged(AccessibilityObjectAtspi&) const;
+    void notifyTextCaretMoved(AccessibilityObjectAtspi&, unsigned) const;
+    void notifyChildrenChanged(AccessibilityObjectAtspi&, AccessibilityObjectAtspi&, ChildrenChanged) const;
+    void notifyValueChanged(AccessibilityObjectAtspi&) const;
+    void notifyLoadEvent(AccessibilityObjectAtspi&, const CString&) const;
+#endif
+
     static GDBusInterfaceVTable s_cacheFunctions;
 
     Ref<WorkQueue> m_queue;
@@ -101,6 +118,9 @@
     unsigned m_cacheID { 0 };
     HashMap<String, AccessibilityObjectAtspi*> m_cache;
     bool m_inGetItems { false };
+#if ENABLE(DEVELOPER_MODE)
+    HashMap<void*, NotificationObserver> m_notificationObservers;
+#endif
 };
 
 } // namespace WebCore

Modified: trunk/Tools/ChangeLog (287386 => 287387)


--- trunk/Tools/ChangeLog	2021-12-23 08:46:14 UTC (rev 287386)
+++ trunk/Tools/ChangeLog	2021-12-23 08:53:38 UTC (rev 287387)
@@ -1,3 +1,28 @@
+2021-12-23  Carlos Garcia Campos  <[email protected]>
+
+        [GTK][a11y] WTR: add support for notifications when building with ATSPI
+        https://bugs.webkit.org/show_bug.cgi?id=234550
+
+        Reviewed by Adrian Perez de Castro.
+
+        Add AccessibilityNotificationHandler class to handle the ATSPI notifications.
+
+        * WebKitTestRunner/InjectedBundle/AccessibilityController.cpp:
+        * WebKitTestRunner/InjectedBundle/AccessibilityController.h:
+        * WebKitTestRunner/InjectedBundle/AccessibilityUIElement.h:
+        * WebKitTestRunner/InjectedBundle/atspi/AccessibilityControllerAtspi.cpp:
+        (WTR::AccessibilityController::resetToConsistentState): Remove the global event listener if there's one active.
+        (WTR::AccessibilityController::addNotificationListener): Create a global event listener.
+        (WTR::AccessibilityController::removeNotificationListener): Remove the global event listener.
+        * WebKitTestRunner/InjectedBundle/atspi/AccessibilityNotificationHandler.cpp: Added.
+        (WTR::AccessibilityNotificationHandler::AccessibilityNotificationHandler):
+        (WTR::AccessibilityNotificationHandler::~AccessibilityNotificationHandler):
+        * WebKitTestRunner/InjectedBundle/atspi/AccessibilityNotificationHandler.h: Added.
+        * WebKitTestRunner/InjectedBundle/atspi/AccessibilityUIElementAtspi.cpp:
+        (WTR::AccessibilityUIElement::addNotificationListener): Create the element event listener.
+        (WTR::AccessibilityUIElement::removeNotificationListener): Remove the element event listener.
+        * WebKitTestRunner/PlatformGTK.cmake:
+
 2021-12-22  Alex Christensen  <[email protected]>
 
         Re-enable WebPushD.HandleInjectedPush API test

Modified: trunk/Tools/WebKitTestRunner/InjectedBundle/AccessibilityController.cpp (287386 => 287387)


--- trunk/Tools/WebKitTestRunner/InjectedBundle/AccessibilityController.cpp	2021-12-23 08:46:14 UTC (rev 287386)
+++ trunk/Tools/WebKitTestRunner/InjectedBundle/AccessibilityController.cpp	2021-12-23 08:53:38 UTC (rev 287387)
@@ -36,6 +36,10 @@
 #include <WebKit/WKBundlePage.h>
 #include <WebKit/WKBundlePagePrivate.h>
 
+#if USE(ATSPI)
+#include "AccessibilityNotificationHandler.h"
+#endif
+
 namespace WTR {
 
 Ref<AccessibilityController> AccessibilityController::create()

Modified: trunk/Tools/WebKitTestRunner/InjectedBundle/AccessibilityController.h (287386 => 287387)


--- trunk/Tools/WebKitTestRunner/InjectedBundle/AccessibilityController.h	2021-12-23 08:46:14 UTC (rev 287386)
+++ trunk/Tools/WebKitTestRunner/InjectedBundle/AccessibilityController.h	2021-12-23 08:53:38 UTC (rev 287387)
@@ -44,6 +44,9 @@
 namespace WTR {
 
 class AccessibilityUIElement;
+#if USE(ATSPI)
+class AccessibilityNotificationHandler;
+#endif
 
 class AccessibilityController : public JSWrappable {
 public:
@@ -99,6 +102,8 @@
     RetainPtr<id> m_globalNotificationHandler;
 #elif USE(ATK)
     RefPtr<AccessibilityNotificationHandler> m_globalNotificationHandler;
+#elif USE(ATSPI)
+    std::unique_ptr<AccessibilityNotificationHandler> m_globalNotificationHandler;
 #endif
 
 #if ENABLE(ACCESSIBILITY_ISOLATED_TREE)

Modified: trunk/Tools/WebKitTestRunner/InjectedBundle/AccessibilityUIElement.h (287386 => 287387)


--- trunk/Tools/WebKitTestRunner/InjectedBundle/AccessibilityUIElement.h	2021-12-23 08:46:14 UTC (rev 287386)
+++ trunk/Tools/WebKitTestRunner/InjectedBundle/AccessibilityUIElement.h	2021-12-23 08:53:38 UTC (rev 287387)
@@ -59,6 +59,9 @@
 namespace WTR {
 
 class AccessibilityController;
+#if USE(ATSPI)
+class AccessibilityNotificationHandler;
+#endif
 
 class AccessibilityUIElement : public JSWrappable {
 #if PLATFORM(COCOA)
@@ -435,6 +438,7 @@
 #elif USE(ATSPI)
     static RefPtr<AccessibilityController> s_controller;
     RefPtr<WebCore::AccessibilityObjectAtspi> m_element;
+    std::unique_ptr<AccessibilityNotificationHandler> m_notificationHandler;
 #endif
 #endif
 };

Modified: trunk/Tools/WebKitTestRunner/InjectedBundle/atspi/AccessibilityControllerAtspi.cpp (287386 => 287387)


--- trunk/Tools/WebKitTestRunner/InjectedBundle/atspi/AccessibilityControllerAtspi.cpp	2021-12-23 08:46:14 UTC (rev 287386)
+++ trunk/Tools/WebKitTestRunner/InjectedBundle/atspi/AccessibilityControllerAtspi.cpp	2021-12-23 08:53:38 UTC (rev 287387)
@@ -29,6 +29,7 @@
 #include "AccessibilityController.h"
 
 #if HAVE(ACCESSIBILITY) && USE(ATSPI)
+#include "AccessibilityNotificationHandler.h"
 #include "AccessibilityUIElement.h"
 #include "InjectedBundle.h"
 #include "InjectedBundlePage.h"
@@ -41,6 +42,8 @@
 
 void AccessibilityController::resetToConsistentState()
 {
+    if (m_globalNotificationHandler)
+        removeNotificationListener();
 }
 
 static WebCore::AccessibilityObjectAtspi* findAccessibleObjectById(WebCore::AccessibilityObjectAtspi& axObject, const String& elementID)
@@ -105,12 +108,21 @@
 
 bool AccessibilityController::addNotificationListener(JSValueRef functionCallback)
 {
+    if (!functionCallback)
+        return false;
+
+    if (m_globalNotificationHandler)
+        return false;
+
+    m_globalNotificationHandler = makeUnique<AccessibilityNotificationHandler>(functionCallback);
     return true;
 }
 
 bool AccessibilityController::removeNotificationListener()
 {
-    return false;
+    ASSERT(m_globalNotificationHandler);
+    m_globalNotificationHandler = nullptr;
+    return true;
 }
 
 void AccessibilityController::updateIsolatedTreeMode()

Added: trunk/Tools/WebKitTestRunner/InjectedBundle/atspi/AccessibilityNotificationHandler.cpp (0 => 287387)


--- trunk/Tools/WebKitTestRunner/InjectedBundle/atspi/AccessibilityNotificationHandler.cpp	                        (rev 0)
+++ trunk/Tools/WebKitTestRunner/InjectedBundle/atspi/AccessibilityNotificationHandler.cpp	2021-12-23 08:53:38 UTC (rev 287387)
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2021 Igalia S.L.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "AccessibilityNotificationHandler.h"
+
+#if HAVE(ACCESSIBILITY) && USE(ATSPI)
+#include "InjectedBundlePage.h"
+#include "JSWrapper.h"
+#include <_javascript_Core/OpaqueJSString.h>
+#include <WebCore/AccessibilityObjectAtspi.h>
+#include <WebCore/AccessibilityRootAtspi.h>
+#include <WebKit/WKBundleFrame.h>
+#include <WebKit/WKBundlePage.h>
+#include <WebKit/WKBundlePagePrivate.h>
+
+namespace WTR {
+
+AccessibilityNotificationHandler::AccessibilityNotificationHandler(JSValueRef callback, PlatformUIElement element)
+    : m_callback(callback)
+    , m_element(element)
+{
+    WKBundlePageRef page = InjectedBundle::singleton().page()->page();
+    WKBundleFrameRef mainFrame = WKBundlePageGetMainFrame(page);
+    JSContextRef jsContext = WKBundleFrameGetJavaScriptContext(mainFrame);
+    JSValueProtect(jsContext, m_callback);
+
+    auto& atspi = m_element ? m_element->root().atspi() : static_cast<WebCore::AccessibilityObjectAtspi*>(WKAccessibilityRootObject(page))->root().atspi();
+    atspi.addNotificationObserver(this, [this](WebCore::AccessibilityObjectAtspi& element, const char* notificationName, WebCore::AccessibilityAtspi::NotificationObserverParameter parameter) {
+        if (m_element && m_element.get() != &element)
+            return;
+
+        WKBundleFrameRef mainFrame = WKBundlePageGetMainFrame(InjectedBundle::singleton().page()->page());
+        JSContextRef jsContext = WKBundleFrameGetJavaScriptContext(mainFrame);
+
+        JSRetainPtr<JSStringRef> jsNotificationEventName(Adopt, JSStringCreateWithUTF8CString(notificationName));
+        JSValueRef jsParameter = WTF::switchOn(parameter,
+            [&](String& stringValue) -> JSValueRef {
+                JSRetainPtr<JSStringRef> jsStringValue(Adopt, OpaqueJSString::tryCreate(stringValue).get());
+                return JSValueMakeString(jsContext, jsStringValue.get());
+            },
+            [&](bool& boolValue) -> JSValueRef {
+                return JSValueMakeBoolean(jsContext, boolValue);
+            },
+            [&](unsigned& unsignedValue) -> JSValueRef {
+                return JSValueMakeNumber(jsContext, unsignedValue);
+            },
+            [&](Ref<WebCore::AccessibilityObjectAtspi>& elementValue) -> JSValueRef {
+                return toJS(jsContext, AccessibilityUIElement::create(elementValue.ptr()).ptr());
+            },
+            [&](auto&) -> JSValueRef {
+                return JSValueMakeUndefined(jsContext);
+            });
+
+        if (m_element) {
+            // Listener for one element gets the notification name parameter.
+            JSValueRef arguments[2];
+            arguments[0] = JSValueMakeString(jsContext, jsNotificationEventName.get());
+            arguments[1] = jsParameter;
+            JSObjectCallAsFunction(jsContext, const_cast<JSObjectRef>(m_callback), 0, 2, arguments, 0);
+        } else {
+            // A global listener gets the element, notification name and parameter.
+            JSValueRef arguments[3];
+            arguments[0] = toJS(jsContext, AccessibilityUIElement::create(&element).ptr());
+            arguments[1] = JSValueMakeString(jsContext, jsNotificationEventName.get());
+            arguments[2] = jsParameter;
+            JSObjectCallAsFunction(jsContext, const_cast<JSObjectRef>(m_callback), 0, 3, arguments, 0);
+        }
+    });
+}
+
+AccessibilityNotificationHandler::~AccessibilityNotificationHandler()
+{
+    WKBundlePageRef page = InjectedBundle::singleton().page()->page();
+    auto& atspi = m_element ? m_element->root().atspi() : static_cast<WebCore::AccessibilityObjectAtspi*>(WKAccessibilityRootObject(page))->root().atspi();
+    atspi.removeNotificationObserver(this);
+
+    WKBundleFrameRef mainFrame = WKBundlePageGetMainFrame(page);
+    JSContextRef jsContext = WKBundleFrameGetJavaScriptContext(mainFrame);
+    JSValueUnprotect(jsContext, m_callback);
+}
+
+} // namespace WTR
+
+#endif // HAVE(ACCESSIBILITY) && USE(ATSPI)

Added: trunk/Tools/WebKitTestRunner/InjectedBundle/atspi/AccessibilityNotificationHandler.h (0 => 287387)


--- trunk/Tools/WebKitTestRunner/InjectedBundle/atspi/AccessibilityNotificationHandler.h	                        (rev 0)
+++ trunk/Tools/WebKitTestRunner/InjectedBundle/atspi/AccessibilityNotificationHandler.h	2021-12-23 08:53:38 UTC (rev 287387)
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2021 Igalia S.L.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#if HAVE(ACCESSIBILITY) && USE(ATSPI)
+
+#include "AccessibilityUIElement.h"
+#include <_javascript_Core/JSObjectRef.h>
+#include <wtf/FastMalloc.h>
+
+namespace WTR {
+
+class AccessibilityNotificationHandler {
+    WTF_MAKE_FAST_ALLOCATED;
+public:
+    explicit AccessibilityNotificationHandler(JSValueRef, PlatformUIElement = nullptr);
+    ~AccessibilityNotificationHandler();
+
+private:
+    JSValueRef m_callback;
+    RefPtr<WebCore::AccessibilityObjectAtspi> m_element;
+};
+
+} // namespace WTR
+
+#endif // HAVE(ACCESSIBILITY) && USE(ATSPI)

Modified: trunk/Tools/WebKitTestRunner/InjectedBundle/atspi/AccessibilityUIElementAtspi.cpp (287386 => 287387)


--- trunk/Tools/WebKitTestRunner/InjectedBundle/atspi/AccessibilityUIElementAtspi.cpp	2021-12-23 08:46:14 UTC (rev 287386)
+++ trunk/Tools/WebKitTestRunner/InjectedBundle/atspi/AccessibilityUIElementAtspi.cpp	2021-12-23 08:53:38 UTC (rev 287387)
@@ -27,6 +27,7 @@
 #include "AccessibilityUIElement.h"
 
 #if HAVE(ACCESSIBILITY) && USE(ATSPI)
+#include "AccessibilityNotificationHandler.h"
 #include "InjectedBundle.h"
 #include "InjectedBundlePage.h"
 #include <_javascript_Core/JSStringRef.h>
@@ -1321,11 +1322,20 @@
 
 bool AccessibilityUIElement::addNotificationListener(JSValueRef functionCallback)
 {
-    return false;
+    if (!functionCallback)
+        return false;
+
+    if (m_notificationHandler)
+        return false;
+
+    m_notificationHandler = makeUnique<AccessibilityNotificationHandler>(functionCallback, m_element.get());
+    return true;
 }
 
 bool AccessibilityUIElement::removeNotificationListener()
 {
+    ASSERT(m_notificationHandler);
+    m_notificationHandler = nullptr;
     return true;
 }
 

Modified: trunk/Tools/WebKitTestRunner/PlatformGTK.cmake (287386 => 287387)


--- trunk/Tools/WebKitTestRunner/PlatformGTK.cmake	2021-12-23 08:46:14 UTC (rev 287386)
+++ trunk/Tools/WebKitTestRunner/PlatformGTK.cmake	2021-12-23 08:53:38 UTC (rev 287387)
@@ -45,6 +45,7 @@
     InjectedBundle/atk/AccessibilityUIElementAtk.cpp
 
     InjectedBundle/atspi/AccessibilityControllerAtspi.cpp
+    InjectedBundle/atspi/AccessibilityNotificationHandler.cpp
     InjectedBundle/atspi/AccessibilityUIElementAtspi.cpp
 
     InjectedBundle/gtk/ActivateFontsGtk.cpp
@@ -57,6 +58,7 @@
     ${ATK_INCLUDE_DIRS}
     ${GLIB_INCLUDE_DIRS}
     ${WebKitTestRunner_DIR}/InjectedBundle/atk
+    ${WebKitTestRunner_DIR}/InjectedBundle/atspi
     ${WebKitTestRunner_DIR}/InjectedBundle/gtk
 )
 
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to