• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "core/accessibility/AXObject.h"
30 #include "core/rendering/RenderText.h"
31 #include "platform/Timer.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 AbstractInlineTextBox;
40 class Document;
41 class HTMLAreaElement;
42 class Node;
43 class Page;
44 class RenderObject;
45 class ScrollView;
46 class VisiblePosition;
47 class Widget;
48 
49 struct TextMarkerData {
50     AXID axID;
51     Node* node;
52     int offset;
53     EAffinity affinity;
54 };
55 
56 class AXComputedObjectAttributeCache {
57 public:
create()58     static PassOwnPtr<AXComputedObjectAttributeCache> create() { return adoptPtr(new AXComputedObjectAttributeCache()); }
59 
60     AXObjectInclusion getIgnored(AXID) const;
61     void setIgnored(AXID, AXObjectInclusion);
62 
63     void clear();
64 
65 private:
AXComputedObjectAttributeCache()66     AXComputedObjectAttributeCache() { }
67 
68     struct CachedAXObjectAttributes {
CachedAXObjectAttributesCachedAXObjectAttributes69         CachedAXObjectAttributes() : ignored(DefaultBehavior) { }
70 
71         AXObjectInclusion ignored;
72     };
73 
74     HashMap<AXID, CachedAXObjectAttributes> m_idMapping;
75 };
76 
77 enum PostType { PostSynchronously, PostAsynchronously };
78 
79 class AXObjectCache {
80     WTF_MAKE_NONCOPYABLE(AXObjectCache); WTF_MAKE_FAST_ALLOCATED;
81 public:
82     explicit AXObjectCache(const Document*);
83     ~AXObjectCache();
84 
85     static AXObject* focusedUIElementForPage(const Page*);
86 
87     // Returns the root object for the entire document.
88     AXObject* rootObject();
89 
90     // For AX objects with elements that back them.
91     AXObject* getOrCreate(RenderObject*);
92     AXObject* getOrCreate(Widget*);
93     AXObject* getOrCreate(Node*);
94     AXObject* getOrCreate(AbstractInlineTextBox*);
95 
96     // used for objects without backing elements
97     AXObject* getOrCreate(AccessibilityRole);
98 
99     // will only return the AXObject if it already exists
100     AXObject* get(RenderObject*);
101     AXObject* get(Widget*);
102     AXObject* get(Node*);
103     AXObject* get(AbstractInlineTextBox*);
104 
105     void remove(RenderObject*);
106     void remove(Node*);
107     void remove(Widget*);
108     void remove(AbstractInlineTextBox*);
109     void remove(AXID);
110 
111     void detachWrapper(AXObject*);
112     void attachWrapper(AXObject*);
113     void childrenChanged(Node*);
114     void childrenChanged(RenderObject*);
115     void childrenChanged(AXObject*);
116     void checkedStateChanged(Node*);
117     void selectedChildrenChanged(Node*);
118     void selectedChildrenChanged(RenderObject*);
119     void selectionChanged(Node*);
120     // Called by a node when text or a text equivalent (e.g. alt) attribute is changed.
121     void textChanged(Node*);
122     void textChanged(RenderObject*);
123     // Called when a node has just been attached, so we can make sure we have the right subclass of AXObject.
124     void updateCacheAfterNodeIsAttached(Node*);
125 
126     void handleActiveDescendantChanged(Node*);
127     void handleAriaRoleChanged(Node*);
128     void handleFocusedUIElementChanged(Node* oldFocusedNode, Node* newFocusedNode);
129     void handleScrolledToAnchor(const Node* anchorNode);
130     void handleAriaExpandedChange(Node*);
131     void handleScrollbarUpdate(ScrollView*);
132 
133     void handleAttributeChanged(const QualifiedName& attrName, Element*);
134     void recomputeIsIgnored(RenderObject* renderer);
135 
enableAccessibility()136     static void enableAccessibility() { gAccessibilityEnabled = true; }
accessibilityEnabled()137     static bool accessibilityEnabled() { return gAccessibilityEnabled; }
setInlineTextBoxAccessibility(bool flag)138     static void setInlineTextBoxAccessibility(bool flag) { gInlineTextBoxAccessibility = flag; }
inlineTextBoxAccessibility()139     static bool inlineTextBoxAccessibility() { return gInlineTextBoxAccessibility; }
140 
141     void removeAXID(AXObject*);
isIDinUse(AXID id)142     bool isIDinUse(AXID id) const { return m_idsInUse.contains(id); }
143 
144     Element* rootAXEditableElement(Node*);
145     const Element* rootAXEditableElement(const Node*);
146     bool nodeIsTextControl(const Node*);
147 
148     AXID platformGenerateAXID() const;
objectFromAXID(AXID id)149     AXObject* objectFromAXID(AXID id) const { return m_objects.get(id); }
150 
151     // Text marker utilities.
152     void textMarkerDataForVisiblePosition(TextMarkerData&, const VisiblePosition&);
153     VisiblePosition visiblePositionForTextMarkerData(TextMarkerData&);
154 
155     enum AXNotification {
156         AXActiveDescendantChanged,
157         AXAlert,
158         AXAriaAttributeChanged,
159         AXAutocorrectionOccured,
160         AXBlur,
161         AXCheckedStateChanged,
162         AXChildrenChanged,
163         AXFocusedUIElementChanged,
164         AXHide,
165         AXInvalidStatusChanged,
166         AXLayoutComplete,
167         AXLiveRegionChanged,
168         AXLoadComplete,
169         AXLocationChanged,
170         AXMenuListItemSelected,
171         AXMenuListValueChanged,
172         AXRowCollapsed,
173         AXRowCountChanged,
174         AXRowExpanded,
175         AXScrolledToAnchor,
176         AXSelectedChildrenChanged,
177         AXSelectedTextChanged,
178         AXShow,
179         AXTextChanged,
180         AXTextInserted,
181         AXTextRemoved,
182         AXValueChanged
183     };
184 
185     void postNotification(RenderObject*, AXNotification, bool postToElement, PostType = PostAsynchronously);
186     void postNotification(Node*, AXNotification, bool postToElement, PostType = PostAsynchronously);
187     void postNotification(AXObject*, Document*, AXNotification, bool postToElement, PostType = PostAsynchronously);
188 
189     bool nodeHasRole(Node*, const AtomicString& role);
190 
191     void startCachingComputedObjectAttributesUntilTreeMutates();
192     void stopCachingComputedObjectAttributes();
193 
computedObjectAttributeCache()194     AXComputedObjectAttributeCache* computedObjectAttributeCache() { return m_computedObjectAttributeCache.get(); }
195 
196 protected:
197     void postPlatformNotification(AXObject*, AXNotification);
198     void textChanged(AXObject*);
199     void labelChanged(Element*);
200 
201     // This is a weak reference cache for knowing if Nodes used by TextMarkers are valid.
setNodeInUse(Node * n)202     void setNodeInUse(Node* n) { m_textMarkerNodes.add(n); }
removeNodeForUse(Node * n)203     void removeNodeForUse(Node* n) { m_textMarkerNodes.remove(n); }
isNodeInUse(Node * n)204     bool isNodeInUse(Node* n) { return m_textMarkerNodes.contains(n); }
205 
206 private:
207     Document* m_document;
208     HashMap<AXID, RefPtr<AXObject> > m_objects;
209     HashMap<RenderObject*, AXID> m_renderObjectMapping;
210     HashMap<Widget*, AXID> m_widgetObjectMapping;
211     HashMap<Node*, AXID> m_nodeObjectMapping;
212     HashMap<AbstractInlineTextBox*, AXID> m_inlineTextBoxObjectMapping;
213     HashSet<Node*> m_textMarkerNodes;
214     OwnPtr<AXComputedObjectAttributeCache> m_computedObjectAttributeCache;
215     static bool gAccessibilityEnabled;
216     static bool gInlineTextBoxAccessibility;
217 
218     HashSet<AXID> m_idsInUse;
219 
220     Timer<AXObjectCache> m_notificationPostTimer;
221     Vector<pair<RefPtr<AXObject>, AXNotification> > m_notificationsToPost;
222     void notificationPostTimerFired(Timer<AXObjectCache>*);
223 
224     static AXObject* focusedImageMapUIElement(HTMLAreaElement*);
225 
226     AXID getAXID(AXObject*);
227 };
228 
229 bool nodeHasRole(Node*, const String& role);
230 // This will let you know if aria-hidden was explicitly set to false.
231 bool isNodeAriaVisible(Node*);
232 
233 }
234 
235 #endif
236