1/* 2 * Copyright (C) 2008, 2009, 2010, 2013 Apple Inc. All Rights Reserved. 3 * Copyright (C) 2012 Serotek Corporation. All Rights Reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY 15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR 18 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 21 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 22 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 */ 26 27 28#include "config.h" 29#include "AXObjectCache.h" 30 31#include "AccessibilityObject.h" 32#include "Chrome.h" 33#include "ChromeClient.h" 34#include "Document.h" 35#include "Page.h" 36#include "RenderObject.h" 37 38// Provided by IAccessibleEventID.idl 39#define IA2_EVENT_DOCUMENT_LOAD_COMPLETE 261 40 41using namespace std; 42 43namespace WebCore { 44 45void AXObjectCache::detachWrapper(AccessibilityObject* obj, AccessibilityDetachmentType) 46{ 47 // On Windows, AccessibilityObjects are created when get_accChildCount is 48 // called, but they are not wrapped until get_accChild is called, so this 49 // object may not have a wrapper. 50 if (AccessibilityObjectWrapper* wrapper = obj->wrapper()) 51 wrapper->detach(); 52} 53 54void AXObjectCache::attachWrapper(AccessibilityObject*) 55{ 56 // On Windows, AccessibilityObjects are wrapped when the accessibility 57 // software requests them via get_accChild. 58} 59 60void AXObjectCache::handleScrolledToAnchor(const Node* anchorNode) 61{ 62 // The anchor node may not be accessible. Post the notification for the 63 // first accessible object. 64 postPlatformNotification(AccessibilityObject::firstAccessibleObjectFromNode(anchorNode), AXScrolledToAnchor); 65} 66 67void AXObjectCache::postPlatformNotification(AccessibilityObject* obj, AXNotification notification) 68{ 69 if (!obj) 70 return; 71 72 Document* document = obj->document(); 73 if (!document) 74 return; 75 76 Page* page = document->page(); 77 if (!page || !page->chrome().platformPageClient()) 78 return; 79 80 DWORD msaaEvent; 81 switch (notification) { 82 case AXCheckedStateChanged: 83 msaaEvent = EVENT_OBJECT_STATECHANGE; 84 break; 85 86 case AXFocusedUIElementChanged: 87 case AXActiveDescendantChanged: 88 msaaEvent = EVENT_OBJECT_FOCUS; 89 break; 90 91 case AXScrolledToAnchor: 92 msaaEvent = EVENT_SYSTEM_SCROLLINGSTART; 93 break; 94 95 case AXLayoutComplete: 96 msaaEvent = EVENT_OBJECT_REORDER; 97 break; 98 99 case AXLoadComplete: 100 msaaEvent = IA2_EVENT_DOCUMENT_LOAD_COMPLETE; 101 break; 102 103 case AXValueChanged: 104 case AXMenuListValueChanged: 105 msaaEvent = EVENT_OBJECT_VALUECHANGE; 106 break; 107 108 case AXMenuListItemSelected: 109 msaaEvent = EVENT_OBJECT_SELECTION; 110 break; 111 112 default: 113 return; 114 } 115 116 // Windows will end up calling get_accChild() on the root accessible 117 // object for the WebView, passing the child ID that we specify below. We 118 // negate the AXID so we know that the caller is passing the ID of an 119 // element, not the index of a child element. 120 121 ASSERT(obj->axObjectID() >= 1); 122 ASSERT(obj->axObjectID() <= numeric_limits<LONG>::max()); 123 124 NotifyWinEvent(msaaEvent, page->chrome().platformPageClient(), OBJID_CLIENT, -static_cast<LONG>(obj->axObjectID())); 125} 126 127void AXObjectCache::nodeTextChangePlatformNotification(AccessibilityObject*, AXTextChange, unsigned, const String&) 128{ 129} 130 131void AXObjectCache::frameLoadingEventPlatformNotification(AccessibilityObject* obj, AXLoadingEvent notification) 132{ 133 if (!obj) 134 return; 135 136 Document* document = obj->document(); 137 if (!document) 138 return; 139 140 Page* page = document->page(); 141 if (!page) 142 return; 143 144 if (notification == AXLoadingStarted) 145 page->chrome().client().AXStartFrameLoad(); 146 else if (notification == AXLoadingFinished) 147 page->chrome().client().AXFinishFrameLoad(); 148} 149 150AXID AXObjectCache::platformGenerateAXID() const 151{ 152 static AXID lastUsedID = 0; 153 154 // Generate a new ID. Windows accessibility relies on a positive AXID, 155 // ranging from 1 to LONG_MAX. 156 AXID objID = lastUsedID; 157 do { 158 ++objID; 159 objID %= std::numeric_limits<LONG>::max(); 160 } while (objID == 0 || HashTraits<AXID>::isDeletedValue(objID) || m_idsInUse.contains(objID)); 161 162 ASSERT(objID >= 1 && objID <= std::numeric_limits<LONG>::max()); 163 164 lastUsedID = objID; 165 166 return objID; 167} 168 169void AXObjectCache::platformHandleFocusedUIElementChanged(Node*, Node* newFocusedNode) 170{ 171 if (!newFocusedNode) 172 return; 173 174 Page* page = newFocusedNode->document().page(); 175 if (!page || !page->chrome().platformPageClient()) 176 return; 177 178 AccessibilityObject* focusedObject = focusedUIElementForPage(page); 179 if (!focusedObject) 180 return; 181 182 ASSERT(!focusedObject->accessibilityIsIgnored()); 183 184 postPlatformNotification(focusedObject, AXFocusedUIElementChanged); 185} 186 187} // namespace WebCore 188