Home | History | Annotate | Download | only in win
      1 /*
      2  * Copyright (C) 2008 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 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 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 #include "config.h"
     27 #include "AccessibilityUIElement.h"
     28 
     29 #include "AccessibilityController.h"
     30 #include "DumpRenderTree.h"
     31 #include "FrameLoadDelegate.h"
     32 #include <JavaScriptCore/JSStringRef.h>
     33 #include <tchar.h>
     34 #include <string>
     35 
     36 using std::wstring;
     37 
     38 AccessibilityUIElement::AccessibilityUIElement(PlatformUIElement element)
     39     : m_element(element)
     40 {
     41 }
     42 
     43 AccessibilityUIElement::AccessibilityUIElement(const AccessibilityUIElement& other)
     44     : m_element(other.m_element)
     45 {
     46 }
     47 
     48 AccessibilityUIElement::~AccessibilityUIElement()
     49 {
     50 }
     51 
     52 void AccessibilityUIElement::getLinkedUIElements(Vector<AccessibilityUIElement>&)
     53 {
     54 }
     55 
     56 void AccessibilityUIElement::getDocumentLinks(Vector<AccessibilityUIElement>&)
     57 {
     58 }
     59 
     60 void AccessibilityUIElement::getChildren(Vector<AccessibilityUIElement>& children)
     61 {
     62     long childCount;
     63     if (FAILED(m_element->get_accChildCount(&childCount)))
     64         return;
     65     for (long i = 0; i < childCount; ++i)
     66         children.append(getChildAtIndex(i));
     67 }
     68 
     69 void AccessibilityUIElement::getChildrenWithRange(Vector<AccessibilityUIElement>& elementVector, unsigned location, unsigned length)
     70 {
     71     long childCount;
     72     unsigned appendedCount = 0;
     73     if (FAILED(m_element->get_accChildCount(&childCount)))
     74         return;
     75     for (long i = location; i < childCount && appendedCount < length; ++i, ++appendedCount)
     76         elementVector.append(getChildAtIndex(i));
     77 }
     78 
     79 int AccessibilityUIElement::childrenCount()
     80 {
     81     long childCount;
     82     m_element->get_accChildCount(&childCount);
     83     return childCount;
     84 }
     85 
     86 AccessibilityUIElement AccessibilityUIElement::elementAtPoint(int x, int y)
     87 {
     88     return 0;
     89 }
     90 
     91 AccessibilityUIElement AccessibilityUIElement::getChildAtIndex(unsigned index)
     92 {
     93     COMPtr<IDispatch> child;
     94     VARIANT vChild;
     95     ::VariantInit(&vChild);
     96     V_VT(&vChild) = VT_I4;
     97     // In MSAA, index 0 is the object itself.
     98     V_I4(&vChild) = index + 1;
     99     if (FAILED(m_element->get_accChild(vChild, &child)))
    100         return 0;
    101     return COMPtr<IAccessible>(Query, child);
    102 }
    103 
    104 unsigned AccessibilityUIElement::indexOfChild(AccessibilityUIElement* element)
    105 {
    106     // FIXME: implement
    107     return 0;
    108 }
    109 
    110 JSStringRef AccessibilityUIElement::allAttributes()
    111 {
    112     return JSStringCreateWithCharacters(0, 0);
    113 }
    114 
    115 JSStringRef AccessibilityUIElement::attributesOfLinkedUIElements()
    116 {
    117     return JSStringCreateWithCharacters(0, 0);
    118 }
    119 
    120 JSStringRef AccessibilityUIElement::attributesOfDocumentLinks()
    121 {
    122     return JSStringCreateWithCharacters(0, 0);
    123 }
    124 
    125 AccessibilityUIElement AccessibilityUIElement::titleUIElement()
    126 {
    127     return 0;
    128 }
    129 
    130 AccessibilityUIElement AccessibilityUIElement::parentElement()
    131 {
    132     COMPtr<IDispatch> parent;
    133     m_element->get_accParent(&parent);
    134 
    135     COMPtr<IAccessible> parentAccessible(Query, parent);
    136     return parentAccessible;
    137 }
    138 
    139 JSStringRef AccessibilityUIElement::attributesOfChildren()
    140 {
    141     return JSStringCreateWithCharacters(0, 0);
    142 }
    143 
    144 JSStringRef AccessibilityUIElement::parameterizedAttributeNames()
    145 {
    146     return JSStringCreateWithCharacters(0, 0);
    147 }
    148 
    149 static VARIANT& self()
    150 {
    151     static VARIANT vSelf;
    152     static bool haveInitialized;
    153 
    154     if (!haveInitialized) {
    155         ::VariantInit(&vSelf);
    156         V_VT(&vSelf) = VT_I4;
    157         V_I4(&vSelf) = CHILDID_SELF;
    158     }
    159     return vSelf;
    160 }
    161 
    162 JSStringRef AccessibilityUIElement::role()
    163 {
    164     VARIANT vRole;
    165     if (FAILED(m_element->get_accRole(self(), &vRole)))
    166         return JSStringCreateWithCharacters(0, 0);
    167 
    168     ASSERT(V_VT(&vRole) == VT_I4 || V_VT(&vRole) == VT_BSTR);
    169 
    170     wstring result;
    171     if (V_VT(&vRole) == VT_I4) {
    172         unsigned roleTextLength = ::GetRoleText(V_I4(&vRole), 0, 0) + 1;
    173 
    174         Vector<TCHAR> roleText(roleTextLength);
    175 
    176         ::GetRoleText(V_I4(&vRole), roleText.data(), roleTextLength);
    177 
    178         result = roleText.data();
    179     } else if (V_VT(&vRole) == VT_BSTR)
    180         result = wstring(V_BSTR(&vRole), ::SysStringLen(V_BSTR(&vRole)));
    181 
    182     ::VariantClear(&vRole);
    183 
    184     return JSStringCreateWithCharacters(result.data(), result.length());
    185 }
    186 
    187 JSStringRef AccessibilityUIElement::subrole()
    188 {
    189     return 0;
    190 }
    191 
    192 JSStringRef AccessibilityUIElement::roleDescription()
    193 {
    194     return 0;
    195 }
    196 
    197 JSStringRef AccessibilityUIElement::title()
    198 {
    199     BSTR titleBSTR;
    200     if (FAILED(m_element->get_accName(self(), &titleBSTR)) || !titleBSTR)
    201         return JSStringCreateWithCharacters(0, 0);
    202     wstring title(titleBSTR, SysStringLen(titleBSTR));
    203     ::SysFreeString(titleBSTR);
    204     return JSStringCreateWithCharacters(title.data(), title.length());
    205 }
    206 
    207 JSStringRef AccessibilityUIElement::description()
    208 {
    209     BSTR descriptionBSTR;
    210     if (FAILED(m_element->get_accDescription(self(), &descriptionBSTR)) || !descriptionBSTR)
    211         return JSStringCreateWithCharacters(0, 0);
    212     wstring description(descriptionBSTR, SysStringLen(descriptionBSTR));
    213     ::SysFreeString(descriptionBSTR);
    214     return JSStringCreateWithCharacters(description.data(), description.length());
    215 }
    216 
    217 JSStringRef AccessibilityUIElement::stringValue()
    218 {
    219     return JSStringCreateWithCharacters(0, 0);
    220 }
    221 
    222 JSStringRef AccessibilityUIElement::language()
    223 {
    224     return JSStringCreateWithCharacters(0, 0);
    225 }
    226 
    227 double AccessibilityUIElement::x()
    228 {
    229     long x, y, width, height;
    230     if (FAILED(m_element->accLocation(&x, &y, &width, &height, self())))
    231         return 0;
    232     return x;
    233 }
    234 
    235 double AccessibilityUIElement::y()
    236 {
    237     long x, y, width, height;
    238     if (FAILED(m_element->accLocation(&x, &y, &width, &height, self())))
    239         return 0;
    240     return y;
    241 }
    242 
    243 double AccessibilityUIElement::width()
    244 {
    245     long x, y, width, height;
    246     if (FAILED(m_element->accLocation(&x, &y, &width, &height, self())))
    247         return 0;
    248     return width;
    249 }
    250 
    251 double AccessibilityUIElement::height()
    252 {
    253     long x, y, width, height;
    254     if (FAILED(m_element->accLocation(&x, &y, &width, &height, self())))
    255         return 0;
    256     return height;
    257 }
    258 
    259 double AccessibilityUIElement::clickPointX()
    260 {
    261     return 0;
    262 }
    263 
    264 double AccessibilityUIElement::clickPointY()
    265 {
    266     return 0;
    267 }
    268 
    269 JSStringRef AccessibilityUIElement::valueDescription()
    270 {
    271     return 0;
    272 }
    273 
    274 static DWORD accessibilityState(COMPtr<IAccessible> element)
    275 {
    276     VARIANT state;
    277     element->get_accState(self(), &state);
    278 
    279     ASSERT(V_VT(&state) == VT_I4);
    280 
    281     DWORD result = state.lVal;
    282     VariantClear(&state);
    283 
    284     return result;
    285 }
    286 
    287 bool AccessibilityUIElement::isSelected() const
    288 {
    289     DWORD state = accessibilityState(m_element);
    290     return (state & STATE_SYSTEM_SELECTED) == STATE_SYSTEM_SELECTED;
    291 }
    292 
    293 int AccessibilityUIElement::hierarchicalLevel() const
    294 {
    295     return 0;
    296 }
    297 
    298 bool AccessibilityUIElement::ariaIsGrabbed() const
    299 {
    300     return false;
    301 }
    302 
    303 JSStringRef AccessibilityUIElement::ariaDropEffects() const
    304 {
    305     return 0;
    306 }
    307 
    308 bool AccessibilityUIElement::isExpanded() const
    309 {
    310     return false;
    311 }
    312 
    313 bool AccessibilityUIElement::isChecked() const
    314 {
    315     VARIANT vState;
    316     if (FAILED(m_element->get_accState(self(), &vState)))
    317         return false;
    318 
    319     return vState.lVal & STATE_SYSTEM_CHECKED;
    320 }
    321 
    322 JSStringRef AccessibilityUIElement::orientation() const
    323 {
    324     return 0;
    325 }
    326 
    327 double AccessibilityUIElement::intValue() const
    328 {
    329     BSTR valueBSTR;
    330     if (FAILED(m_element->get_accValue(self(), &valueBSTR)) || !valueBSTR)
    331         return 0;
    332     wstring value(valueBSTR, SysStringLen(valueBSTR));
    333     ::SysFreeString(valueBSTR);
    334     TCHAR* ignored;
    335     return _tcstod(value.data(), &ignored);
    336 }
    337 
    338 double AccessibilityUIElement::minValue()
    339 {
    340     return 0;
    341 }
    342 
    343 double AccessibilityUIElement::maxValue()
    344 {
    345     return 0;
    346 }
    347 
    348 bool AccessibilityUIElement::isActionSupported(JSStringRef action)
    349 {
    350     return false;
    351 }
    352 
    353 bool AccessibilityUIElement::isEnabled()
    354 {
    355     DWORD state = accessibilityState(m_element);
    356     return (state & STATE_SYSTEM_UNAVAILABLE) != STATE_SYSTEM_UNAVAILABLE;
    357 }
    358 
    359 bool AccessibilityUIElement::isRequired() const
    360 {
    361     return false;
    362 }
    363 
    364 
    365 int AccessibilityUIElement::insertionPointLineNumber()
    366 {
    367     return 0;
    368 }
    369 
    370 JSStringRef AccessibilityUIElement::attributesOfColumnHeaders()
    371 {
    372     return JSStringCreateWithCharacters(0, 0);
    373 }
    374 
    375 JSStringRef AccessibilityUIElement::attributesOfRowHeaders()
    376 {
    377     return JSStringCreateWithCharacters(0, 0);
    378 }
    379 
    380 JSStringRef AccessibilityUIElement::attributesOfColumns()
    381 {
    382     return JSStringCreateWithCharacters(0, 0);
    383 }
    384 
    385 JSStringRef AccessibilityUIElement::attributesOfRows()
    386 {
    387     return JSStringCreateWithCharacters(0, 0);
    388 }
    389 
    390 JSStringRef AccessibilityUIElement::attributesOfVisibleCells()
    391 {
    392     return JSStringCreateWithCharacters(0, 0);
    393 }
    394 
    395 JSStringRef AccessibilityUIElement::attributesOfHeader()
    396 {
    397     return JSStringCreateWithCharacters(0, 0);
    398 }
    399 
    400 int AccessibilityUIElement::indexInTable()
    401 {
    402     return 0;
    403 }
    404 
    405 JSStringRef AccessibilityUIElement::rowIndexRange()
    406 {
    407     return JSStringCreateWithCharacters(0, 0);
    408 }
    409 
    410 JSStringRef AccessibilityUIElement::columnIndexRange()
    411 {
    412     return JSStringCreateWithCharacters(0, 0);
    413 }
    414 
    415 int AccessibilityUIElement::lineForIndex(int)
    416 {
    417     return 0;
    418 }
    419 
    420 JSStringRef AccessibilityUIElement::boundsForRange(unsigned location, unsigned length)
    421 {
    422     return JSStringCreateWithCharacters(0, 0);
    423 }
    424 
    425 JSStringRef AccessibilityUIElement::stringForRange(unsigned, unsigned)
    426 {
    427     return JSStringCreateWithCharacters(0, 0);
    428 }
    429 
    430 AccessibilityUIElement AccessibilityUIElement::cellForColumnAndRow(unsigned column, unsigned row)
    431 {
    432     return 0;
    433 }
    434 
    435 JSStringRef AccessibilityUIElement::selectedTextRange()
    436 {
    437     return JSStringCreateWithCharacters(0, 0);
    438 }
    439 
    440 void AccessibilityUIElement::setSelectedTextRange(unsigned location, unsigned length)
    441 {
    442 }
    443 
    444 JSStringRef AccessibilityUIElement::stringAttributeValue(JSStringRef attribute)
    445 {
    446     // FIXME: implement
    447     return JSStringCreateWithCharacters(0, 0);
    448 }
    449 
    450 bool AccessibilityUIElement::boolAttributeValue(JSStringRef attribute)
    451 {
    452     // FIXME: implement
    453     return false;
    454 }
    455 
    456 bool AccessibilityUIElement::isAttributeSettable(JSStringRef attribute)
    457 {
    458     return false;
    459 }
    460 
    461 bool AccessibilityUIElement::isAttributeSupported(JSStringRef attribute)
    462 {
    463     return false;
    464 }
    465 
    466 void AccessibilityUIElement::increment()
    467 {
    468 }
    469 
    470 void AccessibilityUIElement::decrement()
    471 {
    472 }
    473 
    474 void AccessibilityUIElement::showMenu()
    475 {
    476     ASSERT(hasPopup());
    477     m_element->accDoDefaultAction(self());
    478 }
    479 
    480 AccessibilityUIElement AccessibilityUIElement::disclosedRowAtIndex(unsigned index)
    481 {
    482     return 0;
    483 }
    484 
    485 AccessibilityUIElement AccessibilityUIElement::ariaOwnsElementAtIndex(unsigned index)
    486 {
    487     return 0;
    488 }
    489 
    490 AccessibilityUIElement AccessibilityUIElement::ariaFlowToElementAtIndex(unsigned index)
    491 {
    492     return 0;
    493 }
    494 
    495 AccessibilityUIElement AccessibilityUIElement::selectedRowAtIndex(unsigned index)
    496 {
    497     return 0;
    498 }
    499 
    500 AccessibilityUIElement AccessibilityUIElement::disclosedByRow()
    501 {
    502     return 0;
    503 }
    504 
    505 JSStringRef AccessibilityUIElement::accessibilityValue() const
    506 {
    507     BSTR valueBSTR;
    508     if (FAILED(m_element->get_accValue(self(), &valueBSTR)) || !valueBSTR)
    509         return JSStringCreateWithCharacters(0, 0);
    510 
    511     wstring value(valueBSTR, SysStringLen(valueBSTR));
    512     ::SysFreeString(valueBSTR);
    513 
    514     return JSStringCreateWithCharacters(value.data(), value.length());
    515 }
    516 
    517 
    518 JSStringRef AccessibilityUIElement::documentEncoding()
    519 {
    520     return JSStringCreateWithCharacters(0, 0);
    521 }
    522 
    523 JSStringRef AccessibilityUIElement::documentURI()
    524 {
    525     return JSStringCreateWithCharacters(0, 0);
    526 }
    527 
    528 JSStringRef AccessibilityUIElement::url()
    529 {
    530     // FIXME: implement
    531     return JSStringCreateWithCharacters(0, 0);
    532 }
    533 
    534 bool AccessibilityUIElement::addNotificationListener(JSObjectRef functionCallback)
    535 {
    536     if (!functionCallback)
    537         return false;
    538 
    539     sharedFrameLoadDelegate->accessibilityController()->addNotificationListener(m_element, functionCallback);
    540     return true;
    541 }
    542 
    543 bool AccessibilityUIElement::isSelectable() const
    544 {
    545     DWORD state = accessibilityState(m_element);
    546     return (state & STATE_SYSTEM_SELECTABLE) == STATE_SYSTEM_SELECTABLE;
    547 }
    548 
    549 bool AccessibilityUIElement::isMultiSelectable() const
    550 {
    551     DWORD multiSelectable = STATE_SYSTEM_EXTSELECTABLE | STATE_SYSTEM_MULTISELECTABLE;
    552     DWORD state = accessibilityState(m_element);
    553     return (state & multiSelectable) == multiSelectable;
    554 }
    555 
    556 bool AccessibilityUIElement::isVisible() const
    557 {
    558     DWORD state = accessibilityState(m_element);
    559     return (state & STATE_SYSTEM_INVISIBLE) != STATE_SYSTEM_INVISIBLE;
    560 }
    561 
    562 bool AccessibilityUIElement::isOffScreen() const
    563 {
    564     DWORD state = accessibilityState(m_element);
    565     return (state & STATE_SYSTEM_OFFSCREEN) == STATE_SYSTEM_OFFSCREEN;
    566 }
    567 
    568 bool AccessibilityUIElement::isCollapsed() const
    569 {
    570     DWORD state = accessibilityState(m_element);
    571     return (state & STATE_SYSTEM_COLLAPSED) == STATE_SYSTEM_COLLAPSED;
    572 }
    573 
    574 bool AccessibilityUIElement::hasPopup() const
    575 {
    576     DWORD state = accessibilityState(m_element);
    577     return (state & STATE_SYSTEM_HASPOPUP) == STATE_SYSTEM_HASPOPUP;
    578 }
    579 
    580 void AccessibilityUIElement::takeFocus()
    581 {
    582     m_element->accSelect(SELFLAG_TAKEFOCUS, self());
    583 }
    584 
    585 void AccessibilityUIElement::takeSelection()
    586 {
    587     m_element->accSelect(SELFLAG_TAKESELECTION, self());
    588 }
    589 
    590 void AccessibilityUIElement::addSelection()
    591 {
    592     m_element->accSelect(SELFLAG_ADDSELECTION, self());
    593 }
    594 
    595 void AccessibilityUIElement::removeSelection()
    596 {
    597     m_element->accSelect(SELFLAG_REMOVESELECTION, self());
    598 }
    599