Title: [252609] trunk
Revision
252609
Author
[email protected]
Date
2019-11-18 17:12:00 -0800 (Mon, 18 Nov 2019)

Log Message

Run AccessibilityController::rootElement on secondary thread to simulate HIServices during LayoutTests.
https://bugs.webkit.org/show_bug.cgi?id=204226

Reviewed by Chris Fleizach.

Source/WebCore:

No new tests, no new functionality.

Added AXObjectCahce::canUseSecondaryAXThread to support
WTR::AccessibilityController spawning of a secondary thread to simulate
execution of isolated tree code.

* accessibility/AXObjectCache.cpp:
(WebCore::AXObjectCache::canUseSecondaryAXThread):
* accessibility/AXObjectCache.h:

Source/WebKit:

Added WKAccessibilityCanUseSecondaryAXThread to support
WTR::AccessibilityController spawning of a secondary thread to simulate
execution of isolated tree code.

* WebProcess/InjectedBundle/API/c/WKBundlePage.cpp:
(WKAccessibilityCanUseSecondaryAXThread):
* WebProcess/InjectedBundle/API/c/WKBundlePagePrivate.h:

Tools:

HIServices _AXUIElementUseSecondaryAXThread and _AXUIElementRequestServicedBySecondaryAXThread
do not work for WebKitTestRunner since this is calling directly into
WebCore/accessibility via _javascript_ without going through HIServices.
Thus to simulate the behavior of HIServices, AccessibilityController is
spawning a secondary thread to service the _javascript_ requests.
The very first request needs to be serviced in the main thread,
and all subsequent requests in the secondary thread. this is what
the behavior would be if using HIServices.
Once the IsolatedTree would be enabled, the first request has to be
served in the main thread in order to build the AXIsolatedTree.

* WebKitTestRunner/InjectedBundle/AccessibilityController.cpp:
(WTR::AccessibilityController::rootElement):
(WTR::AXThread::AXThread):
(WTR::AXThread::isCurrentThread):
(WTR::AXThread::dispatch):
(WTR::AXThread::dispatchBarrier):
(WTR::AXThread::singleton):
(WTR::AXThread::createThreadIfNeeded):
(WTR::AXThread::dispatchFunctionsFromAXThread):
(WTR::AXThread::initializeRunLoop):
(WTR::AXThread::wakeUpRunLoop):
(WTR::AXThread::threadRunLoopSourceCallback):
* WebKitTestRunner/InjectedBundle/AccessibilityController.h:
* WebKitTestRunner/InjectedBundle/mac/AccessibilityControllerMac.mm:
(WTR::AXThread::initializeRunLoop):
(WTR::AXThread::wakeUpRunLoop):
(WTR::AXThread::threadRunLoopSourceCallback):

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (252608 => 252609)


--- trunk/Source/WebCore/ChangeLog	2019-11-19 01:05:14 UTC (rev 252608)
+++ trunk/Source/WebCore/ChangeLog	2019-11-19 01:12:00 UTC (rev 252609)
@@ -1,3 +1,20 @@
+2019-11-18  Andres Gonzalez  <[email protected]>
+
+        Run AccessibilityController::rootElement on secondary thread to simulate HIServices during LayoutTests.
+        https://bugs.webkit.org/show_bug.cgi?id=204226
+
+        Reviewed by Chris Fleizach.
+
+        No new tests, no new functionality.
+
+        Added AXObjectCahce::canUseSecondaryAXThread to support
+        WTR::AccessibilityController spawning of a secondary thread to simulate
+        execution of isolated tree code.
+
+        * accessibility/AXObjectCache.cpp:
+        (WebCore::AXObjectCache::canUseSecondaryAXThread):
+        * accessibility/AXObjectCache.h:
+
 2019-11-15  Ryosuke Niwa  <[email protected]>
 
         Share more code between WindowEventLoop and WorkerEventLoop by introducing EventLoopTaskGroup

Modified: trunk/Source/WebCore/accessibility/AXObjectCache.cpp (252608 => 252609)


--- trunk/Source/WebCore/accessibility/AXObjectCache.cpp	2019-11-19 01:05:14 UTC (rev 252608)
+++ trunk/Source/WebCore/accessibility/AXObjectCache.cpp	2019-11-19 01:12:00 UTC (rev 252609)
@@ -705,6 +705,21 @@
 }
 #endif
 
