AX: Make AXIsolatedTree compile again
[WebKit-https.git] / Source / WebKit / WebProcess / WebPage / mac / WKAccessibilityWebPageObjectBase.mm
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. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #import "config.h"
27 #import "WKAccessibilityWebPageObjectBase.h"
28
29 #import "AccessibilityPrivSPI.h"
30 #import "WebFrame.h"
31 #import "WebPage.h"
32 #import "WKArray.h"
33 #import "WKNumber.h"
34 #import "WKRetainPtr.h"
35 #import "WKSharedAPICast.h"
36 #import "WKString.h"
37 #import "WKStringCF.h"
38 #import <WebCore/AXIsolatedTree.h>
39 #import <WebCore/AXObjectCache.h>
40 #import <WebCore/Document.h>
41 #import <WebCore/Frame.h>
42 #import <WebCore/FrameView.h>
43 #import <WebCore/Page.h>
44 #import <WebCore/ScrollView.h>
45 #import <WebCore/Scrollbar.h>
46 #import <wtf/ObjCRuntimeExtras.h>
47
48 @implementation WKAccessibilityWebPageObjectBase
49
50 - (WebCore::AXObjectCache*)axObjectCache
51 {
52     if (!m_page)
53         return nullptr;
54
55     auto page = m_page->corePage();
56     if (!page)
57         return nullptr;
58
59     auto& core = page->mainFrame();
60     if (!core.document())
61         return nullptr;
62
63     return core.document()->axObjectCache();
64 }
65
66 - (id)accessibilityPluginObject
67 {
68     auto retrieveBlock = [&self]() -> id {
69         id axPlugin = nil;
70         auto dispatchBlock = [&axPlugin, &self] {
71             if (self->m_page)
72                 axPlugin = self->m_page->accessibilityObjectForMainFramePlugin();
73         };
74
75         if (isMainThread())
76             dispatchBlock();
77         else {
78             callOnMainThreadAndWait([&dispatchBlock] {
79                 dispatchBlock();
80             });
81         }
82         return axPlugin;
83     };
84     
85     return retrieveBlock();
86 }
87
88 #if ENABLE(ACCESSIBILITY_ISOLATED_TREE)
89 - (BOOL)clientSupportsIsolatedTree
90 {
91     AXClientType type = _AXGetClientForCurrentRequestUntrusted();
92     // FIXME: Remove unknown client before enabling ACCESSIBILITY_ISOLATED_TREE.
93     return type == kAXClientTypeVoiceOver || type == kAXClientTypeUnknown;
94 }
95
96 - (id)isolatedTreeRootObject
97 {
98     if (isMainThread()) {
99         if (auto cache = [self axObjectCache]) {
100             auto tree = cache->generateIsolatedAccessibilityTree();
101
102             // Now that we have created our tree, initialize the secondary thread,
103             // so future requests come in on the other thread.
104             _AXUIElementUseSecondaryAXThread(true);
105             if (auto rootNode = tree->rootNode())
106                 return rootNode->wrapper();
107         }
108     } else {
109         auto tree = WebCore::AXIsolatedTree::treeForPageID(m_pageID);
110         tree->applyPendingChanges();
111         if (auto rootNode = tree->rootNode())
112             return rootNode->wrapper();
113     }
114
115     return nil;
116 }
117 #endif
118
119 - (id)accessibilityRootObjectWrapper
120 {
121     if (!WebCore::AXObjectCache::accessibilityEnabled())
122         WebCore::AXObjectCache::enableAccessibility();
123
124     if (m_hasMainFramePlugin)
125         return self.accessibilityPluginObject;
126
127 #if ENABLE(ACCESSIBILITY_ISOLATED_TREE)
128     // If VoiceOver is on, ensure subsequent requests are now handled on the secondary AX thread.
129     bool clientSupportsIsolatedTree = [self clientSupportsIsolatedTree];
130     if (clientSupportsIsolatedTree)
131         return [self isolatedTreeRootObject];
132 #endif
133
134     if (auto cache = [self axObjectCache]) {
135         if (WebCore::AccessibilityObject* root = cache->rootObject())
136             return root->wrapper();
137     }
138
139     return nil;
140 }
141
142 - (void)setWebPage:(WebKit::WebPage*)page
143 {
144     m_page = page;
145
146     if (page) {
147         m_pageID = page->identifier();
148
149         auto* frame = page->mainFrame();
150         m_hasMainFramePlugin = frame && frame->document() ? frame->document()->isPluginDocument() : false;
151     } else {
152         m_pageID = { };
153         m_hasMainFramePlugin = false;
154     }
155 }
156
157 - (void)setHasMainFramePlugin:(bool)hasPlugin
158 {
159     m_hasMainFramePlugin = hasPlugin;
160 }
161
162 - (void)setRemoteParent:(id)parent
163 {
164     if (parent != m_parent) {
165         [m_parent release];
166         m_parent = [parent retain];
167     }
168 }
169
170 - (id)accessibilityFocusedUIElement
171 {
172     return [[self accessibilityRootObjectWrapper] accessibilityFocusedUIElement];
173 }
174
175
176 @end