diff -r 4f2f89ce4247 -r 303757a437d3 WebKitTools/DumpRenderTree/win/AccessibilityControllerWin.cpp --- a/WebKitTools/DumpRenderTree/win/AccessibilityControllerWin.cpp Fri Sep 17 09:02:29 2010 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,294 +0,0 @@ -/* - * Copyright (C) 2008, 2009, 2010 Apple Inc. All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "AccessibilityController.h" - -#include "AccessibilityUIElement.h" -#include "DumpRenderTree.h" -#include "FrameLoadDelegate.h" -#include -#include -#include -#include -#include -#include -#include - -using namespace std; - -AccessibilityController::AccessibilityController() - : m_focusEventHook(0) - , m_scrollingStartEventHook(0) - , m_valueChangeEventHook(0) - , m_allEventsHook(0) -{ -} - -AccessibilityController::~AccessibilityController() -{ - setLogFocusEvents(false); - setLogValueChangeEvents(false); - - if (m_allEventsHook) - UnhookWinEvent(m_allEventsHook); - - for (HashMap::iterator it = m_notificationListeners.begin(); it != m_notificationListeners.end(); ++it) - JSValueUnprotect(frame->globalContext(), it->second); -} - -AccessibilityUIElement AccessibilityController::elementAtPoint(int x, int y) -{ - // FIXME: implement - return 0; -} - -AccessibilityUIElement AccessibilityController::focusedElement() -{ - COMPtr rootAccessible = rootElement().platformUIElement(); - - VARIANT vFocus; - if (FAILED(rootAccessible->get_accFocus(&vFocus))) - return 0; - - if (V_VT(&vFocus) == VT_I4) { - ASSERT(V_I4(&vFocus) == CHILDID_SELF); - // The root accessible object is the focused object. - return rootAccessible; - } - - ASSERT(V_VT(&vFocus) == VT_DISPATCH); - // We have an IDispatch; query for IAccessible. - return COMPtr(Query, V_DISPATCH(&vFocus)); -} - -AccessibilityUIElement AccessibilityController::rootElement() -{ - COMPtr view; - if (FAILED(frame->webView(&view))) - return 0; - - COMPtr viewPrivate(Query, view); - if (!viewPrivate) - return 0; - - HWND webViewWindow; - if (FAILED(viewPrivate->viewWindow((OLE_HANDLE*)&webViewWindow))) - return 0; - - // Get the root accessible object by querying for the accessible object for the - // WebView's window. - COMPtr rootAccessible; - if (FAILED(AccessibleObjectFromWindow(webViewWindow, static_cast(OBJID_CLIENT), __uuidof(IAccessible), reinterpret_cast(&rootAccessible)))) - return 0; - - return rootAccessible; -} - -static void CALLBACK logEventProc(HWINEVENTHOOK, DWORD event, HWND hwnd, LONG idObject, LONG idChild, DWORD, DWORD) -{ - // Get the accessible object for this event. - COMPtr parentObject; - - VARIANT vChild; - VariantInit(&vChild); - - HRESULT hr = AccessibleObjectFromEvent(hwnd, idObject, idChild, &parentObject, &vChild); - ASSERT(SUCCEEDED(hr)); - - // Get the name of the focused element, and log it to stdout. - BSTR nameBSTR; - hr = parentObject->get_accName(vChild, &nameBSTR); - ASSERT(SUCCEEDED(hr)); - wstring name(nameBSTR, ::SysStringLen(nameBSTR)); - SysFreeString(nameBSTR); - - switch (event) { - case EVENT_OBJECT_FOCUS: - printf("Received focus event for object '%S'.\n", name.c_str()); - break; - - case EVENT_OBJECT_VALUECHANGE: { - BSTR valueBSTR; - hr = parentObject->get_accValue(vChild, &valueBSTR); - ASSERT(SUCCEEDED(hr)); - wstring value(valueBSTR, ::SysStringLen(valueBSTR)); - SysFreeString(valueBSTR); - - printf("Received value change event for object '%S', value '%S'.\n", name.c_str(), value.c_str()); - break; - } - - case EVENT_SYSTEM_SCROLLINGSTART: - printf("Received scrolling start event for object '%S'.\n", name.c_str()); - break; - - default: - printf("Received unknown event for object '%S'.\n", name.c_str()); - break; - } - - VariantClear(&vChild); -} - -void AccessibilityController::setLogFocusEvents(bool logFocusEvents) -{ - if (!!m_focusEventHook == logFocusEvents) - return; - - if (!logFocusEvents) { - UnhookWinEvent(m_focusEventHook); - m_focusEventHook = 0; - return; - } - - // Ensure that accessibility is initialized for the WebView by querying for - // the root accessible object. - rootElement(); - - m_focusEventHook = SetWinEventHook(EVENT_OBJECT_FOCUS, EVENT_OBJECT_FOCUS, GetModuleHandle(0), logEventProc, GetCurrentProcessId(), 0, WINEVENT_INCONTEXT); - - ASSERT(m_focusEventHook); -} - -void AccessibilityController::setLogValueChangeEvents(bool logValueChangeEvents) -{ - if (!!m_valueChangeEventHook == logValueChangeEvents) - return; - - if (!logValueChangeEvents) { - UnhookWinEvent(m_valueChangeEventHook); - m_valueChangeEventHook = 0; - return; - } - - // Ensure that accessibility is initialized for the WebView by querying for - // the root accessible object. - rootElement(); - - m_valueChangeEventHook = SetWinEventHook(EVENT_OBJECT_VALUECHANGE, EVENT_OBJECT_VALUECHANGE, GetModuleHandle(0), logEventProc, GetCurrentProcessId(), 0, WINEVENT_INCONTEXT); - - ASSERT(m_valueChangeEventHook); -} - -void AccessibilityController::setLogScrollingStartEvents(bool logScrollingStartEvents) -{ - if (!!m_scrollingStartEventHook == logScrollingStartEvents) - return; - - if (!logScrollingStartEvents) { - UnhookWinEvent(m_scrollingStartEventHook); - m_scrollingStartEventHook = 0; - return; - } - - // Ensure that accessibility is initialized for the WebView by querying for - // the root accessible object. - rootElement(); - - m_scrollingStartEventHook = SetWinEventHook(EVENT_SYSTEM_SCROLLINGSTART, EVENT_SYSTEM_SCROLLINGSTART, GetModuleHandle(0), logEventProc, GetCurrentProcessId(), 0, WINEVENT_INCONTEXT); - - ASSERT(m_scrollingStartEventHook); -} - -static string stringEvent(DWORD event) -{ - switch(event) { - case EVENT_OBJECT_VALUECHANGE: - return "value change event"; - default: - return "unknown event"; - } -} - -static void CALLBACK notificationListenerProc(HWINEVENTHOOK, DWORD event, HWND hwnd, LONG idObject, LONG idChild, DWORD, DWORD) -{ - // Get the accessible object for this event. - COMPtr parentObject; - - VARIANT vChild; - VariantInit(&vChild); - - HRESULT hr = AccessibleObjectFromEvent(hwnd, idObject, idChild, &parentObject, &vChild); - ASSERT(SUCCEEDED(hr)); - - COMPtr childDispatch; - if (FAILED(parentObject->get_accChild(vChild, &childDispatch))) { - VariantClear(&vChild); - return; - } - - COMPtr childAccessible(Query, childDispatch); - - sharedFrameLoadDelegate->accessibilityController()->notificationReceived(childAccessible, stringEvent(event)); - - VariantClear(&vChild); -} - -static COMPtr comparableObject(const COMPtr& serviceProvider) -{ - COMPtr comparable; - serviceProvider->QueryService(SID_AccessibleComparable, __uuidof(IAccessibleComparable), reinterpret_cast(&comparable)); - return comparable; -} - -void AccessibilityController::notificationReceived(PlatformUIElement element, const string& eventName) -{ - for (HashMap::iterator it = m_notificationListeners.begin(); it != m_notificationListeners.end(); ++it) { - COMPtr thisServiceProvider(Query, it->first); - if (!thisServiceProvider) - continue; - - COMPtr thisComparable = comparableObject(thisServiceProvider); - if (!thisComparable) - continue; - - COMPtr elementServiceProvider(Query, element); - if (!elementServiceProvider) - continue; - - COMPtr elementComparable = comparableObject(elementServiceProvider); - if (!elementComparable) - continue; - - BOOL isSame = FALSE; - thisComparable->isSameObject(elementComparable.get(), &isSame); - if (!isSame) - continue; - - JSRetainPtr jsNotification(Adopt, JSStringCreateWithUTF8CString(eventName.c_str())); - JSValueRef argument = JSValueMakeString(frame->globalContext(), jsNotification.get()); - JSObjectCallAsFunction(frame->globalContext(), it->second, NULL, 1, &argument, NULL); - } -} - -void AccessibilityController::addNotificationListener(PlatformUIElement element, JSObjectRef functionCallback) -{ - if (!m_allEventsHook) - m_allEventsHook = SetWinEventHook(EVENT_MIN, EVENT_MAX, GetModuleHandle(0), notificationListenerProc, GetCurrentProcessId(), 0, WINEVENT_INCONTEXT); - - JSValueProtect(frame->globalContext(), functionCallback); - m_notificationListeners.add(element, functionCallback); -}