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