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: 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: 66 AXComputedObjectAttributeCache() { } 67 68 struct CachedAXObjectAttributes { 69 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(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 clearWeakMembers(Visitor*); 112 113 void detachWrapper(AXObject*); 114 void attachWrapper(AXObject*); 115 void childrenChanged(Node*); 116 void childrenChanged(RenderObject*); 117 void childrenChanged(AXObject*); 118 void checkedStateChanged(Node*); 119 void selectedChildrenChanged(Node*); 120 void selectedChildrenChanged(RenderObject*); 121 void selectionChanged(Node*); 122 // Called by a node when text or a text equivalent (e.g. alt) attribute is changed. 123 void textChanged(Node*); 124 void textChanged(RenderObject*); 125 // Called when a node has just been attached, so we can make sure we have the right subclass of AXObject. 126 void updateCacheAfterNodeIsAttached(Node*); 127 128 void handleActiveDescendantChanged(Node*); 129 void handleAriaRoleChanged(Node*); 130 void handleFocusedUIElementChanged(Node* oldFocusedNode, Node* newFocusedNode); 131 void handleScrolledToAnchor(const Node* anchorNode); 132 void handleAriaExpandedChange(Node*); 133 134 // Called when scroll bars are added / removed (as the view resizes). 135 void handleScrollbarUpdate(ScrollView*); 136 137 void handleLayoutComplete(RenderObject*); 138 139 // Called when the scroll offset changes. 140 void handleScrollPositionChanged(ScrollView*); 141 void handleScrollPositionChanged(RenderObject*); 142 143 void handleAttributeChanged(const QualifiedName& attrName, Element*); 144 void recomputeIsIgnored(RenderObject* renderer); 145 146 void inlineTextBoxesUpdated(RenderObject* renderer); 147 148 static void enableAccessibility() { gAccessibilityEnabled = true; } 149 static bool accessibilityEnabled() { return gAccessibilityEnabled; } 150 static void setInlineTextBoxAccessibility(bool flag) { gInlineTextBoxAccessibility = flag; } 151 static bool inlineTextBoxAccessibility() { return gInlineTextBoxAccessibility; } 152 153 void removeAXID(AXObject*); 154 bool isIDinUse(AXID id) const { return m_idsInUse.contains(id); } 155 156 Element* rootAXEditableElement(Node*); 157 const Element* rootAXEditableElement(const Node*); 158 bool nodeIsTextControl(const Node*); 159 160 AXID platformGenerateAXID() const; 161 AXObject* objectFromAXID(AXID id) const { return m_objects.get(id); } 162 163 enum AXNotification { 164 AXActiveDescendantChanged, 165 AXAlert, 166 AXAriaAttributeChanged, 167 AXAutocorrectionOccured, 168 AXBlur, 169 AXCheckedStateChanged, 170 AXChildrenChanged, 171 AXFocusedUIElementChanged, 172 AXHide, 173 AXInvalidStatusChanged, 174 AXLayoutComplete, 175 AXLiveRegionChanged, 176 AXLoadComplete, 177 AXLocationChanged, 178 AXMenuListItemSelected, 179 AXMenuListValueChanged, 180 AXRowCollapsed, 181 AXRowCountChanged, 182 AXRowExpanded, 183 AXScrollPositionChanged, 184 AXScrolledToAnchor, 185 AXSelectedChildrenChanged, 186 AXSelectedTextChanged, 187 AXShow, 188 AXTextChanged, 189 AXTextInserted, 190 AXTextRemoved, 191 AXValueChanged 192 }; 193 194 void postNotification(RenderObject*, AXNotification, bool postToElement, PostType = PostAsynchronously); 195 void postNotification(Node*, AXNotification, bool postToElement, PostType = PostAsynchronously); 196 void postNotification(AXObject*, Document*, AXNotification, bool postToElement, PostType = PostAsynchronously); 197 198 bool nodeHasRole(Node*, const AtomicString& role); 199 200 AXComputedObjectAttributeCache* computedObjectAttributeCache() { return m_computedObjectAttributeCache.get(); } 201 202 protected: 203 void postPlatformNotification(AXObject*, AXNotification); 204 void textChanged(AXObject*); 205 void labelChanged(Element*); 206 207 // This is a weak reference cache for knowing if Nodes used by TextMarkers are valid. 208 void setNodeInUse(Node* n) { m_textMarkerNodes.add(n); } 209 void removeNodeForUse(Node* n) { m_textMarkerNodes.remove(n); } 210 bool isNodeInUse(Node* n) { return m_textMarkerNodes.contains(n); } 211 212 private: 213 Document& m_document; 214 HashMap<AXID, RefPtr<AXObject> > m_objects; 215 HashMap<RenderObject*, AXID> m_renderObjectMapping; 216 HashMap<Widget*, AXID> m_widgetObjectMapping; 217 HashMap<Node*, AXID> m_nodeObjectMapping; 218 HashMap<AbstractInlineTextBox*, AXID> m_inlineTextBoxObjectMapping; 219 HashSet<Node*> m_textMarkerNodes; 220 OwnPtr<AXComputedObjectAttributeCache> m_computedObjectAttributeCache; 221 static bool gAccessibilityEnabled; 222 static bool gInlineTextBoxAccessibility; 223 224 HashSet<AXID> m_idsInUse; 225 226 Timer<AXObjectCache> m_notificationPostTimer; 227 Vector<pair<RefPtr<AXObject>, AXNotification> > m_notificationsToPost; 228 void notificationPostTimerFired(Timer<AXObjectCache>*); 229 230 static AXObject* focusedImageMapUIElement(HTMLAreaElement*); 231 232 AXID getAXID(AXObject*); 233 }; 234 235 bool nodeHasRole(Node*, const String& role); 236 // This will let you know if aria-hidden was explicitly set to false. 237 bool isNodeAriaVisible(Node*); 238 239 } 240 241 #endif 242