Home | History | Annotate | Download | only in runner
      1 /*
      2  * Copyright (C) 2010 Google 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 are
      6  * met:
      7  *
      8  *     * Redistributions of source code must retain the above copyright
      9  * notice, this list of conditions and the following disclaimer.
     10  *     * Redistributions in binary form must reproduce the above
     11  * copyright notice, this list of conditions and the following disclaimer
     12  * in the documentation and/or other materials provided with the
     13  * distribution.
     14  *     * Neither the name of Google Inc. nor the names of its
     15  * contributors may be used to endorse or promote products derived from
     16  * this software without specific prior written permission.
     17  *
     18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     21  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     22  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     23  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     24  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     28  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     29  */
     30 
     31 #include "AccessibilityControllerChromium.h"
     32 
     33 #include "public/platform/WebCString.h"
     34 #include "public/testing/WebTestDelegate.h"
     35 #include "public/web/WebAccessibilityObject.h"
     36 #include "public/web/WebElement.h"
     37 #include "public/web/WebFrame.h"
     38 #include "public/web/WebNode.h"
     39 #include "public/web/WebView.h"
     40 
     41 using namespace WebKit;
     42 
     43 namespace WebTestRunner {
     44 
     45 AccessibilityController::AccessibilityController()
     46     : m_logAccessibilityEvents(false)
     47 {
     48 
     49     bindMethod("logAccessibilityEvents", &AccessibilityController::logAccessibilityEventsCallback);
     50     bindMethod("addNotificationListener", &AccessibilityController::addNotificationListenerCallback);
     51     bindMethod("removeNotificationListener", &AccessibilityController::removeNotificationListenerCallback);
     52 
     53     bindProperty("focusedElement", &AccessibilityController::focusedElementGetterCallback);
     54     bindProperty("rootElement", &AccessibilityController::rootElementGetterCallback);
     55 
     56     bindMethod("accessibleElementById", &AccessibilityController::accessibleElementByIdGetterCallback);
     57 
     58     bindFallbackMethod(&AccessibilityController::fallbackCallback);
     59 }
     60 
     61 void AccessibilityController::bindToJavascript(WebFrame* frame, const WebString& classname)
     62 {
     63     WebAccessibilityObject::enableAccessibility();
     64     CppBoundClass::bindToJavascript(frame, classname);
     65 }
     66 
     67 void AccessibilityController::reset()
     68 {
     69     m_rootElement = WebAccessibilityObject();
     70     m_focusedElement = WebAccessibilityObject();
     71     m_elements.clear();
     72 
     73     m_logAccessibilityEvents = false;
     74 }
     75 
     76 void AccessibilityController::setFocusedElement(const WebAccessibilityObject& focusedElement)
     77 {
     78     m_focusedElement = focusedElement;
     79 }
     80 
     81 AccessibilityUIElement* AccessibilityController::getFocusedElement()
     82 {
     83     if (m_focusedElement.isNull())
     84         m_focusedElement = m_webView->accessibilityObject();
     85     return m_elements.getOrCreate(m_focusedElement);
     86 }
     87 
     88 AccessibilityUIElement* AccessibilityController::getRootElement()
     89 {
     90     if (m_rootElement.isNull())
     91         m_rootElement = m_webView->accessibilityObject();
     92     return m_elements.createRoot(m_rootElement);
     93 }
     94 
     95 AccessibilityUIElement* AccessibilityController::findAccessibleElementByIdRecursive(const WebAccessibilityObject& obj, const WebString& id)
     96 {
     97     if (obj.isNull() || obj.isDetached())
     98         return 0;
     99 
    100     WebNode node = obj.node();
    101     if (!node.isNull() && node.isElementNode()) {
    102         WebElement element = node.to<WebElement>();
    103         element.getAttribute("id");
    104         if (element.getAttribute("id") == id)
    105             return m_elements.getOrCreate(obj);
    106     }
    107 
    108     unsigned childCount = obj.childCount();
    109     for (unsigned i = 0; i < childCount; i++) {
    110         if (AccessibilityUIElement* result = findAccessibleElementByIdRecursive(obj.childAt(i), id))
    111             return result;
    112     }
    113 
    114     return 0;
    115 }
    116 
    117 AccessibilityUIElement* AccessibilityController::getAccessibleElementById(const std::string& id)
    118 {
    119     if (m_rootElement.isNull())
    120         m_rootElement = m_webView->accessibilityObject();
    121 
    122     if (!m_rootElement.updateBackingStoreAndCheckValidity())
    123         return 0;
    124 
    125     return findAccessibleElementByIdRecursive(m_rootElement, WebString::fromUTF8(id.c_str()));
    126 }
    127 
    128 bool AccessibilityController::shouldLogAccessibilityEvents()
    129 {
    130     return m_logAccessibilityEvents;
    131 }
    132 
    133 void AccessibilityController::notificationReceived(const WebKit::WebAccessibilityObject& target, const char* notificationName)
    134 {
    135     // Call notification listeners on the element.
    136     AccessibilityUIElement* element = m_elements.getOrCreate(target);
    137     element->notificationReceived(notificationName);
    138 
    139     // Call global notification listeners.
    140     size_t callbackCount = m_notificationCallbacks.size();
    141     for (size_t i = 0; i < callbackCount; i++) {
    142         CppVariant arguments[2];
    143         arguments[0].set(*element->getAsCppVariant());
    144         arguments[1].set(notificationName);
    145         CppVariant invokeResult;
    146         m_notificationCallbacks[i].invokeDefault(arguments, 2, invokeResult);
    147     }
    148 }
    149 
    150 void AccessibilityController::logAccessibilityEventsCallback(const CppArgumentList&, CppVariant* result)
    151 {
    152     m_logAccessibilityEvents = true;
    153     result->setNull();
    154 }
    155 
    156 void AccessibilityController::addNotificationListenerCallback(const CppArgumentList& arguments, CppVariant* result)
    157 {
    158     if (arguments.size() < 1 || !arguments[0].isObject()) {
    159         result->setNull();
    160         return;
    161     }
    162 
    163     m_notificationCallbacks.push_back(arguments[0]);
    164     result->setNull();
    165 }
    166 
    167 void AccessibilityController::removeNotificationListenerCallback(const CppArgumentList&, CppVariant* result)
    168 {
    169     // FIXME: Implement this.
    170     result->setNull();
    171 }
    172 
    173 void AccessibilityController::focusedElementGetterCallback(CppVariant* result)
    174 {
    175     result->set(*(getFocusedElement()->getAsCppVariant()));
    176 }
    177 
    178 void AccessibilityController::rootElementGetterCallback(CppVariant* result)
    179 {
    180     result->set(*(getRootElement()->getAsCppVariant()));
    181 }
    182 
    183 void AccessibilityController::accessibleElementByIdGetterCallback(const CppArgumentList& arguments, CppVariant* result)
    184 {
    185     result->setNull();
    186 
    187     if (arguments.size() < 1 || !arguments[0].isString())
    188         return;
    189 
    190     std::string id = arguments[0].toString();
    191     AccessibilityUIElement* foundElement = getAccessibleElementById(id);
    192     if (!foundElement)
    193         return;
    194 
    195     result->set(*(foundElement->getAsCppVariant()));
    196 }
    197 
    198 void AccessibilityController::fallbackCallback(const CppArgumentList&, CppVariant* result)
    199 {
    200     m_delegate->printMessage("CONSOLE MESSAGE: JavaScript ERROR: unknown method called on AccessibilityController\n");
    201     result->setNull();
    202 }
    203 
    204 }
    205