+bool AXObjectCache::canUseSecondaryAXThread()
+{
+#if ENABLE(ACCESSIBILITY_ISOLATED_TREE) && PLATFORM(MAC)
+    if (_AXUIElementRequestServicedBySecondaryAXThread())
+        return true;
+
+    // _AXUIElementRequestServicedBySecondaryAXThread returns false for
+    // LayoutTests, but we still want to run LayoutTests using isolated tree on
+    // a secondary thread to simulate the actual execution.
+    return clientSupportsIsolatedTree();
+#else
+    return false;
+#endif
+}
+
 AccessibilityObject* AXObjectCache::rootObjectForFrame(Frame* frame)
 {
     if (!gAccessibilityEnabled)

Modified: trunk/Source/WebCore/accessibility/AXObjectCache.h (252608 => 252609)


--- trunk/Source/WebCore/accessibility/AXObjectCache.h	2019-11-19 01:05:14 UTC (rev 252608)
+++ trunk/Source/WebCore/accessibility/AXObjectCache.h	2019-11-19 01:12:00 UTC (rev 252609)
@@ -200,6 +200,8 @@
 #endif
 
 public:
+    WEBCORE_EXPORT bool canUseSecondaryAXThread();
+
 #if ENABLE(ACCESSIBILITY)
     WEBCORE_EXPORT static void enableAccessibility();
     WEBCORE_EXPORT static void disableAccessibility();

Modified: trunk/Source/WebKit/ChangeLog (252608 => 252609)


--- trunk/Source/WebKit/ChangeLog	2019-11-19 01:05:14 UTC (rev 252608)
+++ trunk/Source/WebKit/ChangeLog	2019-11-19 01:12:00 UTC (rev 252609)
@@ -1,3 +1,18 @@
+2019-11-18  Andres Gonzalez  <[email protected]>
+
+        Run AccessibilityController::rootElement on secondary thread to simulate HIServices during LayoutTests.
+        https://bugs.webkit.org/show_bug.cgi?id=204226
+
+        Reviewed by Chris Fleizach.
+
+        Added WKAccessibilityCanUseSecondaryAXThread to support
+        WTR::AccessibilityController spawning of a secondary thread to simulate
+        execution of isolated tree code.
+
+        * WebProcess/InjectedBundle/API/c/WKBundlePage.cpp:
+        (WKAccessibilityCanUseSecondaryAXThread):
+        * WebProcess/InjectedBundle/API/c/WKBundlePagePrivate.h:
+
 2019-11-18  Chris Dumez  <[email protected]>
 
         Promote main thread assertions related to sendWithAsyncReply() to be release assertions

Modified: trunk/Source/WebKit/WebProcess/InjectedBundle/API/c/WKBundlePage.cpp (252608 => 252609)


--- trunk/Source/WebKit/WebProcess/InjectedBundle/API/c/WKBundlePage.cpp	2019-11-19 01:05:14 UTC (rev 252608)
+++ trunk/Source/WebKit/WebProcess/InjectedBundle/API/c/WKBundlePage.cpp	2019-11-19 01:12:00 UTC (rev 252609)
@@ -282,6 +282,33 @@
 #endif
 }
 
