Source/JavaScriptCore:
[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 #if ENABLE(ACCESSIBILITY_ISOLATED_TREE)
27
28 #include "config.h"
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<AXIsolatedTreeID, Ref<AXIsolatedTree>>& AXIsolatedTree::treePageCache()
46 {
47     static NeverDestroyed<HashMap<AXIsolatedTreeID, 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<AXIsolatedTree> AXIsolatedTree::treeForID(AXIsolatedTreeID treeID)
71 {
72     return treeIDCache().get(treeID);
73 }
74
75 Ref<AXIsolatedTree> AXIsolatedTree::createTreeForPageID(uint64_t pageID)
76 {
77     LockHolder locker(s_cacheLock);
78
79     auto newTree = AXIsolatedTree::create();
80     treePageCache().set(pageID, newTree.copyRef());
81     treeIDCache().set(newTree->treeIdentifier(), newTree.copyRef());
82     return newTree;
83 }
84
85 RefPtr<AXIsolatedTree> AXIsolatedTree::treeForPageID(uint64_t pageID)
86 {
87     LockHolder locker(s_cacheLock);
88
89     if (auto tree = treePageCache().get(pageID))
90         return makeRefPtr(tree);
91
92     return nullptr;
93 }
94
95 RefPtr<AXIsolatedTreeNode> AXIsolatedTree::nodeForID(AXID axID) const
96 {
97     ASSERT(!isMainThread());
98     if (!axID)
99         return nullptr;
100     return m_readerThreadNodeMap.get(axID);
101 }
102
103 RefPtr<AXIsolatedTreeNode> AXIsolatedTree::rootNode()
104 {
105     return nodeForID(m_rootNodeID);
106 }
107
108 void AXIsolatedTree::removeNode(AXID axID)
109 {
110     LockHolder locker(m_changeLogLock);
111     m_pendingRemovals.append(axID);
112 }
113
114 void AXIsolatedTree::appendNodeChanges(Vector<Ref<AXIsolatedTreeNode>>& log)
115 {
116     LockHolder locker(m_changeLogLock);
117     for (auto& node : log)
118         m_pendingAppends.append(node.copyRef());
119 }
120
121 void AXIsolatedTree::applyPendingChanges()
122 {
123     RELEASE_ASSERT(!isMainThread());
124
125     LockHolder locker(m_changeLogLock);
126     Vector<Ref<AXIsolatedTreeNode>> appendCopy;
127     std::swap(appendCopy, m_pendingAppends);
128     Vector<AXID> removeCopy({ WTFMove(m_pendingRemovals) });
129     locker.unlockEarly();
130
131     for (auto& item : appendCopy) {
132         m_readerThreadNodeMap.add(item->identifier(), item.copyRef());
133         if (item->isRootNode())
134             m_rootNodeID = item->identifier();
135     }
136
137     for (auto item : removeCopy)
138         m_readerThreadNodeMap.remove(item);
139 }
140     
141 } // namespace WebCore
142
143 #endif // ENABLE(ACCESSIBILITY_ISOLATED_TREE)