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
33namespace WebCore {
34
35AXIsolatedTreeNode::AXIsolatedTreeNode(const AccessibilityObject& object)
36 : m_identifier(object.axObjectID())
37{
38 ASSERT(isMainThread());
39 initializeAttributeData(object);
40#if !ASSERT_DISABLED
41 m_initialized = true;
42#endif
43}
44
45Ref<AXIsolatedTreeNode> AXIsolatedTreeNode::create(const AccessibilityObject& object)
46{
47 return adoptRef(*new AXIsolatedTreeNode(object));
48}
49
50AXIsolatedTreeNode::~AXIsolatedTreeNode() = default;
51
52void AXIsolatedTreeNode::initializeAttributeData(const AccessibilityObject& object)
53{
54 setProperty(AXPropertyName::RoleValue, static_cast<int>(object.roleValue()));
55 setProperty(AXPropertyName::IsAttachment, object.isAttachment());
56 setProperty(AXPropertyName::IsMediaControlLabel, object.isMediaControlLabel());
57 setProperty(AXPropertyName::IsLink, object.isLink());
58 setProperty(AXPropertyName::IsImageMapLink, object.isImageMapLink());
59 setProperty(AXPropertyName::IsImage, object.isImage());
60 setProperty(AXPropertyName::IsFileUploadButton, object.isFileUploadButton());
61 setProperty(AXPropertyName::IsAccessibilityIgnored, object.accessibilityIsIgnored());
62 setProperty(AXPropertyName::IsTree, object.isTree());
63 setProperty(AXPropertyName::IsScrollbar, object.isScrollbar());
64 setProperty(AXPropertyName::RelativeFrame, object.relativeFrame());
65 setProperty(AXPropertyName::SpeechHint, object.speechHintAttributeValue().isolatedCopy());
66 setProperty(AXPropertyName::Title, object.titleAttributeValue().isolatedCopy());
67 setProperty(AXPropertyName::Description, object.descriptionAttributeValue().isolatedCopy());
68 setProperty(AXPropertyName::HelpText, object.helpTextAttributeValue().isolatedCopy());
69}
70
71void AXIsolatedTreeNode::setProperty(AXPropertyName propertyName, AttributeValueVariant&& value, bool shouldRemove)
72{
73 ASSERT(!m_initialized);
74 ASSERT(isMainThread());
75
76 if (shouldRemove)
77 m_attributeMap.remove(propertyName);
78 else
79 m_attributeMap.set(propertyName, value);
80}
81
82void AXIsolatedTreeNode::appendChild(AXID axID)
83{
84 ASSERT(isMainThread());
85 m_children.append(axID);
86}
87
88void AXIsolatedTreeNode::setParent(AXID parent)
89{
90 ASSERT(isMainThread());
91 m_parent = parent;
92}
93
94void AXIsolatedTreeNode::setTreeIdentifier(AXIsolatedTreeID treeIdentifier)
95{
96 m_treeIdentifier = treeIdentifier;
97 if (auto tree = AXIsolatedTree::treeForID(m_treeIdentifier))
98 m_cachedTree = makeWeakPtr(tree.get());
99}
100
101AccessibilityObjectInterface* AXIsolatedTreeNode::focusedUIElement() const
102{
103 if (auto focusedElement = tree()->focusedUIElement())
104 return focusedElement.get();
105 return nullptr;
106}
107
108AccessibilityObjectInterface* AXIsolatedTreeNode::parentObjectInterfaceUnignored() const
109{
110 return tree()->nodeForID(parent()).get();
111}
112
113AccessibilityObjectInterface* AXIsolatedTreeNode::accessibilityHitTest(const IntPoint& point) const
114{
115 if (!relativeFrame().contains(point))
116 return nullptr;
117 for (auto childID : children()) {
118 auto child = tree()->nodeForID(childID);
119 ASSERT(child);
120 if (child && child->relativeFrame().contains(point))
121 return child->accessibilityHitTest(point);
122 }
123 return const_cast<AXIsolatedTreeNode*>(this);
124}
125
126AXIsolatedTree* AXIsolatedTreeNode::tree() const
127{
128 return m_cachedTree.get();
129}
130
131FloatRect AXIsolatedTreeNode::rectAttributeValue(AXPropertyName propertyName) const
132{
133 auto value = m_attributeMap.get(propertyName);
134 return WTF::switchOn(value,
135 [&zeroRect] (Optional<FloatRect> typedValue) {
136 if (!typedValue)
137 return FloatRect { };
138 return typedValue.value();
139 },
140 [] (auto&) { return FloatRect { }; }
141 );
142}
143
144double AXIsolatedTreeNode::doubleAttributeValue(AXPropertyName propertyName) const
145{
146 auto value = m_attributeMap.get(propertyName);
147 return WTF::switchOn(value,
148 [&] (double& typedValue) { return typedValue; },
149 [] (auto&) { return 0; }
150 );
151}
152
153unsigned AXIsolatedTreeNode::unsignedAttributeValue(AXPropertyName propertyName) const
154{
155 auto value = m_attributeMap.get(propertyName);
156 return WTF::switchOn(value,
157 [&] (unsigned& typedValue) { return typedValue; },
158 [] (auto&) { return 0; }
159 );
160}
161
162bool AXIsolatedTreeNode::boolAttributeValue(AXPropertyName propertyName) const
163{
164 auto value = m_attributeMap.get(propertyName);
165 return WTF::switchOn(value,
166 [&] (bool& typedValue) { return typedValue; },
167 [] (auto&) { return false; }
168 );
169}
170
171const String AXIsolatedTreeNode::stringAttributeValue(AXPropertyName propertyName) const
172{
173 auto value = m_attributeMap.get(propertyName);
174 return WTF::switchOn(value,
175 [&] (String& typedValue) { return typedValue; },
176 [] (auto&) { return emptyString(); }
177 );
178}
179
180int AXIsolatedTreeNode::intAttributeValue(AXPropertyName propertyName) const
181{
182 auto value = m_attributeMap.get(propertyName);
183 return WTF::switchOn(value,
184 [&] (int& typedValue) { return typedValue; },
185 [] (auto&) { return 0; }
186 );
187}
188
189} // namespace WebCore
190
191#endif // ENABLE((ACCESSIBILITY_ISOLATED_TREE)
192