96b0f85885b1e43c4a176f6786fcaace37983d4e
[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 COMPUTER, 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 COMPUTER, 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*);
108     void childrenChanged(RenderObject*);
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() { gAccessibilityEnabled = true; }
131     // Enhanced user interface accessibility can be toggled by the assistive technology.
132     static void setEnhancedUserInterfaceAccessibility(bool flag) { gAccessibilityEnhancedUserInterfaceEnabled = flag; }
133     
134     static bool accessibilityEnabled() { return gAccessibilityEnabled; }
135     static bool accessibilityEnhancedUserInterfaceEnabled() { return gAccessibilityEnhancedUserInterfaceEnabled; }
136 #else
137     static void enableAccessibility() { }
138     static void setEnhancedUserInterfaceAccessibility(bool) { }
139     static bool accessibilityEnabled() { return false; }
140     static bool accessibilityEnhancedUserInterfaceEnabled() { return false; }
141 #endif
142
143     void removeAXID(AccessibilityObject*);
144     bool isIDinUse(AXID id) const { return m_idsInUse.contains(id); }
145
146     Element* rootAXEditableElement(Node*);
147     const Element* rootAXEditableElement(const Node*);
148     bool nodeIsTextControl(const Node*);
149
150     AXID platformGenerateAXID() const;
151     AccessibilityObject* objectFromAXID(AXID id) const { return m_objects.get(id); }
152
153     // Text marker utilities.
154     void textMarkerDataForVisiblePosition(TextMarkerData&, const VisiblePosition&);
155     VisiblePosition visiblePositionForTextMarkerData(TextMarkerData&);
156
157     enum AXNotification {
158         AXActiveDescendantChanged,
159         AXAutocorrectionOccured,
160         AXCheckedStateChanged,
161         AXChildrenChanged,
162         AXFocusedUIElementChanged,
163         AXLayoutComplete,
164         AXLoadComplete,
165         AXSelectedChildrenChanged,
166         AXSelectedTextChanged,
167         AXValueChanged,
168         AXScrolledToAnchor,
169         AXLiveRegionChanged,
170         AXMenuListItemSelected,
171         AXMenuListValueChanged,
172         AXMenuClosed,
173         AXRowCountChanged,
174         AXRowCollapsed,
175         AXRowExpanded,
176         AXInvalidStatusChanged,
177         AXTextChanged,
178         AXAriaAttributeChanged,
179         AXElementBusyChanged
180     };
181
182     void postNotification(RenderObject*, AXNotification, PostTarget = TargetElement, PostType = PostAsynchronously);
183     void postNotification(Node*, AXNotification, PostTarget = TargetElement, PostType = PostAsynchronously);
184     void postNotification(AccessibilityObject*, Document*, AXNotification, PostTarget = TargetElement, PostType = PostAsynchronously);
185
186     enum AXTextChange {
187         AXTextInserted,
188         AXTextDeleted,
189     };
190
191     void nodeTextChangeNotification(Node*, AXTextChange, unsigned offset, const String&);
192
193     enum AXLoadingEvent {
194         AXLoadingStarted,
195         AXLoadingReloaded,
196         AXLoadingFailed,
197         AXLoadingFinished
198     };
199
200     void frameLoadingEventNotification(Frame*, AXLoadingEvent);
201
202     bool nodeHasRole(Node*, const AtomicString& role);
203     void clearTextMarkerNodesInUse(Document*);
204
205     void startCachingComputedObjectAttributesUntilTreeMutates();
206     void stopCachingComputedObjectAttributes();
207
208     AXComputedObjectAttributeCache* computedObjectAttributeCache() { return m_computedObjectAttributeCache.get(); }
209
210     Document& document() const { return m_document; }
211     
212 protected:
213     void postPlatformNotification(AccessibilityObject*, AXNotification);
214     void nodeTextChangePlatformNotification(AccessibilityObject*, AXTextChange, unsigned offset, const String&);
215     void frameLoadingEventPlatformNotification(AccessibilityObject*, AXLoadingEvent);
216     void textChanged(AccessibilityObject*);
217     void labelChanged(Element*);
218
219     // This is a weak reference cache for knowing if Nodes used by TextMarkers are valid.
220     void setNodeInUse(Node* n) { m_textMarkerNodes.add(n); }
221     void removeNodeForUse(Node* n) { m_textMarkerNodes.remove(n); }
222     bool isNodeInUse(Node* n) { return m_textMarkerNodes.contains(n); }
223
224 private:
225     Document& m_document;
226     HashMap<AXID, RefPtr<AccessibilityObject>> m_objects;
227     HashMap<RenderObject*, AXID> m_renderObjectMapping;
228     HashMap<Widget*, AXID> m_widgetObjectMapping;
229     HashMap<Node*, AXID> m_nodeObjectMapping;
230     HashSet<Node*> m_textMarkerNodes;
231     std::unique_ptr<AXComputedObjectAttributeCache> m_computedObjectAttributeCache;
232     static bool gAccessibilityEnabled;
233     static bool gAccessibilityEnhancedUserInterfaceEnabled;
234     
235     HashSet<AXID> m_idsInUse;
236     
237     Timer<AXObjectCache> m_notificationPostTimer;
238     Vector<std::pair<RefPtr<AccessibilityObject>, AXNotification>> m_notificationsToPost;
239     void notificationPostTimerFired(Timer<AXObjectCache>*);
240     
241     static AccessibilityObject* focusedImageMapUIElement(HTMLAreaElement*);
242     
243     AXID getAXID(AccessibilityObject*);
244 };
245
246 class AXAttributeCacheEnabler
247 {
248 public:
249     explicit AXAttributeCacheEnabler(AXObjectCache *cache);
250     ~AXAttributeCacheEnabler();
251     
252 private:
253     AXObjectCache* m_cache;
254 };
255     
256 bool nodeHasRole(Node*, const String& role);
257 // This will let you know if aria-hidden was explicitly set to false.
258 bool isNodeAriaVisible(Node*);
259     
260 #if !HAVE(ACCESSIBILITY)
261 inline AccessibilityObjectInclusion AXComputedObjectAttributeCache::getIgnored(AXID) const { return DefaultBehavior; }
262 inline void AXComputedObjectAttributeCache::setIgnored(AXID, AccessibilityObjectInclusion) { }
263 inline AXObjectCache::AXObjectCache(Document& document) : m_document(document), m_notificationPostTimer(this, 0) { }
264 inline AXObjectCache::~AXObjectCache() { }
265 inline AccessibilityObject* AXObjectCache::focusedUIElementForPage(const Page*) { return 0; }
266 inline AccessibilityObject* AXObjectCache::get(RenderObject*) { return 0; }
267 inline AccessibilityObject* AXObjectCache::get(Node*) { return 0; }
268 inline AccessibilityObject* AXObjectCache::get(Widget*) { return 0; }
269 inline AccessibilityObject* AXObjectCache::getOrCreate(AccessibilityRole) { return 0; }
270 inline AccessibilityObject* AXObjectCache::getOrCreate(RenderObject*) { return 0; }
271 inline AccessibilityObject* AXObjectCache::getOrCreate(Node*) { return 0; }
272 inline AccessibilityObject* AXObjectCache::getOrCreate(Widget*) { return 0; }
273 inline AccessibilityObject* AXObjectCache::rootObject() { return 0; }
274 inline AccessibilityObject* AXObjectCache::rootObjectForFrame(Frame*) { return 0; }
275 inline Element* AXObjectCache::rootAXEditableElement(Node*) { return 0; }
276 inline bool nodeHasRole(Node*, const String&) { return false; }
277 inline void AXObjectCache::startCachingComputedObjectAttributesUntilTreeMutates() { }
278 inline void AXObjectCache::stopCachingComputedObjectAttributes() { }
279 inline bool isNodeAriaVisible(Node*) { return true; }
280 inline const Element* AXObjectCache::rootAXEditableElement(const Node*) { return 0; }
281 inline void AXObjectCache::attachWrapper(AccessibilityObject*) { }
282 inline void AXObjectCache::checkedStateChanged(Node*) { }
283 inline void AXObjectCache::childrenChanged(RenderObject*) { }
284 inline void AXObjectCache::childrenChanged(Node*) { }
285 inline void AXObjectCache::childrenChanged(AccessibilityObject*) { }
286 inline void AXObjectCache::textChanged(RenderObject*) { }
287 inline void AXObjectCache::textChanged(Node*) { }
288 inline void AXObjectCache::textChanged(AccessibilityObject*) { }
289 inline void AXObjectCache::updateCacheAfterNodeIsAttached(Node*) { }
290 inline void AXObjectCache::detachWrapper(AccessibilityObject*, AccessibilityDetachmentType) { }
291 inline void AXObjectCache::frameLoadingEventNotification(Frame*, AXLoadingEvent) { }
292 inline void AXObjectCache::frameLoadingEventPlatformNotification(AccessibilityObject*, AXLoadingEvent) { }
293 inline void AXObjectCache::handleActiveDescendantChanged(Node*) { }
294 inline void AXObjectCache::handleAriaExpandedChange(Node*) { }
295 inline void AXObjectCache::handleAriaRoleChanged(Node*) { }
296 inline void AXObjectCache::handleFocusedUIElementChanged(Node*, Node*) { }
297 inline void AXObjectCache::handleScrollbarUpdate(ScrollView*) { }
298 inline void AXObjectCache::handleAttributeChanged(const QualifiedName&, Element*) { }
299 inline void AXObjectCache::recomputeIsIgnored(RenderObject*) { }
300 inline void AXObjectCache::handleScrolledToAnchor(const Node*) { }
301 inline void AXObjectCache::nodeTextChangeNotification(Node*, AXTextChange, unsigned, const String&) { }
302 inline void AXObjectCache::nodeTextChangePlatformNotification(AccessibilityObject*, AXTextChange, unsigned, const String&) { }
303 inline void AXObjectCache::postNotification(AccessibilityObject*, Document*, AXNotification, PostTarget, PostType) { }
304 inline void AXObjectCache::postNotification(RenderObject*, AXNotification, PostTarget, PostType) { }
305 inline void AXObjectCache::postNotification(Node*, AXNotification, PostTarget, PostType) { }
306 inline void AXObjectCache::postPlatformNotification(AccessibilityObject*, AXNotification) { }
307 inline void AXObjectCache::remove(AXID) { }
308 inline void AXObjectCache::remove(RenderObject*) { }
309 inline void AXObjectCache::remove(Node*) { }
310 inline void AXObjectCache::remove(Widget*) { }
311 inline void AXObjectCache::selectedChildrenChanged(RenderObject*) { }
312 inline void AXObjectCache::selectedChildrenChanged(Node*) { }
313 #endif
314
315 }
316
317 #endif