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(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 136 static void enableAccessibility() { gAccessibilityEnabled = true; } 137 static bool accessibilityEnabled() { return gAccessibilityEnabled; } 138 static void setInlineTextBoxAccessibility(bool flag) { gInlineTextBoxAccessibility = flag; } 139 static bool inlineTextBoxAccessibility() { return gInlineTextBoxAccessibility; } 140 141 void removeAXID(AXObject*); 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; 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 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. 202 void setNodeInUse(Node* n) { m_textMarkerNodes.add(n); } 203 void removeNodeForUse(Node* n) { m_textMarkerNodes.remove(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