68d9958501da70f54a819e887a948075a9df5b97
[WebKit-https.git] / Tools / WebKitTestRunner / InjectedBundle / AccessibilityController.cpp
1 /*
2  * Copyright (C) 2011 Apple Inc. All Rights Reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
24  */
25
26 #include "config.h"
27 #include "AccessibilityController.h"
28
29 #if ENABLE(ACCESSIBILITY)
30
31 #include "AccessibilityUIElement.h"
32 #include "InjectedBundle.h"
33 #include "InjectedBundlePage.h"
34 #include "JSAccessibilityController.h"
35
36 #include <WebKit/WKBundle.h>
37 #include <WebKit/WKBundlePage.h>
38 #include <WebKit/WKBundlePagePrivate.h>
39
40 namespace WTR {
41
42 Ref<AccessibilityController> AccessibilityController::create()
43 {
44     return adoptRef(*new AccessibilityController);
45 }
46
47 AccessibilityController::AccessibilityController()
48 {
49 #if PLATFORM(MAC)
50     m_useAXThread = WKAccessibilityCanUseSecondaryAXThread(InjectedBundle::singleton().page()->page());
51 #endif
52 }
53
54 AccessibilityController::~AccessibilityController()
55 {
56 }
57
58 void AccessibilityController::makeWindowObject(JSContextRef context, JSObjectRef windowObject, JSValueRef* exception)
59 {
60     setProperty(context, windowObject, "accessibilityController", this, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete, exception);
61 }
62
63 JSClassRef AccessibilityController::wrapperClass()
64 {
65     return JSAccessibilityController::accessibilityControllerClass();
66 }
67
68 void AccessibilityController::enableEnhancedAccessibility(bool enable)
69 {
70     WKAccessibilityEnableEnhancedAccessibility(enable);
71 }
72
73 bool AccessibilityController::enhancedAccessibilityEnabled()
74 {
75     return WKAccessibilityEnhancedAccessibilityEnabled();
76 }
77
78 #if PLATFORM(COCOA)
79 Ref<AccessibilityUIElement> AccessibilityController::rootElement()
80 {
81     WKBundlePageRef page = InjectedBundle::singleton().page()->page();
82     PlatformUIElement root = static_cast<PlatformUIElement>(WKAccessibilityRootObject(page));
83
84     return AccessibilityUIElement::create(root);
85 }
86
87 Ref<AccessibilityUIElement> AccessibilityController::focusedElement()
88 {
89     WKBundlePageRef page = InjectedBundle::singleton().page()->page();
90     PlatformUIElement focusedElement = static_cast<PlatformUIElement>(WKAccessibilityFocusedObject(page));
91     return AccessibilityUIElement::create(focusedElement);
92 }
93
94 void AccessibilityController::executeOnAXThreadIfPossible(Function<void()>&& function)
95 {
96     if (m_useAXThread) {
97         AXThread::dispatch([&function, this] {
98             function();
99             m_semaphore.signal();
100         });
101
102         // Spin the main loop so that any required DOM processing can be
103         // executed in the main thread. That is the case of most parameterized
104         // attributes, where the attribute value has to be calculated
105         // back in the main thread.
106         CFRunLoopRunInMode(kCFRunLoopDefaultMode, .25, false);
107         m_semaphore.wait();
108     } else
109         function();
110 }
111 #endif
112
113 RefPtr<AccessibilityUIElement> AccessibilityController::elementAtPoint(int x, int y)
114 {
115     auto uiElement = rootElement();
116     return uiElement->elementAtPoint(x, y);
117 }
118
119 #if PLATFORM(COCOA)
120
121 // AXThread implementation
122
123 AXThread::AXThread()
124 {
125 }
126
127 bool AXThread::isCurrentThread()
128 {
129     return AXThread::singleton().m_thread == &Thread::current();
130 }
131
132 void AXThread::dispatch(Function<void()>&& function)
133 {
134     auto& axThread = AXThread::singleton();
135     axThread.createThreadIfNeeded();
136
137     {
138         auto locker = holdLock(axThread.m_functionsMutex);
139         axThread.m_functions.append(WTFMove(function));
140     }
141
142     axThread.wakeUpRunLoop();
143 }
144
145 void AXThread::dispatchBarrier(Function<void()>&& function)
146 {
147     dispatch([function = WTFMove(function)]() mutable {
148         callOnMainThread(WTFMove(function));
149     });
150 }
151
152 AXThread& AXThread::singleton()
153 {
154     static NeverDestroyed<AXThread> axThread;
155     return axThread;
156 }
157
158 void AXThread::createThreadIfNeeded()
159 {
160     // Wait for the thread to initialize the run loop.
161     std::unique_lock<Lock> lock(m_initializeRunLoopMutex);
162
163     if (!m_thread) {
164         m_thread = Thread::create("WKTR: AccessibilityController", [this] {
165             WTF::Thread::setCurrentThreadIsUserInteractive();
166             initializeRunLoop();
167         });
168     }
169
170     m_initializeRunLoopConditionVariable.wait(lock, [this] {
171 #if PLATFORM(COCOA)
172         return m_threadRunLoop;
173 #else
174         return m_runLoop;
175 #endif
176     });
177 }
178
179 void AXThread::dispatchFunctionsFromAXThread()
180 {
181     ASSERT(isCurrentThread());
182
183     Vector<Function<void()>> functions;
184
185     {
186         auto locker = holdLock(m_functionsMutex);
187         functions = WTFMove(m_functions);
188     }
189
190     for (auto& function : functions)
191         function();
192 }
193
194 #if !PLATFORM(MAC)
195 NO_RETURN_DUE_TO_ASSERT void AXThread::initializeRunLoop()
196 {
197     ASSERT_NOT_REACHED();
198 }
199
200 void AXThread::wakeUpRunLoop()
201 {
202 }
203
204 void AXThread::threadRunLoopSourceCallback(void*)
205 {
206 }
207
208 void AXThread::threadRunLoopSourceCallback()
209 {
210 }
211 #endif // !PLATFORM(MAC)
212
213 #endif // PLATFORM(COCOA)
214
215 } // namespace WTR
216 #endif // ENABLE(ACCESSIBILITY)
217