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
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.
28 #if ENABLE(ACCESSIBILITY_ISOLATED_TREE)
30 #include "AccessibilityObjectInterface.h"
31 #include "PageIdentifier.h"
32 #include <pal/SessionID.h>
33 #include <wtf/HashMap.h>
35 #include <wtf/RefPtr.h>
36 #include <wtf/ThreadSafeRefCounted.h>
44 class AXIsolatedObject
;
47 enum class AXStreamOptions
: uint8_t;
49 using AXIsolatedTreeID
= unsigned;
51 enum class AXPropertyName
: uint16_t {
53 ARIALandmarkRoleDescription
,
62 AccessibilityDescription
,
69 BrailleRoleDescription
,
71 CanHaveSelectedChildren
,
72 CanSetExpandedAttribute
,
75 CanSetSelectedAttribute
,
76 CanSetSelectedChildren
,
77 CanSetTextRangeAttributes
,
79 CanvasHasFallbackContent
,
97 DatetimeAttributeValue
,
107 EmbeddedImageDescription
,
109 FileUploadButtonReturnsValueInTitle
,
112 HasApplePDFAnnotationAttribute
,
123 HighestEditableAncestor
,
129 IsActiveDescendantOfFocusedContainer
,
130 IsAnonymousMathOperator
,
166 IsMathSubscriptSuperscript
,
175 IsMathSeparatorOperator
,
205 IsSelectedOptionActive
,
206 IsShowingValidationMessage
,
219 IsValueAutofillAvailable
,
232 MathFencedOpenString
,
233 MathFencedCloseString
,
242 MathDenominatorObject
,
245 MathSuperscriptObject
,
256 PreventKeyboardDOMEventDispatch
,
275 SubrolePlatformString
,
276 SupportsRowCountChange
,
280 SupportsCheckedState
,
282 SupportsDatetimeAttribute
,
284 SupportsExpandedTextValue
,
290 SupportsRequiredAttribute
,
291 SupportsSelectedRows
,
301 ValueAutofillButtonType
,
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
>&);
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
>&);
339 Ref
<AXIsolatedObject
> isolatedObject
;
341 RetainPtr
<AccessibilityObjectWrapper
> wrapper
;
343 RefPtr
<AccessibilityObjectWrapper
> wrapper
;
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
; }
379 AXIsolatedTree(AXObjectCache
*);
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
{
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