AX: Make AXIsolatedTree compile again
[WebKit-https.git] / Source / WebCore / accessibility / isolatedtree / AXIsolatedTree.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 "AXIsolatedTree.h"
30
31 #include "AXIsolatedTreeNode.h"
32 #include "Page.h"
33 #include <wtf/NeverDestroyed.h>
34
35 namespace WebCore {
36
37 static Lock s_cacheLock;
38
39 static unsigned newTreeID()
40 {
41     static unsigned s_currentTreeID = 0;
42     return ++s_currentTreeID;
43 }
44
45 HashMap<PageIdentifier, Ref<AXIsolatedTree>>& AXIsolatedTree::treePageCache()
46 {
47     static NeverDestroyed<HashMap<PageIdentifier, Ref<AXIsolatedTree>>> map;
48     return map;
49 }
50
51 HashMap<AXIsolatedTreeID, Ref<AXIsolatedTree>>& AXIsolatedTree::treeIDCache()
52 {
53     static NeverDestroyed<HashMap<AXIsolatedTreeID, Ref<AXIsolatedTree>>> map;
54     return map;
55 }
56
57 AXIsolatedTree::AXIsolatedTree()
58     : m_treeID(newTreeID())
59 {
60 }
61
62 AXIsolatedTree::~AXIsolatedTree() = default;
63
64 Ref<AXIsolatedTree> AXIsolatedTree::create()
65 {
66     ASSERT(isMainThread());
67     return adoptRef(*new AXIsolatedTree());
68 }
69
70 RefPtr<AXIsolatedTreeNode> AXIsolatedTree::nodeInTreeForID(AXIsolatedTreeID treeID, AXID axID)
71 {
72     return treeForID(treeID)->nodeForID(axID);
73 }
74
75 RefPtr<AXIsolatedTree> AXIsolatedTree::treeForID(AXIsolatedTreeID treeID)
76 {
77     return treeIDCache().get(treeID);
78 }
79
80 Ref<AXIsolatedTree> AXIsolatedTree::createTreeForPageID(PageIdentifier pageID)
81 {
82     LockHolder locker(s_cacheLock);
83
84     auto newTree = AXIsolatedTree::create();
85     treePageCache().set(pageID, newTree.copyRef());
86     treeIDCache().set(newTree->treeIdentifier(), newTree.copyRef());
87     return newTree;
88 }
89
90 RefPtr<AXIsolatedTree> AXIsolatedTree::treeForPageID(PageIdentifier pageID)
91 {
92     LockHolder locker(s_cacheLock);
93
94     if (auto tree = treePageCache().get(pageID))
95         return makeRefPtr(tree);
96
97     return nullptr;
98 }
99
100 RefPtr<AXIsolatedTreeNode> AXIsolatedTree::nodeForID(AXID axID) const
101 {
102     if (!axID)
103         return nullptr;
104     return m_readerThreadNodeMap.get(axID);
105 }
106
107 RefPtr<AXIsolatedTreeNode> AXIsolatedTree::focusedUIElement()
108 {
109     return nodeForID(m_focusedNodeID);
110 }
111     
112 RefPtr<AXIsolatedTreeNode> AXIsolatedTree::rootNode()
113 {
114     return nodeForID(m_rootNodeID);
115 }
116
117 void AXIsolatedTree::setRootNodeID(AXID axID)
118 {
119     LockHolder locker { m_changeLogLock };
120     m_pendingRootNodeID = axID;
121 }
122     
123 void AXIsolatedTree::setFocusedNodeID(AXID axID)
124 {
125     LockHolder locker { m_changeLogLock };
126     m_pendingFocusedNodeID = axID;
127 }
128     
129 void AXIsolatedTree::removeNode(AXID axID)
130 {
131     LockHolder locker { m_changeLogLock };
132     m_pendingRemovals.append(axID);
133 }
134
135 void AXIsolatedTree::appendNodeChanges(Vector<Ref<AXIsolatedTreeNode>>& log)
136 {
137     LockHolder locker { m_changeLogLock };
138     for (auto& node : log)
139         m_pendingAppends.append(node.copyRef());
140 }
141
142 void AXIsolatedTree::applyPendingChanges()
143 {
144     RELEASE_ASSERT(!isMainThread());
145     LockHolder locker { m_changeLogLock };
146     Vector<Ref<AXIsolatedTreeNode>> appendCopy;
147     std::swap(appendCopy, m_pendingAppends);
148     Vector<AXID> removeCopy({ WTFMove(m_pendingRemovals) });
149     locker.unlockEarly();
150
151     // We don't clear the pending IDs beacause if the next round of updates does not modify them, then they stay the same
152     // value without extra bookkeeping.
153     m_rootNodeID = m_pendingRootNodeID;
154     m_focusedNodeID = m_pendingFocusedNodeID;
155     
156     for (auto& item : appendCopy)
157         m_readerThreadNodeMap.add(item->identifier(), WTFMove(item));
158
159     for (auto item : removeCopy)
160         m_readerThreadNodeMap.remove(item);
161 }
162     
163 } // namespace WebCore
164
165 #endif // ENABLE(ACCESSIBILITY_ISOLATED_TREE)