AX: Update the isolated tree in response to dynamic aria-haspopup and aria-describedb...
[webkit.git] / Source / WebCore / accessibility / AXObjectCache.h
blobf0739b6bbfdcd603f08a000d58dae95872d1fdd1
1 /*
2 * Copyright (C) 2003, 2006, 2007, 2008, 2009, 2010, 2011, 2015 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 #include "AXIsolatedTree.h"
29 #include "AXTextStateChangeIntent.h"
30 #include "AccessibilityObject.h"
31 #include "SimpleRange.h"
32 #include "Timer.h"
33 #include "VisibleUnits.h"
34 #include <limits.h>
35 #include <wtf/HashMap.h>
36 #include <wtf/HashSet.h>
37 #include <wtf/ListHashSet.h>
38 #include <wtf/WeakHashSet.h>
40 namespace WTF {
41 class TextStream;
44 namespace WebCore {
46 class Document;
47 class HTMLAreaElement;
48 class HTMLTextFormControlElement;
49 class Node;
50 class Page;
51 class RenderBlock;
52 class RenderObject;
53 class RenderText;
54 class ScrollView;
55 class VisiblePosition;
56 class Widget;
58 struct TextMarkerData {
59 AXID axID;
61 Node* node { nullptr };
62 unsigned offset { 0 };
63 Position::AnchorType anchorType { Position::PositionIsOffsetInAnchor };
64 Affinity affinity { Affinity::Downstream };
66 int characterStartIndex { 0 };
67 int characterOffset { 0 };
68 bool ignored { false };
71 struct CharacterOffset {
72 Node* node;
73 int startIndex;
74 int offset;
75 int remainingOffset;
77 CharacterOffset(Node* n = nullptr, int startIndex = 0, int offset = 0, int remaining = 0)
78 : node(n)
79 , startIndex(startIndex)
80 , offset(offset)
81 , remainingOffset(remaining)
82 { }
84 int remaining() const { return remainingOffset; }
85 bool isNull() const { return !node; }
86 bool isEqual(const CharacterOffset& other) const
88 if (isNull() || other.isNull())
89 return false;
90 return node == other.node && startIndex == other.startIndex && offset == other.offset;
94 class AXComputedObjectAttributeCache {
95 WTF_MAKE_FAST_ALLOCATED;
96 public:
97 AccessibilityObjectInclusion getIgnored(AXID) const;
98 void setIgnored(AXID, AccessibilityObjectInclusion);
100 private:
101 struct CachedAXObjectAttributes {
102 CachedAXObjectAttributes()
103 : ignored(AccessibilityObjectInclusion::DefaultBehavior)
106 AccessibilityObjectInclusion ignored;
109 HashMap<AXID, CachedAXObjectAttributes> m_idMapping;
112 struct VisiblePositionIndex {
113 int value = -1;
114 RefPtr<ContainerNode> scope;
117 struct VisiblePositionIndexRange {
118 VisiblePositionIndex startIndex;
119 VisiblePositionIndex endIndex;
120 bool isNull() const { return startIndex.value == -1 || endIndex.value == -1; }
123 struct AXTreeData {
124 String liveTree;
125 String isolatedTree;
128 class AccessibilityReplacedText {
129 public:
130 AccessibilityReplacedText() = default;
131 AccessibilityReplacedText(const VisibleSelection&);
132 void postTextStateChangeNotification(AXObjectCache*, AXTextEditType, const String&, const VisibleSelection&);
133 const VisiblePositionIndexRange& replacedRange() { return m_replacedRange; }
134 protected:
135 String m_replacedText;
136 VisiblePositionIndexRange m_replacedRange;
139 #if !PLATFORM(COCOA)
140 enum AXTextChange { AXTextInserted, AXTextDeleted, AXTextAttributesChanged };
141 #endif
143 enum class PostTarget { Element, ObservableParent };
145 class AXObjectCache {
146 WTF_MAKE_NONCOPYABLE(AXObjectCache); WTF_MAKE_FAST_ALLOCATED;
147 friend class AXIsolatedTree;
148 friend WTF::TextStream& operator<<(WTF::TextStream&, AXObjectCache&);
149 public:
150 explicit AXObjectCache(Document&);
151 ~AXObjectCache();
153 // Returns the root object for the entire document.
154 WEBCORE_EXPORT AXCoreObject* rootObject();
155 // Returns the root object for a specific frame.
156 WEBCORE_EXPORT AccessibilityObject* rootObjectForFrame(Frame*);
158 // For AX objects with elements that back them.
159 AccessibilityObject* getOrCreate(RenderObject*);
160 AccessibilityObject* getOrCreate(Widget*);
161 WEBCORE_EXPORT AccessibilityObject* getOrCreate(Node*);
163 // used for objects without backing elements
164 AccessibilityObject* create(AccessibilityRole);
166 // will only return the AccessibilityObject if it already exists
167 AccessibilityObject* get(RenderObject*);
168 AccessibilityObject* get(Widget*);
169 AccessibilityObject* get(Node*);
171 void remove(RenderObject*);
172 void remove(Node&);
173 void remove(Widget*);
174 void remove(AXID);
176 #if !PLATFORM(COCOA) && !USE(ATSPI)
177 void detachWrapper(AXCoreObject*, AccessibilityDetachmentType);
178 #endif
179 private:
180 using DOMObjectVariant = std::variant<std::nullptr_t, RenderObject*, Node*, Widget*>;
181 void cacheAndInitializeWrapper(AccessibilityObject*, DOMObjectVariant = nullptr);
182 void attachWrapper(AXCoreObject*);
184 public:
185 void childrenChanged(Node*, Node* newChild = nullptr);
186 void childrenChanged(RenderObject*, RenderObject* newChild = nullptr);
187 void childrenChanged(AccessibilityObject*);
188 void checkedStateChanged(Node*);
189 void handleRoleChange(AccessibilityObject*);
190 // Called when a node has just been attached, so we can make sure we have the right subclass of AccessibilityObject.
191 void updateCacheAfterNodeIsAttached(Node*);
192 void updateLoadingProgress(double);
193 void loadingFinished() { updateLoadingProgress(1); }
194 double loadingProgress() const { return m_loadingProgress; }
196 void deferFocusedUIElementChangeIfNeeded(Node* oldFocusedNode, Node* newFocusedNode);
197 void deferModalChange(Element*);
198 void deferMenuListValueChange(Element*);
199 void deferNodeAddedOrRemoved(Node*);
200 void handleScrolledToAnchor(const Node* anchorNode);
201 void handleScrollbarUpdate(ScrollView*);
203 bool isRetrievingCurrentModalNode() { return m_isRetrievingCurrentModalNode; }
204 Node* modalNode();
206 void deferAttributeChangeIfNeeded(const QualifiedName&, Element*);
207 void recomputeIsIgnored(RenderObject*);
208 void recomputeIsIgnored(Node*);
210 WEBCORE_EXPORT static void enableAccessibility();
211 WEBCORE_EXPORT static void disableAccessibility();
213 WEBCORE_EXPORT AccessibilityObject* focusedObjectForPage(const Page*);
215 // Enhanced user interface accessibility can be toggled by the assistive technology.
216 WEBCORE_EXPORT static void setEnhancedUserInterfaceAccessibility(bool flag);
218 // Note: these may be called from a non-main thread concurrently as other readers.
219 static bool accessibilityEnabled() { return gAccessibilityEnabled; }
220 static bool accessibilityEnhancedUserInterfaceEnabled() { return gAccessibilityEnhancedUserInterfaceEnabled; }
222 const Element* rootAXEditableElement(const Node*);
223 bool nodeIsTextControl(const Node*);
225 AXID platformGenerateAXID() const;
226 AccessibilityObject* objectFromAXID(AXID id) const { return m_objects.get(id); }
227 Vector<RefPtr<AXCoreObject>> objectsForIDs(const Vector<AXID>&) const;
229 // Text marker utilities.
230 std::optional<TextMarkerData> textMarkerDataForVisiblePosition(const VisiblePosition&);
231 std::optional<TextMarkerData> textMarkerDataForFirstPositionInTextControl(HTMLTextFormControlElement&);
232 void textMarkerDataForCharacterOffset(TextMarkerData&, const CharacterOffset&);
233 void textMarkerDataForNextCharacterOffset(TextMarkerData&, const CharacterOffset&);
234 void textMarkerDataForPreviousCharacterOffset(TextMarkerData&, const CharacterOffset&);
235 VisiblePosition visiblePositionForTextMarkerData(TextMarkerData&);
236 CharacterOffset characterOffsetForTextMarkerData(TextMarkerData&);
237 // Use ignoreNextNodeStart/ignorePreviousNodeEnd to determine the behavior when we are at node boundary.
238 CharacterOffset nextCharacterOffset(const CharacterOffset&, bool ignoreNextNodeStart = true);
239 CharacterOffset previousCharacterOffset(const CharacterOffset&, bool ignorePreviousNodeEnd = true);
240 void startOrEndTextMarkerDataForRange(TextMarkerData&, const SimpleRange&, bool);
241 CharacterOffset startOrEndCharacterOffsetForRange(const SimpleRange&, bool, bool enterTextControls = false);
242 AccessibilityObject* accessibilityObjectForTextMarkerData(TextMarkerData&);
243 std::optional<SimpleRange> rangeForUnorderedCharacterOffsets(const CharacterOffset&, const CharacterOffset&);
244 static SimpleRange rangeForNodeContents(Node&);
245 static int lengthForRange(const std::optional<SimpleRange>&);
247 // Word boundary
248 CharacterOffset nextWordEndCharacterOffset(const CharacterOffset&);
249 CharacterOffset previousWordStartCharacterOffset(const CharacterOffset&);
250 std::optional<SimpleRange> leftWordRange(const CharacterOffset&);
251 std::optional<SimpleRange> rightWordRange(const CharacterOffset&);
253 // Paragraph
254 std::optional<SimpleRange> paragraphForCharacterOffset(const CharacterOffset&);
255 CharacterOffset nextParagraphEndCharacterOffset(const CharacterOffset&);
256 CharacterOffset previousParagraphStartCharacterOffset(const CharacterOffset&);
258 // Sentence
259 std::optional<SimpleRange> sentenceForCharacterOffset(const CharacterOffset&);
260 CharacterOffset nextSentenceEndCharacterOffset(const CharacterOffset&);
261 CharacterOffset previousSentenceStartCharacterOffset(const CharacterOffset&);
263 // Bounds
264 CharacterOffset characterOffsetForPoint(const IntPoint&, AXCoreObject*);
265 IntRect absoluteCaretBoundsForCharacterOffset(const CharacterOffset&);
266 CharacterOffset characterOffsetForBounds(const IntRect&, bool);
268 // Lines
269 CharacterOffset endCharacterOffsetOfLine(const CharacterOffset&);
270 CharacterOffset startCharacterOffsetOfLine(const CharacterOffset&);
272 // Index
273 CharacterOffset characterOffsetForIndex(int, const AXCoreObject*);
274 int indexForCharacterOffset(const CharacterOffset&, AccessibilityObject*);
276 enum AXNotification {
277 AXActiveDescendantChanged,
278 AXAriaRoleChanged,
279 AXAutocorrectionOccured,
280 AXCheckedStateChanged,
281 AXChildrenChanged,
282 AXCurrentStateChanged,
283 AXDescribedByChanged,
284 AXDisabledStateChanged,
285 AXFocusedUIElementChanged,
286 AXFrameLoadComplete,
287 AXGrabbedStateChanged,
288 AXHasPopupChanged,
289 AXIdAttributeChanged,
290 AXImageOverlayChanged,
291 AXLanguageChanged,
292 AXLayoutComplete,
293 AXLoadComplete,
294 AXNewDocumentLoadComplete,
295 AXPageScrolled,
296 AXPositionInSetChanged,
297 AXSelectedChildrenChanged,
298 AXSelectedStateChanged,
299 AXSelectedTextChanged,
300 AXValueChanged,
301 AXScrolledToAnchor,
302 AXLiveRegionCreated,
303 AXLiveRegionChanged,
304 AXMenuListItemSelected,
305 AXMenuListValueChanged,
306 AXMenuClosed,
307 AXMenuOpened,
308 AXRowCountChanged,
309 AXRowCollapsed,
310 AXRowExpanded,
311 AXExpandedChanged,
312 AXInvalidStatusChanged,
313 AXPressDidSucceed,
314 AXPressDidFail,
315 AXPressedStateChanged,
316 AXReadOnlyStatusChanged,
317 AXRequiredStatusChanged,
318 AXSortDirectionChanged,
319 AXTextChanged,
320 AXElementBusyChanged,
321 AXDraggingStarted,
322 AXDraggingEnded,
323 AXDraggingEnteredDropZone,
324 AXDraggingDropped,
325 AXDraggingExitedDropZone
328 void postNotification(RenderObject*, AXNotification, PostTarget = PostTarget::Element);
329 void postNotification(Node*, AXNotification, PostTarget = PostTarget::Element);
330 void postNotification(AXCoreObject*, Document*, AXNotification, PostTarget = PostTarget::Element);
332 #ifndef NDEBUG
333 void showIntent(const AXTextStateChangeIntent&);
334 #endif
336 void setTextSelectionIntent(const AXTextStateChangeIntent&);
337 void setIsSynchronizingSelection(bool);
339 void postTextStateChangeNotification(Node*, AXTextEditType, const String&, const VisiblePosition&);
340 void postTextReplacementNotification(Node*, AXTextEditType deletionType, const String& deletedText, AXTextEditType insertionType, const String& insertedText, const VisiblePosition&);
341 void postTextReplacementNotificationForTextControl(HTMLTextFormControlElement&, const String& deletedText, const String& insertedText);
342 void postTextStateChangeNotification(Node*, const AXTextStateChangeIntent&, const VisibleSelection&);
343 void postTextStateChangeNotification(const Position&, const AXTextStateChangeIntent&, const VisibleSelection&);
344 void postLiveRegionChangeNotification(AccessibilityObject*);
345 void focusModalNode();
347 enum AXLoadingEvent {
348 AXLoadingStarted,
349 AXLoadingReloaded,
350 AXLoadingFailed,
351 AXLoadingFinished
354 void frameLoadingEventNotification(Frame*, AXLoadingEvent);
356 void prepareForDocumentDestruction(const Document&);
358 void startCachingComputedObjectAttributesUntilTreeMutates();
359 void stopCachingComputedObjectAttributes();
361 AXComputedObjectAttributeCache* computedObjectAttributeCache() { return m_computedObjectAttributeCache.get(); }
363 Document& document() const { return m_document; }
364 std::optional<PageIdentifier> pageID() const { return m_pageID; }
366 #if PLATFORM(MAC)
367 static void setShouldRepostNotificationsForTests(bool value);
368 #endif
369 void deferRecomputeIsIgnoredIfNeeded(Element*);
370 void deferRecomputeIsIgnored(Element*);
371 void deferTextChangedIfNeeded(Node*);
372 void deferSelectedChildrenChangedIfNeeded(Element&);
373 void performDeferredCacheUpdate();
374 void deferTextReplacementNotificationForTextControl(HTMLTextFormControlElement&, const String& previousValue);
376 std::optional<SimpleRange> rangeMatchesTextNearRange(const SimpleRange&, const String&);
378 static ASCIILiteral notificationPlatformName(AXNotification);
380 AXTreeData treeData();
382 // Returns the IDs of the objects that relate to the given object with the specified relationship.
383 std::optional<Vector<AXID>> relatedObjectsFor(const AXCoreObject&, AXRelationType);
385 #if ENABLE(ACCESSIBILITY_ISOLATED_TREE)
386 WEBCORE_EXPORT static bool isIsolatedTreeEnabled();
387 WEBCORE_EXPORT static bool usedOnAXThread();
388 private:
389 static bool clientSupportsIsolatedTree();
390 AXCoreObject* isolatedTreeRootObject();
391 void setIsolatedTreeFocusedObject(Node*);
392 RefPtr<AXIsolatedTree> getOrCreateIsolatedTree() const;
393 void updateIsolatedTree(AXCoreObject&, AXNotification);
394 void updateIsolatedTree(AXCoreObject*, AXNotification);
395 void updateIsolatedTree(const Vector<std::pair<RefPtr<AXCoreObject>, AXNotification>>&);
396 static void initializeSecondaryAXThread();
397 #endif
399 protected:
400 void postPlatformNotification(AXCoreObject*, AXNotification);
401 void platformHandleFocusedUIElementChanged(Node* oldFocusedNode, Node* newFocusedNode);
403 void platformPerformDeferredCacheUpdate();
405 #if PLATFORM(COCOA) || USE(ATSPI)
406 void postTextStateChangePlatformNotification(AXCoreObject*, const AXTextStateChangeIntent&, const VisibleSelection&);
407 void postTextStateChangePlatformNotification(AccessibilityObject*, AXTextEditType, const String&, const VisiblePosition&);
408 void postTextReplacementPlatformNotificationForTextControl(AXCoreObject*, const String& deletedText, const String& insertedText, HTMLTextFormControlElement&);
409 void postTextReplacementPlatformNotification(AXCoreObject*, AXTextEditType, const String&, AXTextEditType, const String&, const VisiblePosition&);
410 #else
411 static AXTextChange textChangeForEditType(AXTextEditType);
412 void nodeTextChangePlatformNotification(AccessibilityObject*, AXTextChange, unsigned, const String&);
413 #endif
415 void frameLoadingEventPlatformNotification(AccessibilityObject*, AXLoadingEvent);
416 void textChanged(AccessibilityObject*);
417 void labelChanged(Element*);
419 // This is a weak reference cache for knowing if Nodes used by TextMarkers are valid.
420 void setNodeInUse(Node* n) { m_textMarkerNodes.add(n); }
421 void removeNodeForUse(Node& n) { m_textMarkerNodes.remove(&n); }
422 bool isNodeInUse(Node* n) { return m_textMarkerNodes.contains(n); }
424 // CharacterOffset functions.
425 enum TraverseOption { TraverseOptionDefault = 1 << 0, TraverseOptionToNodeEnd = 1 << 1, TraverseOptionIncludeStart = 1 << 2, TraverseOptionValidateOffset = 1 << 3, TraverseOptionDoNotEnterTextControls = 1 << 4 };
426 Node* nextNode(Node*) const;
427 Node* previousNode(Node*) const;
428 CharacterOffset traverseToOffsetInRange(const SimpleRange&, int, TraverseOption = TraverseOptionDefault, bool stayWithinRange = false);
429 VisiblePosition visiblePositionFromCharacterOffset(const CharacterOffset&);
430 CharacterOffset characterOffsetFromVisiblePosition(const VisiblePosition&);
431 void setTextMarkerDataWithCharacterOffset(TextMarkerData&, const CharacterOffset&);
432 UChar32 characterAfter(const CharacterOffset&);
433 UChar32 characterBefore(const CharacterOffset&);
434 CharacterOffset characterOffsetForNodeAndOffset(Node&, int, TraverseOption = TraverseOptionDefault);
436 enum class NeedsContextAtParagraphStart { Yes, No };
437 CharacterOffset previousBoundary(const CharacterOffset&, BoundarySearchFunction, NeedsContextAtParagraphStart = NeedsContextAtParagraphStart::No);
438 CharacterOffset nextBoundary(const CharacterOffset&, BoundarySearchFunction);
439 CharacterOffset startCharacterOffsetOfWord(const CharacterOffset&, EWordSide = RightWordIfOnBoundary);
440 CharacterOffset endCharacterOffsetOfWord(const CharacterOffset&, EWordSide = RightWordIfOnBoundary);
441 CharacterOffset startCharacterOffsetOfParagraph(const CharacterOffset&, EditingBoundaryCrossingRule = CannotCrossEditingBoundary);
442 CharacterOffset endCharacterOffsetOfParagraph(const CharacterOffset&, EditingBoundaryCrossingRule = CannotCrossEditingBoundary);
443 CharacterOffset startCharacterOffsetOfSentence(const CharacterOffset&);
444 CharacterOffset endCharacterOffsetOfSentence(const CharacterOffset&);
445 CharacterOffset characterOffsetForPoint(const IntPoint&);
446 LayoutRect localCaretRectForCharacterOffset(RenderObject*&, const CharacterOffset&);
447 bool shouldSkipBoundary(const CharacterOffset&, const CharacterOffset&);
448 private:
449 AccessibilityObject* rootWebArea();
450 static AccessibilityObject* focusedImageMapUIElement(HTMLAreaElement*);
452 AXID getAXID(AccessibilityObject*);
454 void notificationPostTimerFired();
456 void liveRegionChangedNotificationPostTimerFired();
458 void focusModalNodeTimerFired();
460 void performCacheUpdateTimerFired();
462 void postTextStateChangeNotification(AccessibilityObject*, const AXTextStateChangeIntent&, const VisibleSelection&);
464 bool enqueuePasswordValueChangeNotification(AccessibilityObject*);
465 void passwordNotificationPostTimerFired();
467 void processDeferredChildrenChangedList();
468 void handleChildrenChanged(AccessibilityObject&);
469 void handleMenuOpened(Node*);
470 void handleLiveRegionCreated(Node*);
471 void handleMenuItemSelected(Node*);
472 void handleRowCountChanged(AXCoreObject*, Document*);
473 void handleAttributeChange(const QualifiedName&, Element*);
474 bool shouldProcessAttributeChange(const QualifiedName&, Element*);
475 void selectedChildrenChanged(Node*);
476 void selectedChildrenChanged(RenderObject*);
477 void selectedStateChanged(Node*);
478 // Called by a node when text or a text equivalent (e.g. alt) attribute is changed.
479 void textChanged(Node*);
481 void handleActiveDescendantChanged(Element&);
483 void handleAriaExpandedChange(Node*);
484 void handleFocusedUIElementChanged(Node* oldFocusedNode, Node* newFocusedNode);
485 void handleMenuListValueChanged(Element&);
487 // aria-modal or modal <dialog> related
488 bool isModalElement(Element&) const;
489 void findModalNodes();
490 Element* currentModalNode();
491 bool isNodeVisible(Node*) const;
492 void handleModalChange(Element&);
493 bool modalElementHasAccessibleContent(Element&);
495 // Relationships between objects.
496 static Vector<QualifiedName>& relationAttributes();
497 static AXRelationType attributeToRelationType(const QualifiedName&);
498 enum class AddingSymmetricRelation : bool { No, Yes };
499 static AXRelationType symmetricRelation(AXRelationType);
500 void addRelation(Element*, Element*, AXRelationType);
501 void addRelation(AccessibilityObject*, AccessibilityObject*, AXRelationType, AddingSymmetricRelation = AddingSymmetricRelation::No);
502 void updateRelationsIfNeeded();
503 void relationsNeedUpdate(bool needUpdate) { m_relationsNeedUpdate = needUpdate; }
505 Document& m_document;
506 const std::optional<PageIdentifier> m_pageID; // constant for object's lifetime.
507 HashMap<AXID, RefPtr<AccessibilityObject>> m_objects;
508 HashMap<RenderObject*, AXID> m_renderObjectMapping;
509 HashMap<Widget*, AXID> m_widgetObjectMapping;
510 HashMap<Node*, AXID> m_nodeObjectMapping;
511 ListHashSet<Node*> m_textMarkerNodes;
512 std::unique_ptr<AXComputedObjectAttributeCache> m_computedObjectAttributeCache;
514 #if ENABLE(ACCESSIBILITY)
515 WEBCORE_EXPORT static bool gAccessibilityEnabled;
516 WEBCORE_EXPORT static bool gAccessibilityEnhancedUserInterfaceEnabled;
517 #else
518 static constexpr bool gAccessibilityEnabled = false;
519 static constexpr bool gAccessibilityEnhancedUserInterfaceEnabled = false;
520 #endif
522 HashSet<AXID> m_idsInUse;
524 Timer m_notificationPostTimer;
525 Vector<std::pair<RefPtr<AXCoreObject>, AXNotification>> m_notificationsToPost;
527 Timer m_passwordNotificationPostTimer;
529 ListHashSet<RefPtr<AccessibilityObject>> m_passwordNotificationsToPost;
531 Timer m_liveRegionChangedPostTimer;
532 ListHashSet<RefPtr<AccessibilityObject>> m_liveRegionObjectsSet;
534 Timer m_focusModalNodeTimer;
535 WeakPtr<Element> m_currentModalElement;
536 // Multiple aria-modals behavior is undefined by spec. We keep them sorted based on DOM order here.
537 // If that changes to require only one aria-modal we could change this to a WeakHashSet, or discard the set completely.
538 ListHashSet<Element*> m_modalElementsSet;
539 bool m_modalNodesInitialized { false };
540 bool m_isRetrievingCurrentModalNode { false };
542 Timer m_performCacheUpdateTimer;
544 AXTextStateChangeIntent m_textSelectionIntent;
545 WeakHashSet<Element> m_deferredRecomputeIsIgnoredList;
546 WeakHashSet<HTMLTableElement> m_deferredRecomputeTableIsExposedList;
547 ListHashSet<Node*> m_deferredTextChangedList;
548 WeakHashSet<Element> m_deferredSelectedChildredChangedList;
549 ListHashSet<RefPtr<AccessibilityObject>> m_deferredChildrenChangedList;
550 ListHashSet<Node*> m_deferredNodeAddedOrRemovedList;
551 WeakHashSet<Element> m_deferredModalChangedList;
552 WeakHashSet<Element> m_deferredMenuListChange;
553 HashMap<Element*, String> m_deferredTextFormControlValue;
554 HashMap<Element*, QualifiedName> m_deferredAttributeChange;
555 Vector<std::pair<Node*, Node*>> m_deferredFocusedNodeChange;
556 bool m_isSynchronizingSelection { false };
557 bool m_performingDeferredCacheUpdate { false };
558 double m_loadingProgress { 0 };
560 // Relationships between objects.
561 using Relations = HashMap<AXRelationType, Vector<AXID>, DefaultHash<uint8_t>, WTF::UnsignedWithZeroKeyHashTraits<uint8_t>>;
562 HashMap<AXID, Relations> m_relations;
563 bool m_relationsNeedUpdate { true };
565 #if USE(ATSPI)
566 ListHashSet<RefPtr<AXCoreObject>> m_deferredParentChangedList;
567 #endif
570 class AXAttributeCacheEnabler
572 public:
573 explicit AXAttributeCacheEnabler(AXObjectCache *cache);
574 ~AXAttributeCacheEnabler();
576 #if ENABLE(ACCESSIBILITY)
577 private:
578 AXObjectCache* m_cache;
579 #endif
582 bool nodeHasRole(Node*, StringView role);
583 // This will let you know if aria-hidden was explicitly set to false.
584 bool isNodeAriaVisible(Node*);
586 #if !ENABLE(ACCESSIBILITY)
587 inline AccessibilityObjectInclusion AXComputedObjectAttributeCache::getIgnored(AXID) const { return AccessibilityObjectInclusion::DefaultBehavior; }
588 inline AccessibilityReplacedText::AccessibilityReplacedText(const VisibleSelection&) { }
589 inline void AccessibilityReplacedText::postTextStateChangeNotification(AXObjectCache*, AXTextEditType, const String&, const VisibleSelection&) { }
590 inline void AXComputedObjectAttributeCache::setIgnored(AXID, AccessibilityObjectInclusion) { }
591 inline AXObjectCache::AXObjectCache(Document& document) : m_document(document), m_notificationPostTimer(*this, &AXObjectCache::notificationPostTimerFired), m_passwordNotificationPostTimer(*this, &AXObjectCache::passwordNotificationPostTimerFired), m_liveRegionChangedPostTimer(*this, &AXObjectCache::liveRegionChangedNotificationPostTimerFired), m_focusModalNodeTimer(*this, &AXObjectCache::focusModalNodeTimerFired), m_performCacheUpdateTimer(*this, &AXObjectCache::performCacheUpdateTimerFired) { }
592 inline AXObjectCache::~AXObjectCache() { }
593 inline AccessibilityObject* AXObjectCache::get(RenderObject*) { return nullptr; }
594 inline AccessibilityObject* AXObjectCache::get(Node*) { return nullptr; }
595 inline AccessibilityObject* AXObjectCache::get(Widget*) { return nullptr; }
596 inline AccessibilityObject* AXObjectCache::getOrCreate(RenderObject*) { return nullptr; }
597 inline AccessibilityObject* AXObjectCache::create(AccessibilityRole) { return nullptr; }
598 inline AccessibilityObject* AXObjectCache::getOrCreate(Node*) { return nullptr; }
599 inline AccessibilityObject* AXObjectCache::getOrCreate(Widget*) { return nullptr; }
600 inline AXCoreObject* AXObjectCache::rootObject() { return nullptr; }
601 inline AccessibilityObject* AXObjectCache::rootObjectForFrame(Frame*) { return nullptr; }
602 inline AccessibilityObject* AXObjectCache::focusedObjectForPage(const Page*) { return nullptr; }
603 inline void AXObjectCache::enableAccessibility() { }
604 inline void AXObjectCache::disableAccessibility() { }
605 inline void AXObjectCache::setEnhancedUserInterfaceAccessibility(bool) { }
606 inline bool nodeHasRole(Node*, StringView) { return false; }
607 inline void AXObjectCache::startCachingComputedObjectAttributesUntilTreeMutates() { }
608 inline void AXObjectCache::stopCachingComputedObjectAttributes() { }
609 inline bool isNodeAriaVisible(Node*) { return true; }
610 inline const Element* AXObjectCache::rootAXEditableElement(const Node*) { return nullptr; }
611 inline Node* AXObjectCache::modalNode() { return nullptr; }
612 inline void AXObjectCache::attachWrapper(AXCoreObject*) { }
613 inline void AXObjectCache::checkedStateChanged(Node*) { }
614 inline void AXObjectCache::childrenChanged(Node*, Node*) { }
615 inline void AXObjectCache::childrenChanged(RenderObject*, RenderObject*) { }
616 inline void AXObjectCache::childrenChanged(AccessibilityObject*) { }
617 inline void AXObjectCache::deferFocusedUIElementChangeIfNeeded(Node*, Node*) { }
618 inline void AXObjectCache::deferRecomputeIsIgnoredIfNeeded(Element*) { }
619 inline void AXObjectCache::deferRecomputeIsIgnored(Element*) { }
620 inline void AXObjectCache::deferTextChangedIfNeeded(Node*) { }
621 inline void AXObjectCache::deferSelectedChildrenChangedIfNeeded(Element&) { }
622 inline void AXObjectCache::deferTextReplacementNotificationForTextControl(HTMLTextFormControlElement&, const String&) { }
623 #if !PLATFORM(COCOA) && !USE(ATSPI)
624 inline void AXObjectCache::detachWrapper(AXCoreObject*, AccessibilityDetachmentType) { }
625 #endif
626 inline void AXObjectCache::focusModalNodeTimerFired() { }
627 inline void AXObjectCache::performCacheUpdateTimerFired() { }
628 inline void AXObjectCache::frameLoadingEventNotification(Frame*, AXLoadingEvent) { }
629 inline void AXObjectCache::frameLoadingEventPlatformNotification(AccessibilityObject*, AXLoadingEvent) { }
630 inline void AXObjectCache::handleActiveDescendantChanged(Element&) { }
631 inline void AXObjectCache::handleAriaExpandedChange(Node*) { }
632 inline void AXObjectCache::handleModalChange(Element&) { }
633 inline void AXObjectCache::deferModalChange(Element*) { }
634 inline void AXObjectCache::handleRoleChange(AccessibilityObject*) { }
635 inline void AXObjectCache::deferAttributeChangeIfNeeded(const QualifiedName&, Element*) { }
636 inline void AXObjectCache::handleAttributeChange(const QualifiedName&, Element*) { }
637 inline bool AXObjectCache::shouldProcessAttributeChange(const QualifiedName&, Element*) { return false; }
638 inline void AXObjectCache::handleFocusedUIElementChanged(Node*, Node*) { }
639 inline void AXObjectCache::handleScrollbarUpdate(ScrollView*) { }
640 inline void AXObjectCache::handleScrolledToAnchor(const Node*) { }
641 inline void AXObjectCache::liveRegionChangedNotificationPostTimerFired() { }
642 inline void AXObjectCache::notificationPostTimerFired() { }
643 inline Vector<RefPtr<AXCoreObject>> AXObjectCache::objectsForIDs(const Vector<AXID>&) const { return { }; }
644 inline void AXObjectCache::passwordNotificationPostTimerFired() { }
645 inline void AXObjectCache::performDeferredCacheUpdate() { }
646 inline void AXObjectCache::postLiveRegionChangeNotification(AccessibilityObject*) { }
647 inline void AXObjectCache::postNotification(AXCoreObject*, Document*, AXNotification, PostTarget) { }
648 inline void AXObjectCache::postNotification(Node*, AXNotification, PostTarget) { }
649 inline void AXObjectCache::postNotification(RenderObject*, AXNotification, PostTarget) { }
650 inline void AXObjectCache::postPlatformNotification(AXCoreObject*, AXNotification) { }
651 inline void AXObjectCache::postTextReplacementNotification(Node*, AXTextEditType, const String&, AXTextEditType, const String&, const VisiblePosition&) { }
652 inline void AXObjectCache::postTextReplacementNotificationForTextControl(HTMLTextFormControlElement&, const String&, const String&) { }
653 inline void AXObjectCache::postTextStateChangeNotification(Node*, AXTextEditType, const String&, const VisiblePosition&) { }
654 inline void AXObjectCache::postTextStateChangeNotification(Node*, const AXTextStateChangeIntent&, const VisibleSelection&) { }
655 inline void AXObjectCache::recomputeIsIgnored(RenderObject*) { }
656 inline void AXObjectCache::textChanged(AccessibilityObject*) { }
657 inline void AXObjectCache::textChanged(Node*) { }
658 inline void AXObjectCache::updateCacheAfterNodeIsAttached(Node*) { }
659 inline void AXObjectCache::updateLoadingProgress(double) { }
660 inline SimpleRange AXObjectCache::rangeForNodeContents(Node& node) { return makeRangeSelectingNodeContents(node); }
661 inline std::optional<Vector<AXID>> AXObjectCache::relatedObjectsFor(const AXCoreObject&, AXRelationType) { return std::nullopt; }
662 inline void AXObjectCache::remove(AXID) { }
663 inline void AXObjectCache::remove(RenderObject*) { }
664 inline void AXObjectCache::remove(Node&) { }
665 inline void AXObjectCache::remove(Widget*) { }
666 inline void AXObjectCache::selectedChildrenChanged(RenderObject*) { }
667 inline void AXObjectCache::selectedChildrenChanged(Node*) { }
668 inline void AXObjectCache::setIsSynchronizingSelection(bool) { }
669 inline void AXObjectCache::setTextSelectionIntent(const AXTextStateChangeIntent&) { }
670 inline std::optional<SimpleRange> AXObjectCache::rangeForUnorderedCharacterOffsets(const CharacterOffset&, const CharacterOffset&) { return std::nullopt; }
671 inline IntRect AXObjectCache::absoluteCaretBoundsForCharacterOffset(const CharacterOffset&) { return IntRect(); }
672 inline CharacterOffset AXObjectCache::characterOffsetForIndex(int, const AXCoreObject*) { return CharacterOffset(); }
673 inline CharacterOffset AXObjectCache::startOrEndCharacterOffsetForRange(const SimpleRange&, bool, bool) { return CharacterOffset(); }
674 inline CharacterOffset AXObjectCache::endCharacterOffsetOfLine(const CharacterOffset&) { return CharacterOffset(); }
675 inline CharacterOffset AXObjectCache::nextCharacterOffset(const CharacterOffset&, bool) { return CharacterOffset(); }
676 inline CharacterOffset AXObjectCache::previousCharacterOffset(const CharacterOffset&, bool) { return CharacterOffset(); }
677 #if PLATFORM(COCOA)
678 inline void AXObjectCache::postTextStateChangePlatformNotification(AccessibilityObject*, const AXTextStateChangeIntent&, const VisibleSelection&) { }
679 inline void AXObjectCache::postTextStateChangePlatformNotification(AccessibilityObject*, AXTextEditType, const String&, const VisiblePosition&) { }
680 inline void AXObjectCache::postTextReplacementPlatformNotification(AccessibilityObject*, AXTextEditType, const String&, AXTextEditType, const String&, const VisiblePosition&) { }
681 #else
682 inline AXTextChange AXObjectCache::textChangeForEditType(AXTextEditType) { return AXTextInserted; }
683 inline void AXObjectCache::nodeTextChangePlatformNotification(AccessibilityObject*, AXTextChange, unsigned, const String&) { }
684 #endif
685 inline AXTreeData AXObjectCache::treeData() { return { }; }
687 inline AXAttributeCacheEnabler::AXAttributeCacheEnabler(AXObjectCache*) { }
688 inline AXAttributeCacheEnabler::~AXAttributeCacheEnabler() { }
689 #endif // !ENABLE(ACCESSIBILITY)
691 WTF::TextStream& operator<<(WTF::TextStream&, AXObjectCache::AXNotification);
693 } // namespace WebCore