[GTK] REGRESSION(183368): It made editing tests assert
[WebKit-https.git] / Source / WebCore / accessibility / AXObjectCache.h
1 /*
2  * Copyright (C) 2003, 2006, 2007, 2008, 2009, 2010, 2011, 2015 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. ``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.
24  */
25
26 #ifndef AXObjectCache_h
27 #define AXObjectCache_h
28
29 #include "AXTextStateChangeIntent.h"
30 #include "AccessibilityObject.h"
31 #include "Timer.h"
32 #include <limits.h>
33 #include <wtf/Forward.h>
34 #include <wtf/HashMap.h>
35 #include <wtf/HashSet.h>
36 #include <wtf/ListHashSet.h>
37 #include <wtf/RefPtr.h>
38
39 namespace WebCore {
40
41 class Document;
42 class HTMLAreaElement;
43 class Node;
44 class Page;
45 class RenderObject;
46 class ScrollView;
47 class VisiblePosition;
48 class Widget;
49
50 struct TextMarkerData {
51     AXID axID;
52     Node* node;
53     int offset;
54     EAffinity affinity;
55 };
56
57 class AXComputedObjectAttributeCache {
58 public:
59     AccessibilityObjectInclusion getIgnored(AXID) const;
60     void setIgnored(AXID, AccessibilityObjectInclusion);
61
62 private:
63     struct CachedAXObjectAttributes {
64         CachedAXObjectAttributes() : ignored(DefaultBehavior) { }
65
66         AccessibilityObjectInclusion ignored;
67     };
68
69     HashMap<AXID, CachedAXObjectAttributes> m_idMapping;
70 };
71
72 #if !PLATFORM(COCOA)
73 enum AXTextChange { AXTextInserted, AXTextDeleted, AXTextAttributesChanged };
74 #endif
75
76 enum PostTarget { TargetElement, TargetObservableParent };
77
78 enum PostType { PostSynchronously, PostAsynchronously };
79
80 class AXObjectCache {
81     WTF_MAKE_NONCOPYABLE(AXObjectCache); WTF_MAKE_FAST_ALLOCATED;
82 public:
83     explicit AXObjectCache(Document&);
84     ~AXObjectCache();
85
86     WEBCORE_EXPORT static AccessibilityObject* focusedUIElementForPage(const Page*);
87
88     // Returns the root object for the entire document.
89     WEBCORE_EXPORT AccessibilityObject* rootObject();
90     // Returns the root object for a specific frame.
91     WEBCORE_EXPORT AccessibilityObject* rootObjectForFrame(Frame*);
92     
93     // For AX objects with elements that back them.
94     AccessibilityObject* getOrCreate(RenderObject*);
95     AccessibilityObject* getOrCreate(Widget*);
96     AccessibilityObject* getOrCreate(Node*);
97
98     // used for objects without backing elements
99     AccessibilityObject* getOrCreate(AccessibilityRole);
100     
101     // will only return the AccessibilityObject if it already exists
102     AccessibilityObject* get(RenderObject*);
103     AccessibilityObject* get(Widget*);
104     AccessibilityObject* get(Node*);
105     
106     void remove(RenderObject*);
107     void remove(Node*);
108     void remove(Widget*);
109     void remove(AXID);
110
111     void detachWrapper(AccessibilityObject*, AccessibilityDetachmentType);
112     void attachWrapper(AccessibilityObject*);
113     void childrenChanged(Node*, Node* newChild = nullptr);
114     void childrenChanged(RenderObject*, RenderObject* newChild = nullptr);
115     void childrenChanged(AccessibilityObject*);
116     void checkedStateChanged(Node*);
117     void selectedChildrenChanged(Node*);
118     void selectedChildrenChanged(RenderObject*);
119     // Called by a node when text or a text equivalent (e.g. alt) attribute is changed.
120     void textChanged(Node*);
121     void textChanged(RenderObject*);
122     // Called when a node has just been attached, so we can make sure we have the right subclass of AccessibilityObject.
123     void updateCacheAfterNodeIsAttached(Node*);
124
125     void handleActiveDescendantChanged(Node*);
126     void handleAriaRoleChanged(Node*);
127     void handleFocusedUIElementChanged(Node* oldFocusedNode, Node* newFocusedNode);
128     void handleScrolledToAnchor(const Node* anchorNode);
129     void handleAriaExpandedChange(Node*);
130     void handleScrollbarUpdate(ScrollView*);
131
132     void handleAttributeChanged(const QualifiedName& attrName, Element*);
133     void recomputeIsIgnored(RenderObject* renderer);
134
135 #if HAVE(ACCESSIBILITY)
136     WEBCORE_EXPORT static void enableAccessibility();
137     WEBCORE_EXPORT static void disableAccessibility();
138
139     // Enhanced user interface accessibility can be toggled by the assistive technology.
140     WEBCORE_EXPORT static void setEnhancedUserInterfaceAccessibility(bool flag);
141     
142     static bool accessibilityEnabled() { return gAccessibilityEnabled; }
143     static bool accessibilityEnhancedUserInterfaceEnabled() { return gAccessibilityEnhancedUserInterfaceEnabled; }
144 #else
145     static void enableAccessibility() { }
146     static void disableAccessibility() { }
147     static void setEnhancedUserInterfaceAccessibility(bool) { }
148     static bool accessibilityEnabled() { return false; }
149     static bool accessibilityEnhancedUserInterfaceEnabled() { return false; }
150 #endif
151
152     void removeAXID(AccessibilityObject*);
153     bool isIDinUse(AXID id) const { return m_idsInUse.contains(id); }
154
155     const Element* rootAXEditableElement(const Node*);
156     bool nodeIsTextControl(const Node*);
157
158     AXID platformGenerateAXID() const;
159     AccessibilityObject* objectFromAXID(AXID id) const { return m_objects.get(id); }
160
161     // Text marker utilities.
162     void textMarkerDataForVisiblePosition(TextMarkerData&, const VisiblePosition&);
163     VisiblePosition visiblePositionForTextMarkerData(TextMarkerData&);
164
165     enum AXNotification {
166         AXActiveDescendantChanged,
167         AXAutocorrectionOccured,
168         AXCheckedStateChanged,
169         AXChildrenChanged,
170         AXFocusedUIElementChanged,
171         AXLayoutComplete,
172         AXLoadComplete,
173         AXNewDocumentLoadComplete,
174         AXSelectedChildrenChanged,
175         AXSelectedTextChanged,
176         AXValueChanged,
177         AXScrolledToAnchor,
178         AXLiveRegionCreated,
179         AXLiveRegionChanged,
180         AXMenuListItemSelected,
181         AXMenuListValueChanged,
182         AXMenuClosed,
183         AXMenuOpened,
184         AXRowCountChanged,
185         AXRowCollapsed,
186         AXRowExpanded,
187         AXExpandedChanged,
188         AXInvalidStatusChanged,
189         AXTextChanged,
190         AXAriaAttributeChanged,
191         AXElementBusyChanged
192     };
193
194     void postNotification(RenderObject*, AXNotification, PostTarget = TargetElement, PostType = PostAsynchronously);
195     void postNotification(Node*, AXNotification, PostTarget = TargetElement, PostType = PostAsynchronously);
196     void postNotification(AccessibilityObject*, Document*, AXNotification, PostTarget = TargetElement, PostType = PostAsynchronously);
197
198 #ifndef NDEBUG
199     void showIntent(const AXTextStateChangeIntent&);
200 #endif
201
202     void setTextSelectionIntent(AXTextStateChangeIntent);
203
204     void postTextStateChangeNotification(Node*, AXTextEditType, const String&, const VisiblePosition&);
205     void postTextReplacementNotification(Node*, AXTextEditType deletionType, const String& deletedText, AXTextEditType insertionType, const String& insertedText, const VisiblePosition&);
206     void postTextStateChangeNotification(Node*, const AXTextStateChangeIntent&, const VisibleSelection&);
207
208     enum AXLoadingEvent {
209         AXLoadingStarted,
210         AXLoadingReloaded,
211         AXLoadingFailed,
212         AXLoadingFinished
213     };
214
215     void frameLoadingEventNotification(Frame*, AXLoadingEvent);
216
217     void clearTextMarkerNodesInUse(Document*);
218
219     void startCachingComputedObjectAttributesUntilTreeMutates();
220     void stopCachingComputedObjectAttributes();
221
222     AXComputedObjectAttributeCache* computedObjectAttributeCache() { return m_computedObjectAttributeCache.get(); }
223
224     Document& document() const { return m_document; }
225
226 #if PLATFORM(MAC)
227     static void setShouldRepostNotificationsForTests(bool value);
228 #endif
229
230 protected:
231     void postPlatformNotification(AccessibilityObject*, AXNotification);
232     void platformHandleFocusedUIElementChanged(Node* oldFocusedNode, Node* newFocusedNode);
233
234 #if PLATFORM(COCOA)
235     void postTextStateChangePlatformNotification(AccessibilityObject*, const AXTextStateChangeIntent&, const VisibleSelection&);
236     void postTextStateChangePlatformNotification(AccessibilityObject*, AXTextEditType, const String&, const VisiblePosition&);
237     void postTextReplacementPlatformNotification(AccessibilityObject*, AXTextEditType, const String&, AXTextEditType, const String&, const VisiblePosition&);
238 #else
239     static AXTextChange textChangeForEditType(AXTextEditType);
240     void nodeTextChangePlatformNotification(AccessibilityObject*, AXTextChange, unsigned, const String&);
241 #endif
242
243     void frameLoadingEventPlatformNotification(AccessibilityObject*, AXLoadingEvent);
244     void textChanged(AccessibilityObject*);
245     void labelChanged(Element*);
246
247     // This is a weak reference cache for knowing if Nodes used by TextMarkers are valid.
248     void setNodeInUse(Node* n) { m_textMarkerNodes.add(n); }
249     void removeNodeForUse(Node* n) { m_textMarkerNodes.remove(n); }
250     bool isNodeInUse(Node* n) { return m_textMarkerNodes.contains(n); }
251
252 private:
253     AccessibilityObject* rootWebArea();
254
255     static AccessibilityObject* focusedImageMapUIElement(HTMLAreaElement*);
256
257     AXID getAXID(AccessibilityObject*);
258
259     void notificationPostTimerFired();
260
261     bool enqueuePasswordValueChangeNotification(AccessibilityObject*);
262     void passwordNotificationPostTimerFired();
263
264     void handleMenuOpened(Node*);
265     void handleLiveRegionCreated(Node*);
266     void handleMenuItemSelected(Node*);
267
268     Document& m_document;
269     HashMap<AXID, RefPtr<AccessibilityObject>> m_objects;
270     HashMap<RenderObject*, AXID> m_renderObjectMapping;
271     HashMap<Widget*, AXID> m_widgetObjectMapping;
272     HashMap<Node*, AXID> m_nodeObjectMapping;
273     HashSet<Node*> m_textMarkerNodes;
274     std::unique_ptr<AXComputedObjectAttributeCache> m_computedObjectAttributeCache;
275     WEBCORE_EXPORT static bool gAccessibilityEnabled;
276     WEBCORE_EXPORT static bool gAccessibilityEnhancedUserInterfaceEnabled;
277
278     HashSet<AXID> m_idsInUse;
279
280     Timer m_notificationPostTimer;
281     Vector<std::pair<RefPtr<AccessibilityObject>, AXNotification>> m_notificationsToPost;
282
283     Timer m_passwordNotificationPostTimer;
284
285     ListHashSet<RefPtr<AccessibilityObject>> m_passwordNotificationsToPost;
286
287     AXTextStateChangeIntent m_textSelectionIntent;
288 };
289
290 class AXAttributeCacheEnabler
291 {
292 public:
293     explicit AXAttributeCacheEnabler(AXObjectCache *cache);
294     ~AXAttributeCacheEnabler();
295     
296 private:
297     AXObjectCache* m_cache;
298 };
299     
300 bool nodeHasRole(Node*, const String& role);
301 // This will let you know if aria-hidden was explicitly set to false.
302 bool isNodeAriaVisible(Node*);
303     
304 #if !HAVE(ACCESSIBILITY)
305 inline AccessibilityObjectInclusion AXComputedObjectAttributeCache::getIgnored(AXID) const { return DefaultBehavior; }
306 inline void AXComputedObjectAttributeCache::setIgnored(AXID, AccessibilityObjectInclusion) { }
307 inline AXObjectCache::AXObjectCache(Document& document) : m_document(document), m_notificationPostTimer(this, (Timer::TimerFiredFunction) nullptr) { }
308 inline AXObjectCache::~AXObjectCache() { }
309 inline AccessibilityObject* AXObjectCache::focusedUIElementForPage(const Page*) { return nullptr; }
310 inline AccessibilityObject* AXObjectCache::get(RenderObject*) { return nullptr; }
311 inline AccessibilityObject* AXObjectCache::get(Node*) { return nullptr; }
312 inline AccessibilityObject* AXObjectCache::get(Widget*) { return nullptr; }
313 inline AccessibilityObject* AXObjectCache::getOrCreate(AccessibilityRole) { return nullptr; }
314 inline AccessibilityObject* AXObjectCache::getOrCreate(RenderObject*) { return nullptr; }
315 inline AccessibilityObject* AXObjectCache::getOrCreate(Node*) { return nullptr; }
316 inline AccessibilityObject* AXObjectCache::getOrCreate(Widget*) { return nullptr; }
317 inline AccessibilityObject* AXObjectCache::rootObject() { return nullptr; }
318 inline AccessibilityObject* AXObjectCache::rootObjectForFrame(Frame*) { return nullptr; }
319 inline Element* AXObjectCache::rootAXEditableElement(Node*) { return nullptr; }
320 inline bool nodeHasRole(Node*, const String&) { return false; }
321 inline void AXObjectCache::startCachingComputedObjectAttributesUntilTreeMutates() { }
322 inline void AXObjectCache::stopCachingComputedObjectAttributes() { }
323 inline bool isNodeAriaVisible(Node*) { return true; }
324 inline const Element* AXObjectCache::rootAXEditableElement(const Node*) { return nullptr; }
325 inline void AXObjectCache::attachWrapper(AccessibilityObject*) { }
326 inline void AXObjectCache::checkedStateChanged(Node*) { }
327 inline void AXObjectCache::childrenChanged(RenderObject*, RenderObject*) { }
328 inline void AXObjectCache::childrenChanged(Node*, Node*) { }
329 inline void AXObjectCache::childrenChanged(AccessibilityObject*) { }
330 inline void AXObjectCache::textChanged(RenderObject*) { }
331 inline void AXObjectCache::textChanged(Node*) { }
332 inline void AXObjectCache::textChanged(AccessibilityObject*) { }
333 inline void AXObjectCache::updateCacheAfterNodeIsAttached(Node*) { }
334 inline void AXObjectCache::detachWrapper(AccessibilityObject*, AccessibilityDetachmentType) { }
335 inline void AXObjectCache::frameLoadingEventNotification(Frame*, AXLoadingEvent) { }
336 inline void AXObjectCache::frameLoadingEventPlatformNotification(AccessibilityObject*, AXLoadingEvent) { }
337 inline void AXObjectCache::handleActiveDescendantChanged(Node*) { }
338 inline void AXObjectCache::handleAriaExpandedChange(Node*) { }
339 inline void AXObjectCache::handleAriaRoleChanged(Node*) { }
340 inline void AXObjectCache::handleFocusedUIElementChanged(Node*, Node*) { }
341 inline void AXObjectCache::handleScrollbarUpdate(ScrollView*) { }
342 inline void AXObjectCache::handleAttributeChanged(const QualifiedName&, Element*) { }
343 inline void AXObjectCache::recomputeIsIgnored(RenderObject*) { }
344 inline void AXObjectCache::handleScrolledToAnchor(const Node*) { }
345 inline void AXObjectCache::postTextStateChangeNotification(Node*, const AXTextStateChangeIntent&, const VisibleSelection&) { }
346 inline void AXObjectCache::postTextStateChangeNotification(Node*, AXTextEditType, const String&, const VisiblePosition&) { }
347 inline void AXObjectCache::postTextReplacementNotification(Node*, AXTextEditType, const String&, AXTextEditType, const String&, const VisiblePosition&) { }
348 inline void AXObjectCache::postNotification(AccessibilityObject*, Document*, AXNotification, PostTarget, PostType) { }
349 inline void AXObjectCache::postNotification(RenderObject*, AXNotification, PostTarget, PostType) { }
350 inline void AXObjectCache::postNotification(Node*, AXNotification, PostTarget, PostType) { }
351 inline void AXObjectCache::postPlatformNotification(AccessibilityObject*, AXNotification) { }
352 inline void AXObjectCache::remove(AXID) { }
353 inline void AXObjectCache::remove(RenderObject*) { }
354 inline void AXObjectCache::remove(Node*) { }
355 inline void AXObjectCache::remove(Widget*) { }
356 inline void AXObjectCache::selectedChildrenChanged(RenderObject*) { }
357 inline void AXObjectCache::selectedChildrenChanged(Node*) { }
358 #if PLATFORM(COCOA)
359 inline void AXObjectCache::postTextStateChangePlatformNotification(AccessibilityObject*, const AXTextStateChangeIntent&, const VisibleSelection&) { }
360 inline void AXObjectCache::postTextStateChangePlatformNotification(AccessibilityObject*, AXTextEditType, const String&, const VisiblePosition&) { }
361 inline void AXObjectCache::postTextReplacementPlatformNotification(AccessibilityObject*, AXTextEditType, const String&, AXTextEditType, const String&, const VisiblePosition&) { }
362 #else
363 inline AXTextChange AXObjectCache::textChangeForEditType(AXTextEditType) { return AXTextInserted; }
364 inline void AXObjectCache::nodeTextChangePlatformNotification(AccessibilityObject*, AXTextChange, unsigned, const String&) { }
365 #endif
366 #endif
367
368 }
369
370 #endif