AX: AXIsolatedTree::updateChildren sometimes fails to update isolated subtrees when...
[webkit.git] / Source / WebCore / accessibility / isolatedtree / AXIsolatedTree.h
blob0317b2ee887e530ccd54c160808a8d2b518b3568
1 /*
2 * Copyright (C) 2019 Apple Inc. All rights reserved.
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.
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 #pragma once
28 #if ENABLE(ACCESSIBILITY_ISOLATED_TREE)
30 #include "AccessibilityObjectInterface.h"
31 #include "PageIdentifier.h"
32 #include <pal/SessionID.h>
33 #include <wtf/HashMap.h>
34 #include <wtf/Lock.h>
35 #include <wtf/RefPtr.h>
36 #include <wtf/ThreadSafeRefCounted.h>
38 namespace WTF {
39 class TextStream;
42 namespace WebCore {
44 class AXIsolatedObject;
45 class AXObjectCache;
46 class Page;
47 enum class AXStreamOptions : uint8_t;
49 using AXIsolatedTreeID = unsigned;
51 enum class AXPropertyName : uint16_t {
52 ARIAIsMultiline,
53 ARIALandmarkRoleDescription,
54 ARIATreeItemContent,
55 ARIATreeRows,
56 ARIARoleAttribute,
57 AXColumnCount,
58 AXColumnIndex,
59 AXRowCount,
60 AXRowIndex,
61 AccessKey,
62 AccessibilityDescription,
63 AccessibilityText,
64 ActionVerb,
65 AncestorFlags,
66 AutoCompleteValue,
67 BlockquoteLevel,
68 BrailleLabel,
69 BrailleRoleDescription,
70 ButtonState,
71 CanHaveSelectedChildren,
72 CanSetExpandedAttribute,
73 CanSetFocusAttribute,
74 CanSetNumericValue,
75 CanSetSelectedAttribute,
76 CanSetSelectedChildren,
77 CanSetTextRangeAttributes,
78 CanSetValueAttribute,
79 CanvasHasFallbackContent,
80 #if PLATFORM(MAC)
81 CaretBrowsingEnabled,
82 #endif
83 Cells,
84 ClassList,
85 ClickPoint,
86 ColorValue,
87 Columns,
88 ColumnCount,
89 ColumnHeader,
90 ColumnHeaders,
91 ColumnIndex,
92 ColumnIndexRange,
93 ComputedRoleString,
94 Contents,
95 CurrentState,
96 CurrentValue,
97 DatetimeAttributeValue,
98 DecrementButton,
99 Description,
100 DisclosedByRow,
101 DisclosedRows,
102 DocumentEncoding,
103 DocumentLinks,
104 DocumentURI,
105 DropEffects,
106 EditableAncestor,
107 EmbeddedImageDescription,
108 ExpandedTextValue,
109 FileUploadButtonReturnsValueInTitle,
110 FocusableAncestor,
111 HasARIAValueNow,
112 HasApplePDFAnnotationAttribute,
113 HasBoldFont,
114 HasHighlighting,
115 HasItalicFont,
116 HasPlainText,
117 HasPopup,
118 HasUnderline,
119 HeaderContainer,
120 HeadingLevel,
121 HelpText,
122 HierarchicalLevel,
123 HighestEditableAncestor,
124 HorizontalScrollBar,
125 IdentifierAttribute,
126 IncrementButton,
127 InnerHTML,
128 InvalidStatus,
129 IsActiveDescendantOfFocusedContainer,
130 IsAnonymousMathOperator,
131 IsGrabbed,
132 IsARIATreeGridRow,
133 IsAttachment,
134 IsButton,
135 IsBusy,
136 IsChecked,
137 IsCollapsed,
138 IsColumnHeaderCell,
139 IsControl,
140 IsDataTable,
141 IsDescriptionList,
142 IsEnabled,
143 IsExpanded,
144 IsExposable,
145 IsFieldset,
146 IsFileUploadButton,
147 IsFocused,
148 IsGroup,
149 IsImageMapLink,
150 IsIncrementor,
151 IsIndeterminate,
152 IsInlineText,
153 IsInputImage,
154 IsInsideLiveRegion,
155 IsHeading,
156 IsHovered,
157 IsKeyboardFocusable,
158 IsLandmark,
159 IsLink,
160 IsLinked,
161 IsList,
162 IsListBox,
163 IsMathElement,
164 IsMathFraction,
165 IsMathFenced,
166 IsMathSubscriptSuperscript,
167 IsMathRow,
168 IsMathUnderOver,
169 IsMathRoot,
170 IsMathSquareRoot,
171 IsMathText,
172 IsMathNumber,
173 IsMathOperator,
174 IsMathFenceOperator,
175 IsMathSeparatorOperator,
176 IsMathIdentifier,
177 IsMathTable,
178 IsMathTableRow,
179 IsMathTableCell,
180 IsMathMultiscript,
181 IsMathToken,
182 IsMathScriptObject,
183 IsMediaTimeline,
184 IsMenu,
185 IsMenuBar,
186 IsMenuButton,
187 IsMenuItem,
188 IsMenuList,
189 IsMenuListOption,
190 IsMenuListPopup,
191 IsMenuRelated,
192 IsMeter,
193 IsMultiSelectable,
194 IsOrderedList,
195 IsOutput,
196 IsPasswordField,
197 IsPressed,
198 IsProgressIndicator,
199 IsRangeControl,
200 IsRequired,
201 IsRowHeaderCell,
202 IsScrollbar,
203 IsSearchField,
204 IsSelected,
205 IsSelectedOptionActive,
206 IsShowingValidationMessage,
207 IsSlider,
208 IsStyleFormatGroup,
209 IsTable,
210 IsTableCell,
211 IsTableColumn,
212 IsTableRow,
213 IsTextControl,
214 IsTree,
215 IsTreeItem,
216 IsUnorderedList,
217 IsUnvisited,
218 IsValueAutofilled,
219 IsValueAutofillAvailable,
220 IsVisible,
221 IsVisited,
222 IsWidget,
223 KeyShortcutsValue,
224 Language,
225 LayoutCount,
226 LinkRelValue,
227 LinkedObjects,
228 LiveRegionAtomic,
229 LiveRegionRelevant,
230 LiveRegionStatus,
231 LocalizedActionVerb,
232 MathFencedOpenString,
233 MathFencedCloseString,
234 MathLineThickness,
235 MathPrescripts,
236 MathPostscripts,
237 MathRadicand,
238 MathRootIndexObject,
239 MathUnderObject,
240 MathOverObject,
241 MathNumeratorObject,
242 MathDenominatorObject,
243 MathBaseObject,
244 MathSubscriptObject,
245 MathSuperscriptObject,
246 MaxValueForRange,
247 MinValueForRange,
248 NameAttribute,
249 Orientation,
250 OuterHTML,
251 Path,
252 PlaceholderValue,
253 PressedIsPresent,
254 PopupValue,
255 PosInSet,
256 PreventKeyboardDOMEventDispatch,
257 ReadOnlyValue,
258 RoleValue,
259 RolePlatformString,
260 RoleDescription,
261 Rows,
262 RowCount,
263 RowHeaders,
264 RowIndex,
265 RowIndexRange,
266 SelectedChildren,
267 SelectedRadioButton,
268 SelectedTabItem,
269 SessionID,
270 SetSize,
271 SortDirection,
272 SpeakAs,
273 SpeechHint,
274 StringValue,
275 SubrolePlatformString,
276 SupportsRowCountChange,
277 SupportsDragging,
278 SupportsDropping,
279 SupportsARIAOwns,
280 SupportsCheckedState,
281 SupportsCurrent,
282 SupportsDatetimeAttribute,
283 SupportsExpanded,
284 SupportsExpandedTextValue,
285 SupportsLiveRegion,
286 SupportsPath,
287 SupportsPosInSet,
288 SupportsPressAction,
289 SupportsRangeValue,
290 SupportsRequiredAttribute,
291 SupportsSelectedRows,
292 SupportsSetSize,
293 TabChildren,
294 TableLevel,
295 TagName,
296 TextLength,
297 Title,
298 TitleAttributeValue,
299 TitleUIElement,
300 URL,
301 ValueAutofillButtonType,
302 ValueDescription,
303 ValueForRange,
304 ValidationMessage,
305 VerticalScrollBar,
306 VisibleChildren,
307 VisibleRows,
308 WebArea,
311 using AXPropertyValueVariant = std::variant<std::nullptr_t, AXID, String, bool, int, unsigned, double, float, uint64_t, AccessibilityButtonState, Color, URL, LayoutRect, FloatRect, PAL::SessionID, IntPoint, OptionSet<SpeakAs>, std::pair<unsigned, unsigned>, Vector<AccessibilityText>, Vector<AXID>, Vector<std::pair<AXID, AXID>>, Vector<String>, Path, OptionSet<AXAncestorFlag>>;
312 using AXPropertyMap = HashMap<AXPropertyName, AXPropertyValueVariant, IntHash<AXPropertyName>, WTF::StrongEnumHashTraits<AXPropertyName>>;
314 struct AXPropertyChange {
315 AXID axID; // ID of the object whose properties changed.
316 AXPropertyMap properties; // Changed properties.
319 class AXIsolatedTree : public ThreadSafeRefCounted<AXIsolatedTree> {
320 WTF_MAKE_NONCOPYABLE(AXIsolatedTree); WTF_MAKE_FAST_ALLOCATED;
321 friend WTF::TextStream& operator<<(WTF::TextStream&, AXIsolatedTree&);
322 friend void streamIsolatedSubtreeOnMainThread(TextStream&, const AXIsolatedTree&, AXID, const OptionSet<AXStreamOptions>&);
323 public:
324 static Ref<AXIsolatedTree> create(AXObjectCache*);
325 virtual ~AXIsolatedTree();
327 static void removeTreeForPageID(PageIdentifier);
329 static RefPtr<AXIsolatedTree> treeForPageID(PageIdentifier);
330 static RefPtr<AXIsolatedTree> treeForID(AXIsolatedTreeID);
331 AXObjectCache* axObjectCache() const;
333 RefPtr<AXIsolatedObject> rootNode();
334 RefPtr<AXIsolatedObject> focusedNode();
335 RefPtr<AXIsolatedObject> nodeForID(const AXID&) const;
336 Vector<RefPtr<AXCoreObject>> objectsForIDs(const Vector<AXID>&);
338 struct NodeChange {
339 Ref<AXIsolatedObject> isolatedObject;
340 #if PLATFORM(COCOA)
341 RetainPtr<AccessibilityObjectWrapper> wrapper;
342 #elif USE(ATSPI)
343 RefPtr<AccessibilityObjectWrapper> wrapper;
344 #endif
347 void generateSubtree(AXCoreObject&);
348 void updateNode(AXCoreObject&);
349 enum class ResolveNodeChanges : bool { No, Yes };
350 void updateChildren(AXCoreObject&, ResolveNodeChanges = ResolveNodeChanges::Yes);
351 void updateNodeProperty(AXCoreObject&, AXPropertyName);
352 void updateNodeAndDependentProperties(AXCoreObject&);
354 double loadingProgress() { return m_loadingProgress; }
355 void updateLoadingProgress(double);
357 // Removes the corresponding isolated object and all descendants from the m_nodeMap and queues their removal from the tree.
358 void removeNode(const AXCoreObject&);
359 // Removes the given node and all its descendants from m_nodeMap.
360 void removeSubtreeFromNodeMap(AXID axID, AXCoreObject*);
362 // Both setRootNodeID and setFocusedNodeID are called during the generation
363 // of the IsolatedTree.
364 // Focused node updates in AXObjectCache use setFocusNodeID.
365 void setRootNode(AXIsolatedObject*) WTF_REQUIRES_LOCK(m_changeLogLock);
366 void setFocusedNodeID(AXID);
368 // Relationships between objects.
369 std::optional<Vector<AXID>> relatedObjectIDsFor(const AXCoreObject&, AXRelationType);
370 void relationsNeedUpdate(bool needUpdate) { m_relationsNeedUpdate = needUpdate; }
372 // Called on AX thread from WebAccessibilityObjectWrapper methods.
373 // During layout tests, it is called on the main thread.
374 void applyPendingChanges();
376 AXIsolatedTreeID treeID() const { return m_treeID; }
378 private:
379 AXIsolatedTree(AXObjectCache*);
380 void clear();
382 static Lock s_cacheLock;
383 static HashMap<AXIsolatedTreeID, Ref<AXIsolatedTree>>& treeIDCache() WTF_REQUIRES_LOCK(s_cacheLock);
384 static HashMap<PageIdentifier, Ref<AXIsolatedTree>>& treePageCache() WTF_REQUIRES_LOCK(s_cacheLock);
386 enum class AttachWrapper : bool { OnMainThread, OnAXThread };
387 std::optional<NodeChange> nodeChangeForObject(Ref<AXCoreObject>, AttachWrapper = AttachWrapper::OnMainThread);
388 void collectNodeChangesForSubtree(AXCoreObject&);
389 bool isCollectingNodeChanges() const { return m_collectingNodeChangesAtTreeLevel > 0; }
390 void queueChange(const NodeChange&) WTF_REQUIRES_LOCK(m_changeLogLock);
391 void queueRemovals(const Vector<AXID>&);
392 void queueRemovalsLocked(const Vector<AXID>&) WTF_REQUIRES_LOCK(m_changeLogLock);
393 void queueRemovalsAndUnresolvedChanges(const Vector<AXID>&);
395 AXIsolatedTreeID m_treeID;
396 unsigned m_maxTreeDepth { 0 };
397 AXObjectCache* m_axObjectCache { nullptr };
398 bool m_usedOnAXThread { true };
400 // Stores the parent ID and children IDS for a given IsolatedObject.
401 struct ParentChildrenIDs {
402 AXID parentID;
403 Vector<AXID> childrenIDs;
405 // Only accessed on the main thread.
406 // A representation of the tree's parent-child relationships. Each
407 // IsolatedObject must have one and only one entry in this map, that maps
408 // its ObjectID to its ParentChildrenIDs struct.
409 HashMap<AXID, ParentChildrenIDs> m_nodeMap;
411 // Only accessed on the main thread.
412 // The key is the ID of the object that will be resolved into an m_pendingAppends NodeChange.
413 // The value is whether the wrapper should be attached on the main thread or the AX thread.
414 HashMap<AXID, AttachWrapper> m_unresolvedPendingAppends;
415 // 1-based tree level, 0 = not collecting. Only accessed on the main thread.
416 unsigned m_collectingNodeChangesAtTreeLevel { 0 };
418 // Only accessed on AX thread requesting data.
419 HashMap<AXID, Ref<AXIsolatedObject>> m_readerThreadNodeMap;
421 // Written to by main thread under lock, accessed and applied by AX thread.
422 RefPtr<AXIsolatedObject> m_rootNode WTF_GUARDED_BY_LOCK(m_changeLogLock);
423 Vector<NodeChange> m_pendingAppends WTF_GUARDED_BY_LOCK(m_changeLogLock); // Nodes to be added to the tree and platform-wrapped.
424 Vector<AXPropertyChange> m_pendingPropertyChanges WTF_GUARDED_BY_LOCK(m_changeLogLock);
425 Vector<AXID> m_pendingSubtreeRemovals WTF_GUARDED_BY_LOCK(m_changeLogLock); // Nodes whose subtrees are to be removed from the tree.
426 Vector<std::pair<AXID, Vector<AXID>>> m_pendingChildrenUpdates WTF_GUARDED_BY_LOCK(m_changeLogLock);
427 AXID m_pendingFocusedNodeID WTF_GUARDED_BY_LOCK(m_changeLogLock);
428 AXID m_focusedNodeID;
429 std::atomic<double> m_loadingProgress { 0 };
431 // Relationships between objects.
432 // Accessed only on the AX thread.
433 HashMap<AXID, AXRelations> m_relations;
434 // Set to true by the AXObjectCache on the main thread.
435 // Set to false on the AX thread by relatedObjectIDsFor.
436 std::atomic<bool> m_relationsNeedUpdate { true };
438 Lock m_changeLogLock;
441 inline AXObjectCache* AXIsolatedTree::axObjectCache() const
443 ASSERT(isMainThread());
444 return m_axObjectCache;
447 } // namespace WebCore
449 #endif