Home | History | Annotate | Download | only in accessibility
      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/AccessibilityObject.h"
     30 #include "core/platform/Timer.h"
     31 #include "wtf/Forward.h"
     32 #include "wtf/HashMap.h"
     33 #include "wtf/HashSet.h"
     34 #include "wtf/RefPtr.h"
     35 
     36 namespace WebCore {
     37 
     38 class Document;
     39 class HTMLAreaElement;
     40 class Node;
     41 class Page;
     42 class RenderObject;
     43 class ScrollView;
     44 class VisiblePosition;
     45 class Widget;
     46 
     47 struct TextMarkerData {
     48     AXID axID;
     49     Node* node;
     50     int offset;
     51     EAffinity affinity;
     52 };
     53 
     54 class AXComputedObjectAttributeCache {
     55 public:
     56     static PassOwnPtr<AXComputedObjectAttributeCache> create() { return adoptPtr(new AXComputedObjectAttributeCache()); }
     57 
     58     AccessibilityObjectInclusion getIgnored(AXID) const;
     59     void setIgnored(AXID, AccessibilityObjectInclusion);
     60 
     61 private:
     62     AXComputedObjectAttributeCache() { }
     63 
     64     struct CachedAXObjectAttributes {
     65         CachedAXObjectAttributes() : ignored(DefaultBehavior) { }
     66 
     67         AccessibilityObjectInclusion ignored;
     68     };
     69 
     70     HashMap<AXID, CachedAXObjectAttributes> m_idMapping;
     71 };
     72 
     73 enum PostType { PostSynchronously, PostAsynchronously };
     74 
     75 class AXObjectCache {
     76     WTF_MAKE_NONCOPYABLE(AXObjectCache); WTF_MAKE_FAST_ALLOCATED;
     77 public:
     78     explicit AXObjectCache(const Document*);
     79     ~AXObjectCache();
     80 
     81     static AccessibilityObject* focusedUIElementForPage(const Page*);
     82 
     83     // Returns the root object for the entire document.
     84     AccessibilityObject* rootObject();
     85 
     86     // For AX objects with elements that back them.
     87     AccessibilityObject* getOrCreate(RenderObject*);
     88     AccessibilityObject* getOrCreate(Widget*);
     89     AccessibilityObject* getOrCreate(Node*);
     90 
     91     // used for objects without backing elements
     92     AccessibilityObject* getOrCreate(AccessibilityRole);
     93 
     94     // will only return the AccessibilityObject if it already exists
     95     AccessibilityObject* get(RenderObject*);
     96     AccessibilityObject* get(Widget*);
     97     AccessibilityObject* get(Node*);
     98 
     99     void remove(RenderObject*);
    100     void remove(Node*);
    101     void remove(Widget*);
    102     void remove(AXID);
    103 
    104     void detachWrapper(AccessibilityObject*);
    105     void attachWrapper(AccessibilityObject*);
    106     void childrenChanged(Node*);
    107     void childrenChanged(RenderObject*);
    108     void childrenChanged(AccessibilityObject*);
    109     void checkedStateChanged(Node*);
    110     void selectedChildrenChanged(Node*);
    111     void selectedChildrenChanged(RenderObject*);
    112     void selectionChanged(Node*);
    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     static bool accessibilityEnabled() { return gAccessibilityEnabled; }
    132 #else
    133     static void enableAccessibility() { }
    134     static bool accessibilityEnabled() { return false; }
    135 #endif
    136 
    137     void removeAXID(AccessibilityObject*);
    138     bool isIDinUse(AXID id) const { return m_idsInUse.contains(id); }
    139 
    140     Element* rootAXEditableElement(Node*);
    141     const Element* rootAXEditableElement(const Node*);
    142     bool nodeIsTextControl(const Node*);
    143 
    144     AXID platformGenerateAXID() const;
    145     AccessibilityObject* objectFromAXID(AXID id) const { return m_objects.get(id); }
    146 
    147     // Text marker utilities.
    148     void textMarkerDataForVisiblePosition(TextMarkerData&, const VisiblePosition&);
    149     VisiblePosition visiblePositionForTextMarkerData(TextMarkerData&);
    150 
    151     enum AXNotification {
    152         AXActiveDescendantChanged,
    153         AXAutocorrectionOccured,
    154         AXCheckedStateChanged,
    155         AXChildrenChanged,
    156         AXFocusedUIElementChanged,
    157         AXLayoutComplete,
    158         AXLoadComplete,
    159         AXSelectedChildrenChanged,
    160         AXSelectedTextChanged,
    161         AXValueChanged,
    162         AXScrolledToAnchor,
    163         AXLiveRegionChanged,
    164         AXMenuListItemSelected,
    165         AXMenuListValueChanged,
    166         AXRowCountChanged,
    167         AXRowCollapsed,
    168         AXRowExpanded,
    169         AXInvalidStatusChanged,
    170         AXTextChanged,
    171         AXAriaAttributeChanged
    172     };
    173 
    174     void postNotification(RenderObject*, AXNotification, bool postToElement, PostType = PostAsynchronously);
    175     void postNotification(Node*, AXNotification, bool postToElement, PostType = PostAsynchronously);
    176     void postNotification(AccessibilityObject*, Document*, AXNotification, bool postToElement, PostType = PostAsynchronously);
    177 
    178     enum AXTextChange {
    179         AXTextInserted,
    180         AXTextDeleted,
    181     };
    182 
    183     void nodeTextChangeNotification(Node*, AXTextChange, unsigned offset, const String&);
    184     bool nodeHasRole(Node*, const AtomicString& role);
    185 
    186     void startCachingComputedObjectAttributesUntilTreeMutates();
    187     void stopCachingComputedObjectAttributes();
    188 
    189     AXComputedObjectAttributeCache* computedObjectAttributeCache() { return m_computedObjectAttributeCache.get(); }
    190 
    191 protected:
    192     void postPlatformNotification(AccessibilityObject*, AXNotification);
    193     void nodeTextChangePlatformNotification(AccessibilityObject*, AXTextChange, unsigned offset, const String&);
    194     void textChanged(AccessibilityObject*);
    195     void labelChanged(Element*);
    196 
    197     // This is a weak reference cache for knowing if Nodes used by TextMarkers are valid.
    198     void setNodeInUse(Node* n) { m_textMarkerNodes.add(n); }
    199     void removeNodeForUse(Node* n) { m_textMarkerNodes.remove(n); }
    200     bool isNodeInUse(Node* n) { return m_textMarkerNodes.contains(n); }
    201 
    202 private:
    203     Document* m_document;
    204     HashMap<AXID, RefPtr<AccessibilityObject> > m_objects;
    205     HashMap<RenderObject*, AXID> m_renderObjectMapping;
    206     HashMap<Widget*, AXID> m_widgetObjectMapping;
    207     HashMap<Node*, AXID> m_nodeObjectMapping;
    208     HashSet<Node*> m_textMarkerNodes;
    209     OwnPtr<AXComputedObjectAttributeCache> m_computedObjectAttributeCache;
    210     static bool gAccessibilityEnabled;
    211 
    212     HashSet<AXID> m_idsInUse;
    213 
    214     Timer<AXObjectCache> m_notificationPostTimer;
    215     Vector<pair<RefPtr<AccessibilityObject>, AXNotification> > m_notificationsToPost;
    216     void notificationPostTimerFired(Timer<AXObjectCache>*);
    217 
    218     static AccessibilityObject* focusedImageMapUIElement(HTMLAreaElement*);
    219 
    220     AXID getAXID(AccessibilityObject*);
    221 };
    222 
    223 bool nodeHasRole(Node*, const String& role);
    224 // This will let you know if aria-hidden was explicitly set to false.
    225 bool isNodeAriaVisible(Node*);
    226 
    227 #if !HAVE(ACCESSIBILITY)
    228 inline AccessibilityObjectInclusion AXComputedObjectAttributeCache::getIgnored(AXID) const { return DefaultBehavior; }
    229 inline void AXComputedObjectAttributeCache::setIgnored(AXID, AccessibilityObjectInclusion) { }
    230 inline AXObjectCache::AXObjectCache(const Document* doc) : m_document(const_cast<Document*>(doc)), m_notificationPostTimer(this, 0) { }
    231 inline AXObjectCache::~AXObjectCache() { }
    232 inline AccessibilityObject* AXObjectCache::focusedUIElementForPage(const Page*) { return 0; }
    233 inline AccessibilityObject* AXObjectCache::get(RenderObject*) { return 0; }
    234 inline AccessibilityObject* AXObjectCache::get(Node*) { return 0; }
    235 inline AccessibilityObject* AXObjectCache::get(Widget*) { return 0; }
    236 inline AccessibilityObject* AXObjectCache::getOrCreate(AccessibilityRole) { return 0; }
    237 inline AccessibilityObject* AXObjectCache::getOrCreate(RenderObject*) { return 0; }
    238 inline AccessibilityObject* AXObjectCache::getOrCreate(Node*) { return 0; }
    239 inline AccessibilityObject* AXObjectCache::getOrCreate(Widget*) { return 0; }
    240 inline AccessibilityObject* AXObjectCache::rootObject() { return 0; }
    241 inline Element* AXObjectCache::rootAXEditableElement(Node*) { return 0; }
    242 inline bool nodeHasRole(Node*, const String&) { return false; }
    243 inline void AXObjectCache::startCachingComputedObjectAttributesUntilTreeMutates() { }
    244 inline void AXObjectCache::stopCachingComputedObjectAttributes() { }
    245 inline bool isNodeAriaVisible(Node*) { return true; }
    246 inline const Element* AXObjectCache::rootAXEditableElement(const Node*) { return 0; }
    247 inline void AXObjectCache::attachWrapper(AccessibilityObject*) { }
    248 inline void AXObjectCache::checkedStateChanged(Node*) { }
    249 inline void AXObjectCache::childrenChanged(RenderObject*) { }
    250 inline void AXObjectCache::childrenChanged(Node*) { }
    251 inline void AXObjectCache::childrenChanged(AccessibilityObject*) { }
    252 inline void AXObjectCache::textChanged(RenderObject*) { }
    253 inline void AXObjectCache::textChanged(Node*) { }
    254 inline void AXObjectCache::textChanged(AccessibilityObject*) { }
    255 inline void AXObjectCache::updateCacheAfterNodeIsAttached(Node*) { }
    256 inline void AXObjectCache::detachWrapper(AccessibilityObject*) { }
    257 inline void AXObjectCache::handleActiveDescendantChanged(Node*) { }
    258 inline void AXObjectCache::handleAriaExpandedChange(Node*) { }
    259 inline void AXObjectCache::handleAriaRoleChanged(Node*) { }
    260 inline void AXObjectCache::handleFocusedUIElementChanged(Node*, Node*) { }
    261 inline void AXObjectCache::handleScrollbarUpdate(ScrollView*) { }
    262 inline void AXObjectCache::handleAttributeChanged(const QualifiedName&, Element*) { }
    263 inline void AXObjectCache::recomputeIsIgnored(RenderObject*) { }
    264 inline void AXObjectCache::handleScrolledToAnchor(const Node*) { }
    265 inline void AXObjectCache::nodeTextChangeNotification(Node*, AXTextChange, unsigned, const String&) { }
    266 inline void AXObjectCache::nodeTextChangePlatformNotification(AccessibilityObject*, AXTextChange, unsigned, const String&) { }
    267 inline void AXObjectCache::postNotification(AccessibilityObject*, Document*, AXNotification, bool, PostType) { }
    268 inline void AXObjectCache::postNotification(RenderObject*, AXNotification, bool, PostType) { }
    269 inline void AXObjectCache::postNotification(Node*, AXNotification, bool, PostType) { }
    270 inline void AXObjectCache::postPlatformNotification(AccessibilityObject*, AXNotification) { }
    271 inline void AXObjectCache::remove(AXID) { }
    272 inline void AXObjectCache::remove(RenderObject*) { }
    273 inline void AXObjectCache::remove(Node*) { }
    274 inline void AXObjectCache::remove(Widget*) { }
    275 inline void AXObjectCache::selectedChildrenChanged(RenderObject*) { }
    276 inline void AXObjectCache::selectedChildrenChanged(Node*) { }
    277 #endif
    278 
    279 }
    280 
    281 #endif
    282