1a9a573e0b960384bcb8b8ed94932fe8b155c204
[WebKit-https.git] / Source / WebCore / accessibility / isolatedtree / AXIsolatedTreeNode.cpp
1 /*
2  * Copyright (C) 2019 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 #include "config.h"
27
28 #if ENABLE(ACCESSIBILITY_ISOLATED_TREE)
29 #include "AXIsolatedTreeNode.h"
30
31 #include "AccessibilityObject.h"
32
33 extern "C" bool _AXUIElementRequestServicedBySecondaryAXThread(void);
34
35 namespace WebCore {
36
37 AXIsolatedObject::AXIsolatedObject(AXCoreObject& object)
38     : m_id(object.objectID())
39 {
40     ASSERT(isMainThread());
41     initializeAttributeData(object);
42 #if !ASSERT_DISABLED
43     m_initialized = true;
44 #endif
45 }
46
47 Ref<AXIsolatedObject> AXIsolatedObject::create(AXCoreObject& object)
48 {
49     return adoptRef(*new AXIsolatedObject(object));
50 }
51
52 AXIsolatedObject::~AXIsolatedObject() = default;
53
54 void AXIsolatedObject::initializeAttributeData(AXCoreObject& object)
55 {
56     setProperty(AXPropertyName::RoleValue, static_cast<int>(object.roleValue()));
57     setProperty(AXPropertyName::RolePlatformString, object.rolePlatformString().isolatedCopy());
58     setProperty(AXPropertyName::ARIALandmarkRoleDescription, object.ariaLandmarkRoleDescription().isolatedCopy());
59     setProperty(AXPropertyName::RoleDescription, object.roleDescription().isolatedCopy());
60     setProperty(AXPropertyName::IsAttachment, object.isAttachment());
61     setProperty(AXPropertyName::IsMediaControlLabel, object.isMediaControlLabel());
62     setProperty(AXPropertyName::IsLink, object.isLink());
63     setProperty(AXPropertyName::IsImageMapLink, object.isImageMapLink());
64     setProperty(AXPropertyName::IsImage, object.isImage());
65     setProperty(AXPropertyName::IsFileUploadButton, object.isFileUploadButton());
66     setProperty(AXPropertyName::IsAccessibilityIgnored, object.accessibilityIsIgnored());
67     setProperty(AXPropertyName::IsTree, object.isTree());
68     setProperty(AXPropertyName::IsScrollbar, object.isScrollbar());
69     setProperty(AXPropertyName::RelativeFrame, object.relativeFrame());
70     setProperty(AXPropertyName::SpeechHint, object.speechHintAttributeValue().isolatedCopy());
71     setProperty(AXPropertyName::Title, object.titleAttributeValue().isolatedCopy());
72     setProperty(AXPropertyName::Description, object.descriptionAttributeValue().isolatedCopy());
73     setProperty(AXPropertyName::HelpText, object.helpTextAttributeValue().isolatedCopy());
74
75     if (bool isMathElement = object.isMathElement()) {
76         setProperty(AXPropertyName::IsMathElement, isMathElement);
77         setProperty(AXPropertyName::IsAnonymousMathOperator, object.isAnonymousMathOperator());
78         setProperty(AXPropertyName::IsMathFraction, object.isMathFraction());
79         setProperty(AXPropertyName::IsMathFenced, object.isMathFenced());
80         setProperty(AXPropertyName::IsMathSubscriptSuperscript, object.isMathSubscriptSuperscript());
81         setProperty(AXPropertyName::IsMathRow, object.isMathRow());
82         setProperty(AXPropertyName::IsMathUnderOver, object.isMathUnderOver());
83         setProperty(AXPropertyName::IsMathRoot, object.isMathRoot());
84         setProperty(AXPropertyName::IsMathSquareRoot, object.isMathSquareRoot());
85         setProperty(AXPropertyName::IsMathText, object.isMathText());
86         setProperty(AXPropertyName::IsMathNumber, object.isMathNumber());
87         setProperty(AXPropertyName::IsMathOperator, object.isMathOperator());
88         setProperty(AXPropertyName::IsMathFenceOperator, object.isMathFenceOperator());
89         setProperty(AXPropertyName::IsMathSeparatorOperator, object.isMathSeparatorOperator());
90         setProperty(AXPropertyName::IsMathIdentifier, object.isMathIdentifier());
91         setProperty(AXPropertyName::IsMathTable, object.isMathTable());
92         setProperty(AXPropertyName::IsMathTableRow, object.isMathTableRow());
93         setProperty(AXPropertyName::IsMathTableCell, object.isMathTableCell());
94         setProperty(AXPropertyName::IsMathMultiscript, object.isMathMultiscript());
95         setProperty(AXPropertyName::IsMathToken, object.isMathToken());
96         setProperty(AXPropertyName::MathFencedOpenString, object.mathFencedOpenString());
97         setProperty(AXPropertyName::MathFencedCloseString, object.mathFencedCloseString());
98         setProperty(AXPropertyName::MathLineThickness, object.mathLineThickness());
99         setObjectProperty(AXPropertyName::MathRadicandObject, object.mathRadicandObject());
100         setObjectProperty(AXPropertyName::MathRootIndexObject, object.mathRootIndexObject());
101         setObjectProperty(AXPropertyName::MathUnderObject, object.mathUnderObject());
102         setObjectProperty(AXPropertyName::MathOverObject, object.mathOverObject());
103         setObjectProperty(AXPropertyName::MathNumeratorObject, object.mathNumeratorObject());
104         setObjectProperty(AXPropertyName::MathDenominatorObject, object.mathDenominatorObject());
105         setObjectProperty(AXPropertyName::MathBaseObject, object.mathBaseObject());
106         setObjectProperty(AXPropertyName::MathSubscriptObject, object.mathSubscriptObject());
107         setObjectProperty(AXPropertyName::MathSuperscriptObject, object.mathSuperscriptObject());
108     }
109 }
110
111 void AXIsolatedObject::setObjectProperty(AXPropertyName propertyName, AXCoreObject* object)
112 {
113     if (object)
114         setProperty(propertyName, object->objectID());
115     else
116         setProperty(propertyName, nullptr, true);
117 }
118
119 void AXIsolatedObject::setProperty(AXPropertyName propertyName, AttributeValueVariant&& value, bool shouldRemove)
120 {
121     ASSERT(!m_initialized);
122     ASSERT(isMainThread());
123
124     if (shouldRemove)
125         m_attributeMap.remove(propertyName);
126     else
127         m_attributeMap.set(propertyName, value);
128 }
129
130 void AXIsolatedObject::appendChild(AXID axID)
131 {
132     ASSERT(isMainThread());
133     m_childrenIDs.append(axID);
134 }
135
136 void AXIsolatedObject::setParent(AXID parent)
137 {
138     ASSERT(isMainThread());
139     m_parent = parent;
140 }
141
142 void AXIsolatedObject::setTreeIdentifier(AXIsolatedTreeID treeIdentifier)
143 {
144     m_treeIdentifier = treeIdentifier;
145     if (auto tree = AXIsolatedTree::treeForID(m_treeIdentifier))
146         m_cachedTree = tree;
147 }
148
149 const AXCoreObject::AccessibilityChildrenVector& AXIsolatedObject::children(bool)
150 {
151     if (_AXUIElementRequestServicedBySecondaryAXThread()) {
152         m_children.clear();
153         m_children.reserveInitialCapacity(m_childrenIDs.size());
154         auto tree = this->tree();
155         for (auto childID : m_childrenIDs)
156             m_children.uncheckedAppend(tree->nodeForID(childID));
157     }
158     return m_children;
159 }
160
161 AXCoreObject* AXIsolatedObject::focusedUIElement() const
162 {
163     if (auto focusedElement = tree()->focusedUIElement())
164         return focusedElement.get();
165     return nullptr;
166 }
167     
168 AXCoreObject* AXIsolatedObject::parentObjectUnignored() const
169 {
170     return tree()->nodeForID(parent()).get();
171 }
172
173 AXCoreObject* AXIsolatedObject::accessibilityHitTest(const IntPoint& point) const
174 {
175     if (!relativeFrame().contains(point))
176         return nullptr;
177     for (const auto& childID : m_childrenIDs) {
178         auto child = tree()->nodeForID(childID);
179         ASSERT(child);
180         if (child && child->relativeFrame().contains(point))
181             return child->accessibilityHitTest(point);
182     }
183     return const_cast<AXIsolatedObject*>(this);
184 }
185
186 AXIsolatedTree* AXIsolatedObject::tree() const
187 {
188     return m_cachedTree.get();
189 }
190
191 AXCoreObject* AXIsolatedObject::objectAttributeValue(AXPropertyName propertyName) const
192 {
193     auto value = m_attributeMap.get(propertyName);
194     AXID nodeID = WTF::switchOn(value,
195         [] (AXID& typedValue) { return typedValue; },
196         [] (auto&) { return InvalidAXID; }
197     );
198     
199     return tree()->nodeForID(nodeID).get();
200 }
201
202
203 FloatRect AXIsolatedObject::rectAttributeValue(AXPropertyName propertyName) const
204 {
205     auto value = m_attributeMap.get(propertyName);
206     return WTF::switchOn(value,
207         [] (Optional<FloatRect> typedValue) {
208             if (!typedValue)
209                 return FloatRect { };
210             return typedValue.value();
211         },
212         [] (auto&) { return FloatRect { }; }
213     );
214 }
215
216 double AXIsolatedObject::doubleAttributeValue(AXPropertyName propertyName) const
217 {
218     auto value = m_attributeMap.get(propertyName);
219     return WTF::switchOn(value,
220         [] (double& typedValue) { return typedValue; },
221         [] (auto&) { return 0; }
222     );
223 }
224
225 unsigned AXIsolatedObject::unsignedAttributeValue(AXPropertyName propertyName) const
226 {
227     auto value = m_attributeMap.get(propertyName);
228     return WTF::switchOn(value,
229         [] (unsigned& typedValue) { return typedValue; },
230         [] (auto&) { return 0; }
231     );
232 }
233
234 bool AXIsolatedObject::boolAttributeValue(AXPropertyName propertyName) const
235 {
236     auto value = m_attributeMap.get(propertyName);
237     return WTF::switchOn(value,
238         [] (bool& typedValue) { return typedValue; },
239         [] (auto&) { return false; }
240     );
241 }
242
243 const String AXIsolatedObject::stringAttributeValue(AXPropertyName propertyName) const
244 {
245     auto value = m_attributeMap.get(propertyName);
246     return WTF::switchOn(value,
247         [] (String& typedValue) { return typedValue; },
248         [] (auto&) { return emptyString(); }
249     );
250 }
251
252 int AXIsolatedObject::intAttributeValue(AXPropertyName propertyName) const
253 {
254     auto value = m_attributeMap.get(propertyName);
255     return WTF::switchOn(value,
256         [] (int& typedValue) { return typedValue; },
257         [] (auto&) { return 0; }
258     );
259 }
260
261 void AXIsolatedObject::updateBackingStore()
262 {
263     if (_AXUIElementRequestServicedBySecondaryAXThread()) {
264         RELEASE_ASSERT(!isMainThread());
265         if (auto tree = this->tree())
266             tree->applyPendingChanges();
267     }
268 }
269
270 } // namespace WebCore
271
272 #endif // ENABLE((ACCESSIBILITY_ISOLATED_TREE)