+bool WKAccessibilityCanUseSecondaryAXThread(WKBundlePageRef pageRef)
+{
+#if ENABLE(ACCESSIBILITY)
+    if (!pageRef)
+        return false;
+
+    WebCore::Page* page = WebKit::toImpl(pageRef)->corePage();
+    if (!page)
+        return false;
+
+    WebCore::Frame& core = page->mainFrame();
+    if (!core.document())
+        return false;
+
+    WebCore::AXObjectCache::enableAccessibility();
+
+    auto* axObjectCache = core.document()->axObjectCache();
+    if (!axObjectCache)
+        return false;
+
+    return axObjectCache->canUseSecondaryAXThread();
+#else
+    UNUSED_PARAM(pageRef);
+    return false;
+#endif
+}
+
 void WKAccessibilityEnableEnhancedAccessibility(bool enable)
 {
 #if ENABLE(ACCESSIBILITY)

Modified: trunk/Source/WebKit/WebProcess/InjectedBundle/API/c/WKBundlePagePrivate.h (252608 => 252609)


--- trunk/Source/WebKit/WebProcess/InjectedBundle/API/c/WKBundlePagePrivate.h	2019-11-19 01:05:14 UTC (rev 252608)
+++ trunk/Source/WebKit/WebProcess/InjectedBundle/API/c/WKBundlePagePrivate.h	2019-11-19 01:12:00 UTC (rev 252609)
@@ -96,6 +96,7 @@
 
 WK_EXPORT void* WKAccessibilityRootObject(WKBundlePageRef);
 WK_EXPORT void* WKAccessibilityFocusedObject(WKBundlePageRef);
+WK_EXPORT bool WKAccessibilityCanUseSecondaryAXThread(WKBundlePageRef);
 
 WK_EXPORT void WKAccessibilityEnableEnhancedAccessibility(bool);
 WK_EXPORT bool WKAccessibilityEnhancedAccessibilityEnabled();

Modified: trunk/Tools/ChangeLog (252608 => 252609)


--- trunk/Tools/ChangeLog	2019-11-19 01:05:14 UTC (rev 252608)
+++ trunk/Tools/ChangeLog	2019-11-19 01:12:00 UTC (rev 252609)
@@ -1,3 +1,39 @@
+2019-11-18  Andres Gonzalez  <[email protected]>
+
+        Run AccessibilityController::rootElement on secondary thread to simulate HIServices during LayoutTests.
+        https://bugs.webkit.org/show_bug.cgi?id=204226
+
+        Reviewed by Chris Fleizach.
+
+        HIServices _AXUIElementUseSecondaryAXThread and _AXUIElementRequestServicedBySecondaryAXThread
+        do not work for WebKitTestRunner since this is calling directly into
+        WebCore/accessibility via _javascript_ without going through HIServices.
+        Thus to simulate the behavior of HIServices, AccessibilityController is
+        spawning a secondary thread to service the _javascript_ requests.
+        The very first request needs to be serviced in the main thread,
+        and all subsequent requests in the secondary thread. this is what
+        the behavior would be if using HIServices.
+        Once the IsolatedTree would be enabled, the first request has to be
+        served in the main thread in order to build the AXIsolatedTree.
+
+        * WebKitTestRunner/InjectedBundle/AccessibilityController.cpp:
+        (WTR::AccessibilityController::rootElement):
+        (WTR::AXThread::AXThread):
+        (WTR::AXThread::isCurrentThread):
+        (WTR::AXThread::dispatch):
+        (WTR::AXThread::dispatchBarrier):
+        (WTR::AXThread::singleton):
+        (WTR::AXThread::createThreadIfNeeded):
+        (WTR::AXThread::dispatchFunctionsFromAXThread):
+        (WTR::AXThread::initializeRunLoop):
+        (WTR::AXThread::wakeUpRunLoop):
+        (WTR::AXThread::threadRunLoopSourceCallback):
+        * WebKitTestRunner/InjectedBundle/AccessibilityController.h:
+        * WebKitTestRunner/InjectedBundle/mac/AccessibilityControllerMac.mm:
+        (WTR::AXThread::initializeRunLoop):
+        (WTR::AXThread::wakeUpRunLoop):
+        (WTR::AXThread::threadRunLoopSourceCallback):
+
 2019-11-18  Jonathan Bedard  <[email protected]>
 
         results.webkit.org: Uncollapsed failures shouldn't include runs with no failures

Modified: trunk/Tools/WebKitTestRunner/InjectedBundle/AccessibilityController.cpp (252608 => 252609)


--- trunk/Tools/WebKitTestRunner/InjectedBundle/AccessibilityController.cpp	2019-11-19 01:05:14 UTC (rev 252608)
+++ trunk/Tools/WebKitTestRunner/InjectedBundle/AccessibilityController.cpp	2019-11-19 01:12:00 UTC (rev 252609)
@@ -76,9 +76,25 @@
 Ref<AccessibilityUIElement> AccessibilityController::rootElement()
 {
     WKBundlePageRef page = InjectedBundle::singleton().page()->page();
-    void* root = WKAccessibilityRootObject(page);
-    
-    return AccessibilityUIElement::create(static_cast<PlatformUIElement>(root));    
+    PlatformUIElement root = nullptr;
+
+    if (m_useAXThread) {
+        AXThread::dispatch([&root, page, this] {
+            root = static_cast<PlatformUIElement>(WKAccessibilityRootObject(page));
+            m_semaphore.signal();
+        });
+
+        m_semaphore.wait();
+    } else {
+        root = static_cast<PlatformUIElement>(WKAccessibilityRootObject(page));
+
+        if (WKAccessibilityCanUseSecondaryAXThread(page)) {
+            // Set m_useAXThread to true for next request.
+            m_useAXThread = true;
+        }
+    }
+
+    return AccessibilityUIElement::create(root);
 }
 
 Ref<AccessibilityUIElement> AccessibilityController::focusedElement()
@@ -96,6 +112,102 @@
     return uiElement->elementAtPoint(x, y);
 }
 
