REGRESSION (r257739): two fast/events/autoscroll test have started to fail
[WebKit-https.git] / Tools / WebKitTestRunner / InjectedBundle / AccessibilityController.cpp
index 42585b4..68d9958 100644 (file)
 #include "config.h"
 #include "AccessibilityController.h"
 
 #include "config.h"
 #include "AccessibilityController.h"
 
+#if ENABLE(ACCESSIBILITY)
+
 #include "AccessibilityUIElement.h"
 #include "InjectedBundle.h"
 #include "InjectedBundlePage.h"
 #include "JSAccessibilityController.h"
 
 #include "AccessibilityUIElement.h"
 #include "InjectedBundle.h"
 #include "InjectedBundlePage.h"
 #include "JSAccessibilityController.h"
 
-#include <JavaScriptCore/JSRetainPtr.h>
-#include <WebKit2/WKBundle.h>
-#include <WebKit2/WKBundlePage.h>
-#include <WebKit2/WKBundlePagePrivate.h>
+#include <WebKit/WKBundle.h>
+#include <WebKit/WKBundlePage.h>
+#include <WebKit/WKBundlePagePrivate.h>
 
 namespace WTR {
 
 
 namespace WTR {
 
-PassRefPtr<AccessibilityController> AccessibilityController::create()
+Ref<AccessibilityController> AccessibilityController::create()
 {
 {
-    return adoptRef(new AccessibilityController);
+    return adoptRef(*new AccessibilityController);
 }
 
 AccessibilityController::AccessibilityController()
 {
 }
 
 AccessibilityController::AccessibilityController()
 {
+#if PLATFORM(MAC)
+    m_useAXThread = WKAccessibilityCanUseSecondaryAXThread(InjectedBundle::singleton().page()->page());
+#endif
 }
 
 AccessibilityController::~AccessibilityController()
 }
 
 AccessibilityController::~AccessibilityController()
@@ -61,37 +65,153 @@ JSClassRef AccessibilityController::wrapperClass()
     return JSAccessibilityController::accessibilityControllerClass();
 }
 
     return JSAccessibilityController::accessibilityControllerClass();
 }
 
-PassRefPtr<AccessibilityUIElement> AccessibilityController::rootElement()
+void AccessibilityController::enableEnhancedAccessibility(bool enable)
 {
 {
-    // FIXME: Make this work on Windows.
-#if PLATFORM(WIN)
-    return 0;
-#else
-    WKBundlePageRef page = InjectedBundle::shared().page()->page();
-    void* root = WKAccessibilityRootObject(page);
-    
-    return AccessibilityUIElement::create(static_cast<PlatformUIElement>(root));    
+    WKAccessibilityEnableEnhancedAccessibility(enable);
+}
+
+bool AccessibilityController::enhancedAccessibilityEnabled()
+{
+    return WKAccessibilityEnhancedAccessibilityEnabled();
+}
+
+#if PLATFORM(COCOA)
+Ref<AccessibilityUIElement> AccessibilityController::rootElement()
+{
+    WKBundlePageRef page = InjectedBundle::singleton().page()->page();
+    PlatformUIElement root = static_cast<PlatformUIElement>(WKAccessibilityRootObject(page));
+
+    return AccessibilityUIElement::create(root);
+}
+
+Ref<AccessibilityUIElement> AccessibilityController::focusedElement()
+{
+    WKBundlePageRef page = InjectedBundle::singleton().page()->page();
+    PlatformUIElement focusedElement = static_cast<PlatformUIElement>(WKAccessibilityFocusedObject(page));
+    return AccessibilityUIElement::create(focusedElement);
+}
+
+void AccessibilityController::executeOnAXThreadIfPossible(Function<void()>&& function)
+{
+    if (m_useAXThread) {
+        AXThread::dispatch([&function, this] {
+            function();
+            m_semaphore.signal();
+        });
+
+        // Spin the main loop so that any required DOM processing can be
+        // executed in the main thread. That is the case of most parameterized
+        // attributes, where the attribute value has to be calculated
+        // back in the main thread.
+        CFRunLoopRunInMode(kCFRunLoopDefaultMode, .25, false);
+        m_semaphore.wait();
+    } else
+        function();
+}
 #endif
 #endif
+
+RefPtr<AccessibilityUIElement> AccessibilityController::elementAtPoint(int x, int y)
+{
+    auto uiElement = rootElement();
+    return uiElement->elementAtPoint(x, y);
 }
 
 }
 
-PassRefPtr<AccessibilityUIElement> AccessibilityController::focusedElement()
+#if PLATFORM(COCOA)
+
+// AXThread implementation
+
+AXThread::AXThread()
 {
 {
-    // FIXME: Make this work on Windows.
-#if PLATFORM(WIN)
-    return 0;
-#else    
-    WKBundlePageRef page = InjectedBundle::shared().page()->page();
-    void* root = WKAccessibilityFocusedObject(page);
-    
-    return AccessibilityUIElement::create(static_cast<PlatformUIElement>(root));    
+}
+
+bool AXThread::isCurrentThread()
+{
+    return AXThread::singleton().m_thread == &Thread::current();
+}
+
+void AXThread::dispatch(Function<void()>&& function)
+{
+    auto& axThread = AXThread::singleton();
+    axThread.createThreadIfNeeded();
+
+    {
+        auto locker = holdLock(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
 #endif
+    });
 }
 
 }
 
-PassRefPtr<AccessibilityUIElement> AccessibilityController::elementAtPoint(int x, int y)
+void AXThread::dispatchFunctionsFromAXThread()
 {
 {
-    RefPtr<AccessibilityUIElement> uiElement = rootElement();
-    return uiElement->elementAtPoint(x, y);
+    ASSERT(isCurrentThread());
+
+    Vector<Function<void()>> functions;
+
+    {
+        auto locker = holdLock(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
 } // namespace WTR
+#endif // ENABLE(ACCESSIBILITY)