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 "AccessibilityController.h"
     32 
     33 #include "public/platform/WebCString.h"
     34 #include "public/testing/WebTestDelegate.h"
     35 #include "public/web/WebAXObject.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 blink;
     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     WebAXObject::enableAccessibility();
     64     WebAXObject::enableInlineTextBoxAccessibility();
     65     CppBoundClass::bindToJavascript(frame, classname);
     66 }
     67 
     68 void AccessibilityController::reset()
     69 {
     70     m_rootElement = WebAXObject();
     71     m_focusedElement = WebAXObject();
     72     m_elements.clear();
     73     m_notificationCallbacks.clear();
     74 
     75     m_logAccessibilityEvents = false;
     76 }
     77 
     78 void AccessibilityController::setFocusedElement(const WebAXObject& focusedElement)
     79 {
     80     m_focusedElement = focusedElement;
     81 }
     82 
     83 WebAXObjectProxy* AccessibilityController::getFocusedElement()
     84 {
     85     if (m_focusedElement.isNull())
     86         m_focusedElement = m_webView->accessibilityObject();
     87     return m_elements.getOrCreate(m_focusedElement);
     88 }
     89 
     90 WebAXObjectProxy* AccessibilityController::getRootElement()
     91 {
     92     if (m_rootElement.isNull())
     93         m_rootElement = m_webView->accessibilityObject();
     94     return m_elements.createRoot(m_rootElement);
     95 }
     96 
     97 WebAXObjectProxy* AccessibilityController::findAccessibleElementByIdRecursive(const WebAXObject& obj, const WebString& id)
     98 {
     99     if (obj.isNull() || obj.isDetached())
    100         return 0;
    101 
    102     WebNode node = obj.node();
    103     if (!node.isNull() && node.isElementNode()) {
    104         WebElement element = node.to<WebElement>();
    105         element.getAttribute("id");
    106         if (element.getAttribute("id") == id)
    107             return m_elements.getOrCreate(obj);
    108     }
    109 
    110     unsigned childCount = obj.childCount();
    111     for (unsigned i = 0; i < childCount; i++) {
    112         if (WebAXObjectProxy* result = findAccessibleElementByIdRecursive(obj.childAt(i), id))
    113             return result;
    114     }
    115 
    116     return 0;
    117 }
    118 
    119 WebAXObjectProxy* AccessibilityController::getAccessibleElementById(const std::string& id)
    120 {
    121     if (m_rootElement.isNull())
    122         m_rootElement = m_webView->accessibilityObject();
    123 
    124     if (!m_rootElement.updateBackingStoreAndCheckValidity())
    125         return 0;
    126 
    127     return findAccessibleElementByIdRecursive(m_rootElement, WebString::fromUTF8(id.c_str()));
    128 }
    129 
    130 bool AccessibilityController::shouldLogAccessibilityEvents()
    131 {
    132     return m_logAccessibilityEvents;
    133 }
    134 
    135 void AccessibilityController::notificationReceived(const blink::WebAXObject& target, const char* notificationName)
    136 {
    137     // Call notification listeners on the element.
    138     WebAXObjectProxy* element = m_elements.getOrCreate(target);
    139     element->notificationReceived(notificationName);
    140 
    141     // Call global notification listeners.
    142     size_t callbackCount = m_notificationCallbacks.size();
    143     for (size_t i = 0; i < callbackCount; i++) {
    144         CppVariant arguments[2];
    145         arguments[0].set(*element->getAsCppVariant());
    146         arguments[1].set(notificationName);
    147         CppVariant invokeResult;
    148         m_notificationCallbacks[i].invokeDefault(arguments, 2, invokeResult);
    149     }
    150 }
    151 
    152 void AccessibilityController::logAccessibilityEventsCallback(const CppArgumentList&, CppVariant* result)
    153 {
    154     m_logAccessibilityEvents = true;
    155     result->setNull();
    156 }
    157 
    158 void AccessibilityController::addNotificationListenerCallback(const CppArgumentList& arguments, CppVariant* result)
    159 {
    160     if (arguments.size() < 1 || !arguments[0].isObject()) {
    161         result->setNull();
    162         return;
    163     }
    164 
    165     m_notificationCallbacks.push_back(arguments[0]);
    166     result->setNull();
    167 }
    168 
    169 void AccessibilityController::removeNotificationListenerCallback(const CppArgumentList&, CppVariant* result)
    170 {
    171     // FIXME: Implement this.
    172     result->setNull();
    173 }
    174 
    175 void AccessibilityController::focusedElementGetterCallback(CppVariant* result)
    176 {
    177     result->set(*(getFocusedElement()->getAsCppVariant()));
    178 }
    179 
    180 void AccessibilityController::rootElementGetterCallback(CppVariant* result)
    181 {
    182     result->set(*(getRootElement()->getAsCppVariant()));
    183 }
    184 
    185 void AccessibilityController::accessibleElementByIdGetterCallback(const CppArgumentList& arguments, CppVariant* result)
    186 {
    187     result->setNull();
    188 
    189     if (arguments.size() < 1 || !arguments[0].isString())
    190         return;
    191 
    192     std::string id = arguments[0].toString();
    193     WebAXObjectProxy* foundElement = getAccessibleElementById(id);
    194     if (!foundElement)
    195         return;
    196 
    197     result->set(*(foundElement->getAsCppVariant()));
    198 }
    199 
    200 void AccessibilityController::fallbackCallback(const CppArgumentList&, CppVariant* result)
    201 {
    202     m_delegate->printMessage("CONSOLE MESSAGE: JavaScript ERROR: unknown method called on AccessibilityController\n");
    203     result->setNull();
    204 }
    205 
    206 }
    207