+#if PLATFORM(COCOA)
+
+// AXThread implementation
+
+AXThread::AXThread()
+{
+}
+
+bool AXThread::isCurrentThread()
+{
+    return AXThread::singleton().m_thread == &Thread::current();
+}
+
+void AXThread::dispatch(Function<void()>&& function)
+{
+    auto& axThread = AXThread::singleton();
+    axThread.createThreadIfNeeded();
+
+    {
+        std::lock_guard<Lock> lock(axThread.m_functionsMutex);
+        axThread.m_functions.append(WTFMove(function));
+    }
+
+    axThread.wakeUpRunLoop();
+}
+
+void AXThread::dispatchBarrier(Function<void()>&& function)
+{
+    dispatch([function = WTFMove(function)]() mutable {
+        callOnMainThread(WTFMove(function));
+    });
+}
+
+AXThread& AXThread::singleton()
+{
+    static NeverDestroyed<AXThread> axThread;
+    return axThread;
+}
+
+void AXThread::createThreadIfNeeded()
+{
+    // Wait for the thread to initialize the run loop.
+    std::unique_lock<Lock> lock(m_initializeRunLoopMutex);
+
+    if (!m_thread) {
+        m_thread = Thread::create("WKTR: AccessibilityController", [this] {
+            WTF::Thread::setCurrentThreadIsUserInteractive();
+            initializeRunLoop();
+        });
+    }
+
+    m_initializeRunLoopConditionVariable.wait(lock, [this] {
+#if PLATFORM(COCOA)
+        return m_threadRunLoop;
+#else
+        return m_runLoop;
+#endif
+    });
+}
+
+void AXThread::dispatchFunctionsFromAXThread()
+{
+    ASSERT(isCurrentThread());
+
+    Vector<Function<void()>> functions;
+
+    {
+        std::lock_guard<Lock> lock(m_functionsMutex);
+        functions = WTFMove(m_functions);
+    }
+
+    for (auto& function : functions)
+        function();
+}
+
+#if !PLATFORM(MAC)
+NO_RETURN_DUE_TO_ASSERT void AXThread::initializeRunLoop()
+{
+    ASSERT_NOT_REACHED();
+}
+
+void AXThread::wakeUpRunLoop()
+{
+}
+
+void AXThread::threadRunLoopSourceCallback(void*)
+{
+}
+
+void AXThread::threadRunLoopSourceCallback()
+{
+}
+#endif // !PLATFORM(MAC)
+
+#endif // PLATFORM(COCOA)
+
 } // namespace WTR
 #endif // ENABLE(ACCESSIBILITY)
 

Modified: trunk/Tools/WebKitTestRunner/InjectedBundle/AccessibilityController.h (252608 => 252609)


--- trunk/Tools/WebKitTestRunner/InjectedBundle/AccessibilityController.h	2019-11-19 01:05:14 UTC (rev 252608)
+++ trunk/Tools/WebKitTestRunner/InjectedBundle/AccessibilityController.h	2019-11-19 01:12:00 UTC (rev 252609)
@@ -28,8 +28,12 @@
 #include "AccessibilityUIElement.h"
 #include "JSWrappable.h"
 #include <_javascript_Core/JSObjectRef.h>
+#include <wtf/Condition.h>
 #include <wtf/FastMalloc.h>
 #include <wtf/Platform.h>
+#include <wtf/Threading.h>
+#include <wtf/threads/BinarySemaphore.h>
+
 #if USE(ATK)
 #include "AccessibilityNotificationHandlerAtk.h"
 #endif
@@ -82,6 +86,70 @@
 #elif USE(ATK)
     RefPtr<AccessibilityNotificationHandler> m_globalNotificationHandler;
 #endif
