Changeset 252609 in webkit


Ignore:
Timestamp:
Nov 18, 2019 5:12:00 PM (4 years ago)
Author:
Andres Gonzalez
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):

Location:
trunk
Files:
10 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r252607 r252609  
     12019-11-18  Andres Gonzalez  <andresg_22@apple.com>
     2
     3        Run AccessibilityController::rootElement on secondary thread to simulate HIServices during LayoutTests.
     4        https://bugs.webkit.org/show_bug.cgi?id=204226
     5
     6        Reviewed by Chris Fleizach.
     7
     8        No new tests, no new functionality.
     9
     10        Added AXObjectCahce::canUseSecondaryAXThread to support
     11        WTR::AccessibilityController spawning of a secondary thread to simulate
     12        execution of isolated tree code.
     13
     14        * accessibility/AXObjectCache.cpp:
     15        (WebCore::AXObjectCache::canUseSecondaryAXThread):
     16        * accessibility/AXObjectCache.h:
     17
    1182019-11-15  Ryosuke Niwa  <rniwa@webkit.org>
    219
  • trunk/Source/WebCore/accessibility/AXObjectCache.cpp

    r252417 r252609  
    705705}
    706706#endif
     707
     708bool AXObjectCache::canUseSecondaryAXThread()
     709{
     710#if ENABLE(ACCESSIBILITY_ISOLATED_TREE) && PLATFORM(MAC)
     711    if (_AXUIElementRequestServicedBySecondaryAXThread())
     712        return true;
     713
     714    // _AXUIElementRequestServicedBySecondaryAXThread returns false for
     715    // LayoutTests, but we still want to run LayoutTests using isolated tree on
     716    // a secondary thread to simulate the actual execution.
     717    return clientSupportsIsolatedTree();
     718#else
     719    return false;
     720#endif
     721}
    707722
    708723AccessibilityObject* AXObjectCache::rootObjectForFrame(Frame* frame)
  • trunk/Source/WebCore/accessibility/AXObjectCache.h

    r252542 r252609  
    201201
    202202public:
     203    WEBCORE_EXPORT bool canUseSecondaryAXThread();
     204
    203205#if ENABLE(ACCESSIBILITY)
    204206    WEBCORE_EXPORT static void enableAccessibility();
  • trunk/Source/WebKit/ChangeLog

    r252605 r252609  
     12019-11-18  Andres Gonzalez  <andresg_22@apple.com>
     2
     3        Run AccessibilityController::rootElement on secondary thread to simulate HIServices during LayoutTests.
     4        https://bugs.webkit.org/show_bug.cgi?id=204226
     5
     6        Reviewed by Chris Fleizach.
     7
     8        Added WKAccessibilityCanUseSecondaryAXThread to support
     9        WTR::AccessibilityController spawning of a secondary thread to simulate
     10        execution of isolated tree code.
     11
     12        * WebProcess/InjectedBundle/API/c/WKBundlePage.cpp:
     13        (WKAccessibilityCanUseSecondaryAXThread):
     14        * WebProcess/InjectedBundle/API/c/WKBundlePagePrivate.h:
     15
    1162019-11-18  Chris Dumez  <cdumez@apple.com>
    217
  • trunk/Source/WebKit/WebProcess/InjectedBundle/API/c/WKBundlePage.cpp

    r252172 r252609  
    283283}
    284284
     285bool WKAccessibilityCanUseSecondaryAXThread(WKBundlePageRef pageRef)
     286{
     287#if ENABLE(ACCESSIBILITY)
     288    if (!pageRef)
     289        return false;
     290
     291    WebCore::Page* page = WebKit::toImpl(pageRef)->corePage();
     292    if (!page)
     293        return false;
     294
     295    WebCore::Frame& core = page->mainFrame();
     296    if (!core.document())
     297        return false;
     298
     299    WebCore::AXObjectCache::enableAccessibility();
     300
     301    auto* axObjectCache = core.document()->axObjectCache();
     302    if (!axObjectCache)
     303        return false;
     304
     305    return axObjectCache->canUseSecondaryAXThread();
     306#else
     307    UNUSED_PARAM(pageRef);
     308    return false;
     309#endif
     310}
     311
    285312void WKAccessibilityEnableEnhancedAccessibility(bool enable)
    286313{
  • trunk/Source/WebKit/WebProcess/InjectedBundle/API/c/WKBundlePagePrivate.h

    r252172 r252609  
    9797WK_EXPORT void* WKAccessibilityRootObject(WKBundlePageRef);
    9898WK_EXPORT void* WKAccessibilityFocusedObject(WKBundlePageRef);
     99WK_EXPORT bool WKAccessibilityCanUseSecondaryAXThread(WKBundlePageRef);
    99100
    100101WK_EXPORT void WKAccessibilityEnableEnhancedAccessibility(bool);
  • trunk/Tools/ChangeLog

    r252606 r252609  
     12019-11-18  Andres Gonzalez  <andresg_22@apple.com>
     2
     3        Run AccessibilityController::rootElement on secondary thread to simulate HIServices during LayoutTests.
     4        https://bugs.webkit.org/show_bug.cgi?id=204226
     5
     6        Reviewed by Chris Fleizach.
     7
     8        HIServices _AXUIElementUseSecondaryAXThread and _AXUIElementRequestServicedBySecondaryAXThread
     9        do not work for WebKitTestRunner since this is calling directly into
     10        WebCore/accessibility via JavaScript without going through HIServices.
     11        Thus to simulate the behavior of HIServices, AccessibilityController is
     12        spawning a secondary thread to service the JavaScript requests.
     13        The very first request needs to be serviced in the main thread,
     14        and all subsequent requests in the secondary thread. this is what
     15        the behavior would be if using HIServices.
     16        Once the IsolatedTree would be enabled, the first request has to be
     17        served in the main thread in order to build the AXIsolatedTree.
     18
     19        * WebKitTestRunner/InjectedBundle/AccessibilityController.cpp:
     20        (WTR::AccessibilityController::rootElement):
     21        (WTR::AXThread::AXThread):
     22        (WTR::AXThread::isCurrentThread):
     23        (WTR::AXThread::dispatch):
     24        (WTR::AXThread::dispatchBarrier):
     25        (WTR::AXThread::singleton):
     26        (WTR::AXThread::createThreadIfNeeded):
     27        (WTR::AXThread::dispatchFunctionsFromAXThread):
     28        (WTR::AXThread::initializeRunLoop):
     29        (WTR::AXThread::wakeUpRunLoop):
     30        (WTR::AXThread::threadRunLoopSourceCallback):
     31        * WebKitTestRunner/InjectedBundle/AccessibilityController.h:
     32        * WebKitTestRunner/InjectedBundle/mac/AccessibilityControllerMac.mm:
     33        (WTR::AXThread::initializeRunLoop):
     34        (WTR::AXThread::wakeUpRunLoop):
     35        (WTR::AXThread::threadRunLoopSourceCallback):
     36
    1372019-11-18  Jonathan Bedard  <jbedard@apple.com>
    238
  • trunk/Tools/WebKitTestRunner/InjectedBundle/AccessibilityController.cpp

    r247367 r252609  
    7777{
    7878    WKBundlePageRef page = InjectedBundle::singleton().page()->page();
    79     void* root = WKAccessibilityRootObject(page);
    80    
    81     return AccessibilityUIElement::create(static_cast<PlatformUIElement>(root));   
     79    PlatformUIElement root = nullptr;
     80
     81    if (m_useAXThread) {
     82        AXThread::dispatch([&root, page, this] {
     83            root = static_cast<PlatformUIElement>(WKAccessibilityRootObject(page));
     84            m_semaphore.signal();
     85        });
     86
     87        m_semaphore.wait();
     88    } else {
     89        root = static_cast<PlatformUIElement>(WKAccessibilityRootObject(page));
     90
     91        if (WKAccessibilityCanUseSecondaryAXThread(page)) {
     92            // Set m_useAXThread to true for next request.
     93            m_useAXThread = true;
     94        }
     95    }
     96
     97    return AccessibilityUIElement::create(root);
    8298}
    8399
     
    97113}
    98114
     115#if PLATFORM(COCOA)
     116
     117// AXThread implementation
     118
     119AXThread::AXThread()
     120{
     121}
     122
     123bool AXThread::isCurrentThread()
     124{
     125    return AXThread::singleton().m_thread == &Thread::current();
     126}
     127
     128void AXThread::dispatch(Function<void()>&& function)
     129{
     130    auto& axThread = AXThread::singleton();
     131    axThread.createThreadIfNeeded();
     132
     133    {
     134        std::lock_guard<Lock> lock(axThread.m_functionsMutex);
     135        axThread.m_functions.append(WTFMove(function));
     136    }
     137
     138    axThread.wakeUpRunLoop();
     139}
     140
     141void AXThread::dispatchBarrier(Function<void()>&& function)
     142{
     143    dispatch([function = WTFMove(function)]() mutable {
     144        callOnMainThread(WTFMove(function));
     145    });
     146}
     147
     148AXThread& AXThread::singleton()
     149{
     150    static NeverDestroyed<AXThread> axThread;
     151    return axThread;
     152}
     153
     154void AXThread::createThreadIfNeeded()
     155{
     156    // Wait for the thread to initialize the run loop.
     157    std::unique_lock<Lock> lock(m_initializeRunLoopMutex);
     158
     159    if (!m_thread) {
     160        m_thread = Thread::create("WKTR: AccessibilityController", [this] {
     161            WTF::Thread::setCurrentThreadIsUserInteractive();
     162            initializeRunLoop();
     163        });
     164    }
     165
     166    m_initializeRunLoopConditionVariable.wait(lock, [this] {
     167#if PLATFORM(COCOA)
     168        return m_threadRunLoop;
     169#else
     170        return m_runLoop;
     171#endif
     172    });
     173}
     174
     175void AXThread::dispatchFunctionsFromAXThread()
     176{
     177    ASSERT(isCurrentThread());
     178
     179    Vector<Function<void()>> functions;
     180
     181    {
     182        std::lock_guard<Lock> lock(m_functionsMutex);
     183        functions = WTFMove(m_functions);
     184    }
     185
     186    for (auto& function : functions)
     187        function();
     188}
     189
     190#if !PLATFORM(MAC)
     191NO_RETURN_DUE_TO_ASSERT void AXThread::initializeRunLoop()
     192{
     193    ASSERT_NOT_REACHED();
     194}
     195
     196void AXThread::wakeUpRunLoop()
     197{
     198}
     199
     200void AXThread::threadRunLoopSourceCallback(void*)
     201{
     202}
     203
     204void AXThread::threadRunLoopSourceCallback()
     205{
     206}
     207#endif // !PLATFORM(MAC)
     208
     209#endif // PLATFORM(COCOA)
     210
    99211} // namespace WTR
    100212#endif // ENABLE(ACCESSIBILITY)
  • trunk/Tools/WebKitTestRunner/InjectedBundle/AccessibilityController.h

    r248762 r252609  
    2929#include "JSWrappable.h"
    3030#include <JavaScriptCore/JSObjectRef.h>
     31#include <wtf/Condition.h>
    3132#include <wtf/FastMalloc.h>
    3233#include <wtf/Platform.h>
     34#include <wtf/Threading.h>
     35#include <wtf/threads/BinarySemaphore.h>
     36
    3337#if USE(ATK)
    3438#include "AccessibilityNotificationHandlerAtk.h"
     
    8387    RefPtr<AccessibilityNotificationHandler> m_globalNotificationHandler;
    8488#endif
     89
     90#if PLATFORM(COCOA)
     91    // _AXUIElementUseSecondaryAXThread and _AXUIElementRequestServicedBySecondaryAXThread
     92    // do not work for WebKitTestRunner since this is calling directly into
     93    // WebCore/accessibility via JavaScript without going through HIServices.
     94    // Thus to simulate the behavior of HIServices, AccessibilityController is spawning a secondary thread to service the JavaScript requests.
     95    // The following flag allows to run the very first request in the main
     96    // thread and all subsequent requests in the secondary thread. this is what
     97    // the behavior would be if using HIServices.
     98    // The first request has to be served in the main thread in order to build
     99    // the AXIsolatedTree.
     100    bool m_useAXThread { false };
     101    BinarySemaphore m_semaphore;
     102#endif
    85103};
    86104
     105#if PLATFORM(COCOA)
     106
     107class AXThread {
     108    WTF_MAKE_NONCOPYABLE(AXThread);
     109
     110public:
     111    static bool isCurrentThread();
     112    static void dispatch(Function<void()>&&);
     113
     114    // Will dispatch the given function on the main thread once all pending functions
     115    // on the AX thread have finished executing. Used for synchronization purposes.
     116    static void dispatchBarrier(Function<void()>&&);
     117
     118private:
     119    friend NeverDestroyed<AXThread>;
     120
     121    AXThread();
     122
     123    static AXThread& singleton();
     124
     125    void createThreadIfNeeded();
     126    void dispatchFunctionsFromAXThread();
     127
     128    void initializeRunLoop();
     129    void wakeUpRunLoop();
     130
     131#if PLATFORM(COCOA)
     132    static void threadRunLoopSourceCallback(void* AXThread);
     133    void threadRunLoopSourceCallback();
     134#endif
     135
     136    RefPtr<Thread> m_thread;
     137
     138    Condition m_initializeRunLoopConditionVariable;
     139    Lock m_initializeRunLoopMutex;
     140
     141    Lock m_functionsMutex;
     142    Vector<Function<void()>> m_functions;
     143
     144#if PLATFORM(COCOA)
     145    // FIXME: We should use WebCore::RunLoop here.
     146    RetainPtr<CFRunLoopRef> m_threadRunLoop;
     147    RetainPtr<CFRunLoopSourceRef> m_threadRunLoopSource;
     148#else
     149    RunLoop* m_runLoop { nullptr };
     150#endif
     151};
     152
     153#endif // PLATFORM(COCOA)
     154
    87155} // namespace WTR
  • trunk/Tools/WebKitTestRunner/InjectedBundle/mac/AccessibilityControllerMac.mm

    r236032 r252609  
    110110}
    111111
     112// AXThread implementation
     113
     114void AXThread::initializeRunLoop()
     115{
     116    // Initialize the run loop.
     117    {
     118        std::lock_guard<Lock> lock(m_initializeRunLoopMutex);
     119
     120        m_threadRunLoop = CFRunLoopGetCurrent();
     121
     122        CFRunLoopSourceContext context = { 0, this, 0, 0, 0, 0, 0, 0, 0, threadRunLoopSourceCallback };
     123        m_threadRunLoopSource = adoptCF(CFRunLoopSourceCreate(0, 0, &context));
     124        CFRunLoopAddSource(CFRunLoopGetCurrent(), m_threadRunLoopSource.get(), kCFRunLoopDefaultMode);
     125
     126        m_initializeRunLoopConditionVariable.notifyAll();
     127    }
     128
     129    ASSERT(isCurrentThread());
     130
     131    CFRunLoopRun();
     132}
     133
     134void AXThread::wakeUpRunLoop()
     135{
     136    CFRunLoopSourceSignal(m_threadRunLoopSource.get());
     137    CFRunLoopWakeUp(m_threadRunLoop.get());
     138}
     139
     140void AXThread::threadRunLoopSourceCallback(void* axThread)
     141{
     142    static_cast<AXThread*>(axThread)->threadRunLoopSourceCallback();
     143}
     144
     145void AXThread::threadRunLoopSourceCallback()
     146{
     147    @autoreleasepool {
     148        dispatchFunctionsFromAXThread();
     149    }
     150}
     151
    112152} // namespace WTR
Note: See TracChangeset for help on using the changeset viewer.