1/* 2 * Copyright (C) 2008, 2009, 2010 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 "WebKitDLL.h" 28#include "AccessibleBase.h" 29 30#include "AccessibleImage.h" 31#include "WebView.h" 32#include <WebCore/AccessibilityListBox.h> 33#include <WebCore/AccessibilityMenuListPopup.h> 34#include <WebCore/AccessibilityObject.h> 35#include <WebCore/AXObjectCache.h> 36#include <WebCore/BString.h> 37#include <WebCore/Element.h> 38#include <WebCore/EventHandler.h> 39#include <WebCore/FrameView.h> 40#include <WebCore/HostWindow.h> 41#include <WebCore/HTMLNames.h> 42#include <WebCore/HTMLFrameElementBase.h> 43#include <WebCore/HTMLInputElement.h> 44#include <WebCore/IntRect.h> 45#include <WebCore/PlatformKeyboardEvent.h> 46#include <WebCore/RenderFrame.h> 47#include <WebCore/RenderObject.h> 48#include <WebCore/RenderView.h> 49#include <oleacc.h> 50#include <wtf/RefPtr.h> 51 52using namespace WebCore; 53 54AccessibleBase::AccessibleBase(AccessibilityObject* obj) 55 : AccessibilityObjectWrapper(obj) 56 , m_refCount(0) 57{ 58 ASSERT_ARG(obj, obj); 59 m_object->setWrapper(this); 60 ++gClassCount; 61 gClassNameCount.add("AccessibleBase"); 62} 63 64AccessibleBase::~AccessibleBase() 65{ 66 --gClassCount; 67 gClassNameCount.remove("AccessibleBase"); 68} 69 70AccessibleBase* AccessibleBase::createInstance(AccessibilityObject* obj) 71{ 72 ASSERT_ARG(obj, obj); 73 74 if (obj->isImage()) 75 return new AccessibleImage(obj); 76 77 return new AccessibleBase(obj); 78} 79 80HRESULT AccessibleBase::QueryService(REFGUID guidService, REFIID riid, void **ppvObject) 81{ 82 if (!IsEqualGUID(guidService, SID_AccessibleComparable)) { 83 *ppvObject = 0; 84 return E_INVALIDARG; 85 } 86 return QueryInterface(riid, ppvObject); 87} 88 89// IUnknown 90HRESULT STDMETHODCALLTYPE AccessibleBase::QueryInterface(REFIID riid, void** ppvObject) 91{ 92 if (IsEqualGUID(riid, __uuidof(IAccessible))) 93 *ppvObject = static_cast<IAccessible*>(this); 94 else if (IsEqualGUID(riid, __uuidof(IDispatch))) 95 *ppvObject = static_cast<IAccessible*>(this); 96 else if (IsEqualGUID(riid, __uuidof(IUnknown))) 97 *ppvObject = static_cast<IAccessible*>(this); 98 else if (IsEqualGUID(riid, __uuidof(IAccessibleComparable))) 99 *ppvObject = static_cast<IAccessibleComparable*>(this); 100 else if (IsEqualGUID(riid, __uuidof(IServiceProvider))) 101 *ppvObject = static_cast<IServiceProvider*>(this); 102 else if (IsEqualGUID(riid, __uuidof(AccessibleBase))) 103 *ppvObject = static_cast<AccessibleBase*>(this); 104 else { 105 *ppvObject = 0; 106 return E_NOINTERFACE; 107 } 108 AddRef(); 109 return S_OK; 110} 111 112ULONG STDMETHODCALLTYPE AccessibleBase::Release(void) 113{ 114 ASSERT(m_refCount > 0); 115 if (--m_refCount) 116 return m_refCount; 117 delete this; 118 return 0; 119} 120 121// IAccessible 122HRESULT STDMETHODCALLTYPE AccessibleBase::get_accParent(IDispatch** parent) 123{ 124 *parent = 0; 125 126 if (!m_object) 127 return E_FAIL; 128 129 AccessibilityObject* parentObject = m_object->parentObjectUnignored(); 130 if (parentObject) { 131 *parent = wrapper(parentObject); 132 (*parent)->AddRef(); 133 return S_OK; 134 } 135 136 if (!m_object->topDocumentFrameView()) 137 return E_FAIL; 138 139 return WebView::AccessibleObjectFromWindow(m_object->topDocumentFrameView()->hostWindow()->platformPageClient(), 140 OBJID_WINDOW, __uuidof(IAccessible), reinterpret_cast<void**>(parent)); 141} 142 143HRESULT STDMETHODCALLTYPE AccessibleBase::get_accChildCount(long* count) 144{ 145 if (!m_object) 146 return E_FAIL; 147 if (!count) 148 return E_POINTER; 149 *count = static_cast<long>(m_object->children().size()); 150 return S_OK; 151} 152 153HRESULT STDMETHODCALLTYPE AccessibleBase::get_accChild(VARIANT vChild, IDispatch** ppChild) 154{ 155 if (!ppChild) 156 return E_POINTER; 157 158 *ppChild = 0; 159 160 AccessibilityObject* childObj; 161 162 HRESULT hr = getAccessibilityObjectForChild(vChild, childObj); 163 if (FAILED(hr)) 164 return hr; 165 166 *ppChild = static_cast<IDispatch*>(wrapper(childObj)); 167 (*ppChild)->AddRef(); 168 return S_OK; 169} 170 171HRESULT STDMETHODCALLTYPE AccessibleBase::get_accName(VARIANT vChild, BSTR* name) 172{ 173 if (!name) 174 return E_POINTER; 175 176 *name = 0; 177 178 AccessibilityObject* childObj; 179 HRESULT hr = getAccessibilityObjectForChild(vChild, childObj); 180 181 if (FAILED(hr)) 182 return hr; 183 184 if (*name = BString(wrapper(childObj)->name()).release()) 185 return S_OK; 186 return S_FALSE; 187} 188 189HRESULT STDMETHODCALLTYPE AccessibleBase::get_accValue(VARIANT vChild, BSTR* value) 190{ 191 if (!value) 192 return E_POINTER; 193 194 *value = 0; 195 196 AccessibilityObject* childObj; 197 HRESULT hr = getAccessibilityObjectForChild(vChild, childObj); 198 199 if (FAILED(hr)) 200 return hr; 201 202 if (*value = BString(wrapper(childObj)->value()).release()) 203 return S_OK; 204 return S_FALSE; 205} 206 207HRESULT STDMETHODCALLTYPE AccessibleBase::get_accDescription(VARIANT vChild, BSTR* description) 208{ 209 if (!description) 210 return E_POINTER; 211 212 *description = 0; 213 214 AccessibilityObject* childObj; 215 HRESULT hr = getAccessibilityObjectForChild(vChild, childObj); 216 217 if (FAILED(hr)) 218 return hr; 219 220 if (*description = BString(childObj->descriptionForMSAA()).release()) 221 return S_OK; 222 223 return S_FALSE; 224} 225 226HRESULT STDMETHODCALLTYPE AccessibleBase::get_accRole(VARIANT vChild, VARIANT* pvRole) 227{ 228 if (!pvRole) 229 return E_POINTER; 230 231 ::VariantInit(pvRole); 232 233 AccessibilityObject* childObj; 234 HRESULT hr = getAccessibilityObjectForChild(vChild, childObj); 235 236 if (FAILED(hr)) 237 return hr; 238 239 String roleString = childObj->stringRoleForMSAA(); 240 if (!roleString.isEmpty()) { 241 V_VT(pvRole) = VT_BSTR; 242 V_BSTR(pvRole) = BString(roleString).release(); 243 return S_OK; 244 } 245 246 pvRole->vt = VT_I4; 247 pvRole->lVal = wrapper(childObj)->role(); 248 return S_OK; 249} 250 251HRESULT STDMETHODCALLTYPE AccessibleBase::get_accState(VARIANT vChild, VARIANT* pvState) 252{ 253 if (!pvState) 254 return E_POINTER; 255 256 ::VariantInit(pvState); 257 258 AccessibilityObject* childObj; 259 HRESULT hr = getAccessibilityObjectForChild(vChild, childObj); 260 261 if (FAILED(hr)) 262 return hr; 263 264 pvState->vt = VT_I4; 265 pvState->lVal = 0; 266 267 if (childObj->isLinked()) 268 pvState->lVal |= STATE_SYSTEM_LINKED; 269 270 if (childObj->isHovered()) 271 pvState->lVal |= STATE_SYSTEM_HOTTRACKED; 272 273 if (!childObj->isEnabled()) 274 pvState->lVal |= STATE_SYSTEM_UNAVAILABLE; 275 276 if (childObj->isReadOnly()) 277 pvState->lVal |= STATE_SYSTEM_READONLY; 278 279 if (childObj->isOffScreen()) 280 pvState->lVal |= STATE_SYSTEM_OFFSCREEN; 281 282 if (childObj->isPasswordField()) 283 pvState->lVal |= STATE_SYSTEM_PROTECTED; 284 285 if (childObj->isIndeterminate()) 286 pvState->lVal |= STATE_SYSTEM_INDETERMINATE; 287 288 if (childObj->isChecked()) 289 pvState->lVal |= STATE_SYSTEM_CHECKED; 290 291 if (childObj->isPressed()) 292 pvState->lVal |= STATE_SYSTEM_PRESSED; 293 294 if (childObj->isFocused()) 295 pvState->lVal |= STATE_SYSTEM_FOCUSED; 296 297 if (childObj->isVisited()) 298 pvState->lVal |= STATE_SYSTEM_TRAVERSED; 299 300 if (childObj->canSetFocusAttribute()) 301 pvState->lVal |= STATE_SYSTEM_FOCUSABLE; 302 303 if (childObj->isSelected()) 304 pvState->lVal |= STATE_SYSTEM_SELECTED; 305 306 if (childObj->canSetSelectedAttribute()) 307 pvState->lVal |= STATE_SYSTEM_SELECTABLE; 308 309 if (childObj->isMultiSelectable()) 310 pvState->lVal |= STATE_SYSTEM_EXTSELECTABLE | STATE_SYSTEM_MULTISELECTABLE; 311 312 if (!childObj->isVisible()) 313 pvState->lVal |= STATE_SYSTEM_INVISIBLE; 314 315 if (childObj->isCollapsed()) 316 pvState->lVal |= STATE_SYSTEM_COLLAPSED; 317 318 if (childObj->roleValue() == PopUpButtonRole) { 319 pvState->lVal |= STATE_SYSTEM_HASPOPUP; 320 321 if (!childObj->isCollapsed()) 322 pvState->lVal |= STATE_SYSTEM_EXPANDED; 323 } 324 325 return S_OK; 326} 327 328HRESULT STDMETHODCALLTYPE AccessibleBase::get_accHelp(VARIANT vChild, BSTR* helpText) 329{ 330 if (!helpText) 331 return E_POINTER; 332 333 *helpText = 0; 334 335 AccessibilityObject* childObj; 336 HRESULT hr = getAccessibilityObjectForChild(vChild, childObj); 337 338 if (FAILED(hr)) 339 return hr; 340 341 if (*helpText = BString(childObj->helpText()).release()) 342 return S_OK; 343 return S_FALSE; 344} 345 346HRESULT STDMETHODCALLTYPE AccessibleBase::get_accKeyboardShortcut(VARIANT vChild, BSTR* shortcut) 347{ 348 if (!shortcut) 349 return E_POINTER; 350 351 *shortcut = 0; 352 353 AccessibilityObject* childObj; 354 HRESULT hr = getAccessibilityObjectForChild(vChild, childObj); 355 356 if (FAILED(hr)) 357 return hr; 358 359 String accessKey = childObj->accessKey(); 360 if (accessKey.isNull()) 361 return S_FALSE; 362 363 static String accessKeyModifiers; 364 if (accessKeyModifiers.isNull()) { 365 unsigned modifiers = EventHandler::accessKeyModifiers(); 366 // Follow the same order as Mozilla MSAA implementation: 367 // Ctrl+Alt+Shift+Meta+key. MSDN states that keyboard shortcut strings 368 // should not be localized and defines the separator as "+". 369 if (modifiers & PlatformKeyboardEvent::CtrlKey) 370 accessKeyModifiers += "Ctrl+"; 371 if (modifiers & PlatformKeyboardEvent::AltKey) 372 accessKeyModifiers += "Alt+"; 373 if (modifiers & PlatformKeyboardEvent::ShiftKey) 374 accessKeyModifiers += "Shift+"; 375 if (modifiers & PlatformKeyboardEvent::MetaKey) 376 accessKeyModifiers += "Win+"; 377 } 378 *shortcut = BString(accessKeyModifiers + accessKey).release(); 379 return S_OK; 380} 381 382HRESULT STDMETHODCALLTYPE AccessibleBase::accSelect(long selectionFlags, VARIANT vChild) 383{ 384 // According to MSDN, these combinations are invalid. 385 if (((selectionFlags & (SELFLAG_ADDSELECTION | SELFLAG_REMOVESELECTION)) == (SELFLAG_ADDSELECTION | SELFLAG_REMOVESELECTION)) 386 || ((selectionFlags & (SELFLAG_ADDSELECTION | SELFLAG_TAKESELECTION)) == (SELFLAG_ADDSELECTION | SELFLAG_TAKESELECTION)) 387 || ((selectionFlags & (SELFLAG_REMOVESELECTION | SELFLAG_TAKESELECTION)) == (SELFLAG_REMOVESELECTION | SELFLAG_TAKESELECTION)) 388 || ((selectionFlags & (SELFLAG_EXTENDSELECTION | SELFLAG_TAKESELECTION)) == (SELFLAG_EXTENDSELECTION | SELFLAG_TAKESELECTION))) 389 return E_INVALIDARG; 390 391 AccessibilityObject* childObject; 392 HRESULT hr = getAccessibilityObjectForChild(vChild, childObject); 393 394 if (FAILED(hr)) 395 return hr; 396 397 if (selectionFlags & SELFLAG_TAKEFOCUS) 398 childObject->setFocused(true); 399 400 AccessibilityObject* parentObject = childObject->parentObject(); 401 if (!parentObject) 402 return E_INVALIDARG; 403 404 if (selectionFlags & SELFLAG_TAKESELECTION) { 405 if (parentObject->isListBox()) { 406 Vector<RefPtr<AccessibilityObject> > selectedChildren(1); 407 selectedChildren[0] = childObject; 408 static_cast<AccessibilityListBox*>(parentObject)->setSelectedChildren(selectedChildren); 409 } else { // any element may be selectable by virtue of it having the aria-selected property 410 ASSERT(!parentObject->isMultiSelectable()); 411 childObject->setSelected(true); 412 } 413 } 414 415 // MSDN says that ADD, REMOVE, and EXTENDSELECTION with no other flags are invalid for 416 // single-select. 417 const long allSELFLAGs = SELFLAG_TAKEFOCUS | SELFLAG_TAKESELECTION | SELFLAG_EXTENDSELECTION | SELFLAG_ADDSELECTION | SELFLAG_REMOVESELECTION; 418 if (!parentObject->isMultiSelectable() 419 && (((selectionFlags & allSELFLAGs) == SELFLAG_ADDSELECTION) 420 || ((selectionFlags & allSELFLAGs) == SELFLAG_REMOVESELECTION) 421 || ((selectionFlags & allSELFLAGs) == SELFLAG_EXTENDSELECTION))) 422 return E_INVALIDARG; 423 424 if (selectionFlags & SELFLAG_ADDSELECTION) 425 childObject->setSelected(true); 426 427 if (selectionFlags & SELFLAG_REMOVESELECTION) 428 childObject->setSelected(false); 429 430 // FIXME: Should implement SELFLAG_EXTENDSELECTION. For now, we just return 431 // S_OK, matching Firefox. 432 433 return S_OK; 434} 435 436HRESULT STDMETHODCALLTYPE AccessibleBase::get_accSelection(VARIANT*) 437{ 438 return E_NOTIMPL; 439} 440 441HRESULT STDMETHODCALLTYPE AccessibleBase::get_accFocus(VARIANT* pvFocusedChild) 442{ 443 if (!pvFocusedChild) 444 return E_POINTER; 445 446 ::VariantInit(pvFocusedChild); 447 448 if (!m_object) 449 return E_FAIL; 450 451 AccessibilityObject* focusedObj = m_object->focusedUIElement(); 452 if (!focusedObj) 453 return S_FALSE; 454 455 if (focusedObj == m_object) { 456 V_VT(pvFocusedChild) = VT_I4; 457 V_I4(pvFocusedChild) = CHILDID_SELF; 458 return S_OK; 459 } 460 461 V_VT(pvFocusedChild) = VT_DISPATCH; 462 V_DISPATCH(pvFocusedChild) = wrapper(focusedObj); 463 V_DISPATCH(pvFocusedChild)->AddRef(); 464 return S_OK; 465} 466 467HRESULT STDMETHODCALLTYPE AccessibleBase::get_accDefaultAction(VARIANT vChild, BSTR* action) 468{ 469 if (!action) 470 return E_POINTER; 471 472 *action = 0; 473 474 AccessibilityObject* childObj; 475 HRESULT hr = getAccessibilityObjectForChild(vChild, childObj); 476 477 if (FAILED(hr)) 478 return hr; 479 480 if (*action = BString(childObj->actionVerb()).release()) 481 return S_OK; 482 return S_FALSE; 483} 484 485HRESULT STDMETHODCALLTYPE AccessibleBase::accLocation(long* left, long* top, long* width, long* height, VARIANT vChild) 486{ 487 if (!left || !top || !width || !height) 488 return E_POINTER; 489 490 *left = *top = *width = *height = 0; 491 492 AccessibilityObject* childObj; 493 HRESULT hr = getAccessibilityObjectForChild(vChild, childObj); 494 495 if (FAILED(hr)) 496 return hr; 497 498 if (!childObj->documentFrameView()) 499 return E_FAIL; 500 501 IntRect screenRect(childObj->documentFrameView()->contentsToScreen(childObj->elementRect())); 502 *left = screenRect.x(); 503 *top = screenRect.y(); 504 *width = screenRect.width(); 505 *height = screenRect.height(); 506 return S_OK; 507} 508 509HRESULT STDMETHODCALLTYPE AccessibleBase::accNavigate(long direction, VARIANT vFromChild, VARIANT* pvNavigatedTo) 510{ 511 if (!pvNavigatedTo) 512 return E_POINTER; 513 514 ::VariantInit(pvNavigatedTo); 515 516 AccessibilityObject* childObj = 0; 517 518 switch (direction) { 519 case NAVDIR_DOWN: 520 case NAVDIR_UP: 521 case NAVDIR_LEFT: 522 case NAVDIR_RIGHT: 523 // These directions are not implemented, matching Mozilla and IE. 524 return E_NOTIMPL; 525 case NAVDIR_LASTCHILD: 526 case NAVDIR_FIRSTCHILD: 527 // MSDN states that navigating to first/last child can only be from self. 528 if (vFromChild.lVal != CHILDID_SELF) 529 return E_INVALIDARG; 530 531 if (!m_object) 532 return E_FAIL; 533 534 if (direction == NAVDIR_FIRSTCHILD) 535 childObj = m_object->firstChild(); 536 else 537 childObj = m_object->lastChild(); 538 break; 539 case NAVDIR_NEXT: 540 case NAVDIR_PREVIOUS: { 541 // Navigating to next and previous is allowed from self or any of our children. 542 HRESULT hr = getAccessibilityObjectForChild(vFromChild, childObj); 543 if (FAILED(hr)) 544 return hr; 545 546 if (direction == NAVDIR_NEXT) 547 childObj = childObj->nextSibling(); 548 else 549 childObj = childObj->previousSibling(); 550 break; 551 } 552 default: 553 ASSERT_NOT_REACHED(); 554 return E_INVALIDARG; 555 } 556 557 if (!childObj) 558 return S_FALSE; 559 560 V_VT(pvNavigatedTo) = VT_DISPATCH; 561 V_DISPATCH(pvNavigatedTo) = wrapper(childObj); 562 V_DISPATCH(pvNavigatedTo)->AddRef(); 563 return S_OK; 564} 565 566HRESULT STDMETHODCALLTYPE AccessibleBase::accHitTest(long x, long y, VARIANT* pvChildAtPoint) 567{ 568 if (!pvChildAtPoint) 569 return E_POINTER; 570 571 ::VariantInit(pvChildAtPoint); 572 573 if (!m_object || !m_object->documentFrameView()) 574 return E_FAIL; 575 576 IntPoint point = m_object->documentFrameView()->screenToContents(IntPoint(x, y)); 577 AccessibilityObject* childObj = m_object->accessibilityHitTest(point); 578 579 if (!childObj) { 580 // If we did not hit any child objects, test whether the point hit us, and 581 // report that. 582 if (!m_object->boundingBoxRect().contains(point)) 583 return S_FALSE; 584 childObj = m_object; 585 } 586 587 if (childObj == m_object) { 588 V_VT(pvChildAtPoint) = VT_I4; 589 V_I4(pvChildAtPoint) = CHILDID_SELF; 590 } else { 591 V_VT(pvChildAtPoint) = VT_DISPATCH; 592 V_DISPATCH(pvChildAtPoint) = static_cast<IDispatch*>(wrapper(childObj)); 593 V_DISPATCH(pvChildAtPoint)->AddRef(); 594 } 595 return S_OK; 596} 597 598HRESULT STDMETHODCALLTYPE AccessibleBase::accDoDefaultAction(VARIANT vChild) 599{ 600 AccessibilityObject* childObj; 601 HRESULT hr = getAccessibilityObjectForChild(vChild, childObj); 602 603 if (FAILED(hr)) 604 return hr; 605 606 if (!childObj->performDefaultAction()) 607 return S_FALSE; 608 609 return S_OK; 610} 611 612// AccessibleBase 613String AccessibleBase::name() const 614{ 615 return m_object->nameForMSAA(); 616} 617 618String AccessibleBase::value() const 619{ 620 return m_object->stringValueForMSAA(); 621} 622 623static long MSAARole(AccessibilityRole role) 624{ 625 switch (role) { 626 case WebCore::ButtonRole: 627 return ROLE_SYSTEM_PUSHBUTTON; 628 case WebCore::RadioButtonRole: 629 return ROLE_SYSTEM_RADIOBUTTON; 630 case WebCore::CheckBoxRole: 631 return ROLE_SYSTEM_CHECKBUTTON; 632 case WebCore::SliderRole: 633 return ROLE_SYSTEM_SLIDER; 634 case WebCore::TabGroupRole: 635 return ROLE_SYSTEM_PAGETABLIST; 636 case WebCore::TextFieldRole: 637 case WebCore::TextAreaRole: 638 case WebCore::EditableTextRole: 639 return ROLE_SYSTEM_TEXT; 640 case WebCore::ListMarkerRole: 641 case WebCore::StaticTextRole: 642 return ROLE_SYSTEM_STATICTEXT; 643 case WebCore::OutlineRole: 644 return ROLE_SYSTEM_OUTLINE; 645 case WebCore::ColumnRole: 646 return ROLE_SYSTEM_COLUMN; 647 case WebCore::RowRole: 648 return ROLE_SYSTEM_ROW; 649 case WebCore::GroupRole: 650 return ROLE_SYSTEM_GROUPING; 651 case WebCore::ListRole: 652 case WebCore::ListBoxRole: 653 case WebCore::MenuListPopupRole: 654 return ROLE_SYSTEM_LIST; 655 case WebCore::TableRole: 656 return ROLE_SYSTEM_TABLE; 657 case WebCore::LinkRole: 658 case WebCore::WebCoreLinkRole: 659 return ROLE_SYSTEM_LINK; 660 case WebCore::ImageMapRole: 661 case WebCore::ImageRole: 662 return ROLE_SYSTEM_GRAPHIC; 663 case WebCore::MenuListOptionRole: 664 case WebCore::ListItemRole: 665 case WebCore::ListBoxOptionRole: 666 return ROLE_SYSTEM_LISTITEM; 667 case WebCore::PopUpButtonRole: 668 return ROLE_SYSTEM_COMBOBOX; 669 default: 670 // This is the default role for MSAA. 671 return ROLE_SYSTEM_CLIENT; 672 } 673} 674 675long AccessibleBase::role() const 676{ 677 return MSAARole(m_object->roleValueForMSAA()); 678} 679 680HRESULT AccessibleBase::getAccessibilityObjectForChild(VARIANT vChild, AccessibilityObject*& childObj) const 681{ 682 childObj = 0; 683 684 if (!m_object) 685 return E_FAIL; 686 687 if (vChild.vt != VT_I4) 688 return E_INVALIDARG; 689 690 if (vChild.lVal == CHILDID_SELF) 691 childObj = m_object; 692 else if (vChild.lVal < 0) { 693 // When broadcasting MSAA events, we negate the AXID and pass it as the 694 // child ID. 695 Document* document = m_object->document(); 696 if (!document) 697 return E_FAIL; 698 699 childObj = document->axObjectCache()->objectFromAXID(-vChild.lVal); 700 } else { 701 size_t childIndex = static_cast<size_t>(vChild.lVal - 1); 702 703 if (childIndex >= m_object->children().size()) 704 return E_FAIL; 705 childObj = m_object->children().at(childIndex).get(); 706 } 707 708 if (!childObj) 709 return E_FAIL; 710 711 return S_OK; 712} 713 714AccessibleBase* AccessibleBase::wrapper(AccessibilityObject* obj) 715{ 716 AccessibleBase* result = static_cast<AccessibleBase*>(obj->wrapper()); 717 if (!result) 718 result = createInstance(obj); 719 return result; 720} 721 722HRESULT AccessibleBase::isSameObject(IAccessibleComparable* other, BOOL* result) 723{ 724 COMPtr<AccessibleBase> otherAccessibleBase(Query, other); 725 *result = (otherAccessibleBase == this || otherAccessibleBase->m_object == m_object); 726 return S_OK; 727} 728