+
+#if PLATFORM(COCOA)
+    // _AXUIElementUseSecondaryAXThread and _AXUIElementRequestServicedBySecondaryAXThread
+    // do not work for WebKitTestRunner since this is calling directly into
+    // WebCore/accessibility via _javascript_ without going through HIServices.
+    // Thus to simulate the behavior of HIServices, AccessibilityController is spawning a secondary thread to service the _javascript_ requests.
+    // The following flag allows to run the very first request in the main
+    // thread and all subsequent requests in the secondary thread. this is what
+    // the behavior would be if using HIServices.
+    // The first request has to be served in the main thread in order to build
+    // the AXIsolatedTree.
+    bool m_useAXThread { false };
+    BinarySemaphore m_semaphore;
+#endif
 };
 
+#if PLATFORM(COCOA)
+
+class AXThread {
+    WTF_MAKE_NONCOPYABLE(AXThread);
+
+public:
+    static bool isCurrentThread();
+    static void dispatch(Function<void()>&&);
+
+    // Will dispatch the given function on the main thread once all pending functions
+    // on the AX thread have finished executing. Used for synchronization purposes.
+    static void dispatchBarrier(Function<void()>&&);
+
+private:
+    friend NeverDestroyed<AXThread>;
+
+    AXThread();
+
+    static AXThread& singleton();
+
+    void createThreadIfNeeded();
+    void dispatchFunctionsFromAXThread();
+
+    void initializeRunLoop();
+    void wakeUpRunLoop();
+
+#if PLATFORM(COCOA)
+    static void threadRunLoopSourceCallback(void* AXThread);
+    void threadRunLoopSourceCallback();
+#endif
+
+    RefPtr<Thread> m_thread;
+
+    Condition m_initializeRunLoopConditionVariable;
+    Lock m_initializeRunLoopMutex;
+
+    Lock m_functionsMutex;
+    Vector<Function<void()>> m_functions;
+
+#if PLATFORM(COCOA)
+    // FIXME: We should use WebCore::RunLoop here.
+    RetainPtr<CFRunLoopRef> m_threadRunLoop;
+    RetainPtr<CFRunLoopSourceRef> m_threadRunLoopSource;
+#else
+    RunLoop* m_runLoop { nullptr };
+#endif
+};
+
+#endif // PLATFORM(COCOA)
+
 } // namespace WTR

Modified: trunk/Tools/WebKitTestRunner/InjectedBundle/mac/AccessibilityControllerMac.mm (252608 => 252609)


--- trunk/Tools/WebKitTestRunner/InjectedBundle/mac/AccessibilityControllerMac.mm	2019-11-19 01:05:14 UTC (rev 252608)
+++ trunk/Tools/WebKitTestRunner/InjectedBundle/mac/AccessibilityControllerMac.mm	2019-11-19 01:12:00 UTC (rev 252609)
@@ -109,4 +109,44 @@
     return adopt(JSStringCreateWithUTF8CString("mac"));
 }
 
+// AXThread implementation
+
+void AXThread::initializeRunLoop()
+{
+    // Initialize the run loop.
+    {
+        std::lock_guard<Lock> lock(m_initializeRunLoopMutex);
+
+        m_threadRunLoop = CFRunLoopGetCurrent();
+
+        CFRunLoopSourceContext context = { 0, this, 0, 0, 0, 0, 0, 0, 0, threadRunLoopSourceCallback };
+        m_threadRunLoopSource = adoptCF(CFRunLoopSourceCreate(0, 0, &context));
+        CFRunLoopAddSource(CFRunLoopGetCurrent(), m_threadRunLoopSource.get(), kCFRunLoopDefaultMode);
+
+        m_initializeRunLoopConditionVariable.notifyAll();
+    }
+
+    ASSERT(isCurrentThread());
+
+    CFRunLoopRun();
+}
+
+void AXThread::wakeUpRunLoop()
+{
+    CFRunLoopSourceSignal(m_threadRunLoopSource.get());
+    CFRunLoopWakeUp(m_threadRunLoop.get());
+}
+
+void AXThread::threadRunLoopSourceCallback(void* axThread)
+{
+    static_cast<AXThread*>(axThread)->threadRunLoopSourceCallback();
+}
+
+void AXThread::threadRunLoopSourceCallback()
+{
+    @autoreleasepool {
+        dispatchFunctionsFromAXThread();
+    }
+}
+
 } // namespace WTR
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to