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