1 /* 2 * Copyright (C) 2009 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 "config.h" 32 #include "public/web/WebAXObject.h" 33 34 #include "core/HTMLNames.h" 35 #include "core/accessibility/AXObject.h" 36 #include "core/accessibility/AXObjectCache.h" 37 #include "core/accessibility/AXTable.h" 38 #include "core/accessibility/AXTableCell.h" 39 #include "core/accessibility/AXTableColumn.h" 40 #include "core/accessibility/AXTableRow.h" 41 #include "core/css/CSSPrimitiveValueMappings.h" 42 #include "core/dom/Document.h" 43 #include "core/dom/Node.h" 44 #include "core/frame/FrameView.h" 45 #include "core/page/EventHandler.h" 46 #include "core/rendering/RenderView.h" 47 #include "core/rendering/style/RenderStyle.h" 48 #include "platform/PlatformKeyboardEvent.h" 49 #include "public/platform/WebPoint.h" 50 #include "public/platform/WebRect.h" 51 #include "public/platform/WebString.h" 52 #include "public/platform/WebURL.h" 53 #include "public/web/WebDocument.h" 54 #include "public/web/WebNode.h" 55 #include "wtf/text/StringBuilder.h" 56 57 namespace blink { 58 59 #if ENABLE(ASSERT) 60 // It's not safe to call some WebAXObject APIs if a layout is pending. 61 // Clients should call updateLayoutAndCheckValidity first. 62 static bool isLayoutClean(Document* document) 63 { 64 if (!document || !document->view()) 65 return false; 66 return document->lifecycle().state() >= DocumentLifecycle::LayoutClean 67 || (document->lifecycle().state() == DocumentLifecycle::StyleClean && !document->view()->needsLayout()); 68 } 69 #endif 70 71 void WebAXObject::reset() 72 { 73 m_private.reset(); 74 } 75 76 void WebAXObject::assign(const WebAXObject& other) 77 { 78 m_private = other.m_private; 79 } 80 81 bool WebAXObject::equals(const WebAXObject& n) const 82 { 83 return m_private.get() == n.m_private.get(); 84 } 85 86 bool WebAXObject::isDetached() const 87 { 88 if (m_private.isNull()) 89 return true; 90 91 return m_private->isDetached(); 92 } 93 94 int WebAXObject::axID() const 95 { 96 if (isDetached()) 97 return -1; 98 99 return m_private->axObjectID(); 100 } 101 102 bool WebAXObject::updateLayoutAndCheckValidity() 103 { 104 if (!isDetached()) { 105 Document* document = m_private->document(); 106 if (!document || !document->topDocument().view()) 107 return false; 108 document->topDocument().view()->updateLayoutAndStyleIfNeededRecursive(); 109 } 110 111 // Doing a layout can cause this object to be invalid, so check again. 112 return !isDetached(); 113 } 114 115 bool WebAXObject::updateBackingStoreAndCheckValidity() 116 { 117 return updateLayoutAndCheckValidity(); 118 } 119 120 WebString WebAXObject::accessibilityDescription() const 121 { 122 if (isDetached()) 123 return WebString(); 124 125 ASSERT(isLayoutClean(m_private->document())); 126 127 return m_private->accessibilityDescription(); 128 } 129 130 WebString WebAXObject::actionVerb() const 131 { 132 if (isDetached()) 133 return WebString(); 134 135 return m_private->actionVerb(); 136 } 137 138 bool WebAXObject::canDecrement() const 139 { 140 if (isDetached()) 141 return false; 142 143 return m_private->isSlider(); 144 } 145 146 bool WebAXObject::canIncrement() const 147 { 148 if (isDetached()) 149 return false; 150 151 return m_private->isSlider(); 152 } 153 154 bool WebAXObject::canPress() const 155 { 156 if (isDetached()) 157 return false; 158 159 return m_private->actionElement() || m_private->isButton() || m_private->isMenuRelated(); 160 } 161 162 bool WebAXObject::canSetFocusAttribute() const 163 { 164 if (isDetached()) 165 return false; 166 167 return m_private->canSetFocusAttribute(); 168 } 169 170 bool WebAXObject::canSetValueAttribute() const 171 { 172 if (isDetached()) 173 return false; 174 175 return m_private->canSetValueAttribute(); 176 } 177 178 unsigned WebAXObject::childCount() const 179 { 180 if (isDetached()) 181 return 0; 182 183 return m_private->children().size(); 184 } 185 186 WebAXObject WebAXObject::childAt(unsigned index) const 187 { 188 if (isDetached()) 189 return WebAXObject(); 190 191 if (m_private->children().size() <= index) 192 return WebAXObject(); 193 194 return WebAXObject(m_private->children()[index]); 195 } 196 197 WebAXObject WebAXObject::parentObject() const 198 { 199 if (isDetached()) 200 return WebAXObject(); 201 202 return WebAXObject(m_private->parentObject()); 203 } 204 205 bool WebAXObject::canSetSelectedAttribute() const 206 { 207 if (isDetached()) 208 return 0; 209 210 return m_private->canSetSelectedAttribute(); 211 } 212 213 bool WebAXObject::isAnchor() const 214 { 215 if (isDetached()) 216 return 0; 217 218 return m_private->isAnchor(); 219 } 220 221 bool WebAXObject::isAriaReadOnly() const 222 { 223 if (isDetached()) 224 return 0; 225 226 return equalIgnoringCase(m_private->getAttribute(HTMLNames::aria_readonlyAttr), "true"); 227 } 228 229 bool WebAXObject::isButtonStateMixed() const 230 { 231 if (isDetached()) 232 return 0; 233 234 return m_private->checkboxOrRadioValue() == ButtonStateMixed; 235 } 236 237 bool WebAXObject::isChecked() const 238 { 239 if (isDetached()) 240 return 0; 241 242 return m_private->isChecked(); 243 } 244 245 bool WebAXObject::isClickable() const 246 { 247 if (isDetached()) 248 return 0; 249 250 return m_private->isClickable(); 251 } 252 253 bool WebAXObject::isCollapsed() const 254 { 255 if (isDetached()) 256 return 0; 257 258 return m_private->isCollapsed(); 259 } 260 261 bool WebAXObject::isControl() const 262 { 263 if (isDetached()) 264 return 0; 265 266 return m_private->isControl(); 267 } 268 269 bool WebAXObject::isEnabled() const 270 { 271 if (isDetached()) 272 return 0; 273 274 return m_private->isEnabled(); 275 } 276 277 bool WebAXObject::isFocused() const 278 { 279 if (isDetached()) 280 return 0; 281 282 return m_private->isFocused(); 283 } 284 285 bool WebAXObject::isHovered() const 286 { 287 if (isDetached()) 288 return 0; 289 290 return m_private->isHovered(); 291 } 292 293 bool WebAXObject::isIndeterminate() const 294 { 295 if (isDetached()) 296 return 0; 297 298 return m_private->isIndeterminate(); 299 } 300 301 bool WebAXObject::isLinked() const 302 { 303 if (isDetached()) 304 return 0; 305 306 return m_private->isLinked(); 307 } 308 309 bool WebAXObject::isLoaded() const 310 { 311 if (isDetached()) 312 return 0; 313 314 return m_private->isLoaded(); 315 } 316 317 bool WebAXObject::isMultiSelectable() const 318 { 319 if (isDetached()) 320 return 0; 321 322 return m_private->isMultiSelectable(); 323 } 324 325 bool WebAXObject::isOffScreen() const 326 { 327 if (isDetached()) 328 return 0; 329 330 return m_private->isOffScreen(); 331 } 332 333 bool WebAXObject::isPasswordField() const 334 { 335 if (isDetached()) 336 return 0; 337 338 return m_private->isPasswordField(); 339 } 340 341 bool WebAXObject::isPressed() const 342 { 343 if (isDetached()) 344 return 0; 345 346 return m_private->isPressed(); 347 } 348 349 bool WebAXObject::isReadOnly() const 350 { 351 if (isDetached()) 352 return 0; 353 354 return m_private->isReadOnly(); 355 } 356 357 bool WebAXObject::isRequired() const 358 { 359 if (isDetached()) 360 return 0; 361 362 return m_private->isRequired(); 363 } 364 365 bool WebAXObject::isSelected() const 366 { 367 if (isDetached()) 368 return 0; 369 370 return m_private->isSelected(); 371 } 372 373 bool WebAXObject::isSelectedOptionActive() const 374 { 375 if (isDetached()) 376 return false; 377 378 return m_private->isSelectedOptionActive(); 379 } 380 381 bool WebAXObject::isVertical() const 382 { 383 if (isDetached()) 384 return 0; 385 386 return m_private->orientation() == AccessibilityOrientationVertical; 387 } 388 389 bool WebAXObject::isVisible() const 390 { 391 if (isDetached()) 392 return 0; 393 394 return m_private->isVisible(); 395 } 396 397 bool WebAXObject::isVisited() const 398 { 399 if (isDetached()) 400 return 0; 401 402 return m_private->isVisited(); 403 } 404 405 WebString WebAXObject::accessKey() const 406 { 407 if (isDetached()) 408 return WebString(); 409 410 return WebString(m_private->accessKey()); 411 } 412 413 WebAXObject WebAXObject::ariaActiveDescendant() const 414 { 415 if (isDetached()) 416 return WebAXObject(); 417 418 return WebAXObject(m_private->activeDescendant()); 419 } 420 421 bool WebAXObject::ariaControls(WebVector<WebAXObject>& controlsElements) const 422 { 423 if (isDetached()) 424 return false; 425 426 AXObject::AccessibilityChildrenVector controls; 427 m_private->ariaControlsElements(controls); 428 429 WebVector<WebAXObject> result(controls.size()); 430 for (size_t i = 0; i < controls.size(); i++) 431 result[i] = WebAXObject(controls[i]); 432 controlsElements.swap(result); 433 434 return true; 435 } 436 437 bool WebAXObject::ariaDescribedby(WebVector<WebAXObject>& describedbyElements) const 438 { 439 if (isDetached()) 440 return false; 441 442 AXObject::AccessibilityChildrenVector describedby; 443 m_private->ariaDescribedbyElements(describedby); 444 445 WebVector<WebAXObject> result(describedby.size()); 446 for (size_t i = 0; i < describedby.size(); i++) 447 result[i] = WebAXObject(describedby[i]); 448 describedbyElements.swap(result); 449 450 return true; 451 } 452 453 bool WebAXObject::ariaHasPopup() const 454 { 455 if (isDetached()) 456 return 0; 457 458 return m_private->ariaHasPopup(); 459 } 460 461 bool WebAXObject::ariaFlowTo(WebVector<WebAXObject>& flowToElements) const 462 { 463 if (isDetached()) 464 return false; 465 466 AXObject::AccessibilityChildrenVector flowTo; 467 m_private->ariaFlowToElements(flowTo); 468 469 WebVector<WebAXObject> result(flowTo.size()); 470 for (size_t i = 0; i < flowTo.size(); i++) 471 result[i] = WebAXObject(flowTo[i]); 472 flowToElements.swap(result); 473 474 return true; 475 } 476 477 bool WebAXObject::ariaLabelledby(WebVector<WebAXObject>& labelledbyElements) const 478 { 479 if (isDetached()) 480 return false; 481 482 AXObject::AccessibilityChildrenVector labelledby; 483 m_private->ariaLabelledbyElements(labelledby); 484 485 WebVector<WebAXObject> result(labelledby.size()); 486 for (size_t i = 0; i < labelledby.size(); i++) 487 result[i] = WebAXObject(labelledby[i]); 488 labelledbyElements.swap(result); 489 490 return true; 491 } 492 493 bool WebAXObject::ariaLiveRegionAtomic() const 494 { 495 if (isDetached()) 496 return 0; 497 498 return m_private->ariaLiveRegionAtomic(); 499 } 500 501 bool WebAXObject::ariaLiveRegionBusy() const 502 { 503 if (isDetached()) 504 return 0; 505 506 return m_private->ariaLiveRegionBusy(); 507 } 508 509 WebString WebAXObject::ariaLiveRegionRelevant() const 510 { 511 if (isDetached()) 512 return WebString(); 513 514 return m_private->ariaLiveRegionRelevant(); 515 } 516 517 WebString WebAXObject::ariaLiveRegionStatus() const 518 { 519 if (isDetached()) 520 return WebString(); 521 522 return m_private->ariaLiveRegionStatus(); 523 } 524 525 bool WebAXObject::ariaOwns(WebVector<WebAXObject>& ownsElements) const 526 { 527 if (isDetached()) 528 return false; 529 530 AXObject::AccessibilityChildrenVector owns; 531 m_private->ariaOwnsElements(owns); 532 533 WebVector<WebAXObject> result(owns.size()); 534 for (size_t i = 0; i < owns.size(); i++) 535 result[i] = WebAXObject(owns[i]); 536 ownsElements.swap(result); 537 538 return true; 539 } 540 541 WebRect WebAXObject::boundingBoxRect() const 542 { 543 if (isDetached()) 544 return WebRect(); 545 546 ASSERT(isLayoutClean(m_private->document())); 547 548 return pixelSnappedIntRect(m_private->elementRect()); 549 } 550 551 bool WebAXObject::canvasHasFallbackContent() const 552 { 553 if (isDetached()) 554 return false; 555 556 return m_private->canvasHasFallbackContent(); 557 } 558 559 WebPoint WebAXObject::clickPoint() const 560 { 561 if (isDetached()) 562 return WebPoint(); 563 564 return WebPoint(m_private->clickPoint()); 565 } 566 567 void WebAXObject::colorValue(int& r, int& g, int& b) const 568 { 569 if (isDetached()) 570 return; 571 572 m_private->colorValue(r, g, b); 573 } 574 575 double WebAXObject::estimatedLoadingProgress() const 576 { 577 if (isDetached()) 578 return 0.0; 579 580 return m_private->estimatedLoadingProgress(); 581 } 582 583 WebString WebAXObject::helpText() const 584 { 585 if (isDetached()) 586 return WebString(); 587 588 return m_private->helpText(); 589 } 590 591 int WebAXObject::headingLevel() const 592 { 593 if (isDetached()) 594 return 0; 595 596 return m_private->headingLevel(); 597 } 598 599 int WebAXObject::hierarchicalLevel() const 600 { 601 if (isDetached()) 602 return 0; 603 604 return m_private->hierarchicalLevel(); 605 } 606 607 WebAXObject WebAXObject::hitTest(const WebPoint& point) const 608 { 609 if (isDetached()) 610 return WebAXObject(); 611 612 IntPoint contentsPoint = m_private->documentFrameView()->windowToContents(point); 613 RefPtr<AXObject> hit = m_private->accessibilityHitTest(contentsPoint); 614 615 if (hit) 616 return WebAXObject(hit); 617 618 if (m_private->elementRect().contains(contentsPoint)) 619 return *this; 620 621 return WebAXObject(); 622 } 623 624 WebString WebAXObject::keyboardShortcut() const 625 { 626 if (isDetached()) 627 return WebString(); 628 629 String accessKey = m_private->accessKey(); 630 if (accessKey.isNull()) 631 return WebString(); 632 633 DEFINE_STATIC_LOCAL(String, modifierString, ()); 634 if (modifierString.isNull()) { 635 unsigned modifiers = EventHandler::accessKeyModifiers(); 636 // Follow the same order as Mozilla MSAA implementation: 637 // Ctrl+Alt+Shift+Meta+key. MSDN states that keyboard shortcut strings 638 // should not be localized and defines the separator as "+". 639 StringBuilder modifierStringBuilder; 640 if (modifiers & PlatformEvent::CtrlKey) 641 modifierStringBuilder.appendLiteral("Ctrl+"); 642 if (modifiers & PlatformEvent::AltKey) 643 modifierStringBuilder.appendLiteral("Alt+"); 644 if (modifiers & PlatformEvent::ShiftKey) 645 modifierStringBuilder.appendLiteral("Shift+"); 646 if (modifiers & PlatformEvent::MetaKey) 647 modifierStringBuilder.appendLiteral("Win+"); 648 modifierString = modifierStringBuilder.toString(); 649 } 650 651 return String(modifierString + accessKey); 652 } 653 654 bool WebAXObject::performDefaultAction() const 655 { 656 if (isDetached()) 657 return false; 658 659 return m_private->performDefaultAction(); 660 } 661 662 bool WebAXObject::increment() const 663 { 664 if (isDetached()) 665 return false; 666 667 if (canIncrement()) { 668 m_private->increment(); 669 return true; 670 } 671 return false; 672 } 673 674 bool WebAXObject::decrement() const 675 { 676 if (isDetached()) 677 return false; 678 679 if (canDecrement()) { 680 m_private->decrement(); 681 return true; 682 } 683 return false; 684 } 685 686 bool WebAXObject::press() const 687 { 688 if (isDetached()) 689 return false; 690 691 return m_private->press(); 692 } 693 694 WebAXRole WebAXObject::role() const 695 { 696 if (isDetached()) 697 return WebAXRoleUnknown; 698 699 return static_cast<WebAXRole>(m_private->roleValue()); 700 } 701 702 unsigned WebAXObject::selectionEnd() const 703 { 704 if (isDetached()) 705 return 0; 706 707 return m_private->selectedTextRange().start + m_private->selectedTextRange().length; 708 } 709 710 unsigned WebAXObject::selectionStart() const 711 { 712 if (isDetached()) 713 return 0; 714 715 return m_private->selectedTextRange().start; 716 } 717 718 unsigned WebAXObject::selectionEndLineNumber() const 719 { 720 if (isDetached()) 721 return 0; 722 723 VisiblePosition position = m_private->visiblePositionForIndex(selectionEnd()); 724 int lineNumber = m_private->lineForPosition(position); 725 if (lineNumber < 0) 726 return 0; 727 return lineNumber; 728 } 729 730 unsigned WebAXObject::selectionStartLineNumber() const 731 { 732 if (isDetached()) 733 return 0; 734 735 VisiblePosition position = m_private->visiblePositionForIndex(selectionStart()); 736 int lineNumber = m_private->lineForPosition(position); 737 if (lineNumber < 0) 738 return 0; 739 return lineNumber; 740 } 741 742 void WebAXObject::setFocused(bool on) const 743 { 744 if (!isDetached()) 745 m_private->setFocused(on); 746 } 747 748 void WebAXObject::setSelectedTextRange(int selectionStart, int selectionEnd) const 749 { 750 if (isDetached()) 751 return; 752 753 m_private->setSelectedTextRange(AXObject::PlainTextRange(selectionStart, selectionEnd - selectionStart)); 754 } 755 756 WebString WebAXObject::stringValue() const 757 { 758 if (isDetached()) 759 return WebString(); 760 761 return m_private->stringValue(); 762 } 763 764 WebString WebAXObject::title() const 765 { 766 if (isDetached()) 767 return WebString(); 768 769 ASSERT(isLayoutClean(m_private->document())); 770 771 return m_private->title(); 772 } 773 774 WebAXObject WebAXObject::titleUIElement() const 775 { 776 if (isDetached()) 777 return WebAXObject(); 778 779 if (!m_private->exposesTitleUIElement()) 780 return WebAXObject(); 781 782 return WebAXObject(m_private->titleUIElement()); 783 } 784 785 WebURL WebAXObject::url() const 786 { 787 if (isDetached()) 788 return WebURL(); 789 790 return m_private->url(); 791 } 792 793 bool WebAXObject::supportsRangeValue() const 794 { 795 if (isDetached()) 796 return false; 797 798 return m_private->supportsRangeValue(); 799 } 800 801 WebString WebAXObject::valueDescription() const 802 { 803 if (isDetached()) 804 return WebString(); 805 806 return m_private->valueDescription(); 807 } 808 809 float WebAXObject::valueForRange() const 810 { 811 if (isDetached()) 812 return 0.0; 813 814 return m_private->valueForRange(); 815 } 816 817 float WebAXObject::maxValueForRange() const 818 { 819 if (isDetached()) 820 return 0.0; 821 822 return m_private->maxValueForRange(); 823 } 824 825 float WebAXObject::minValueForRange() const 826 { 827 if (isDetached()) 828 return 0.0; 829 830 return m_private->minValueForRange(); 831 } 832 833 WebNode WebAXObject::node() const 834 { 835 if (isDetached()) 836 return WebNode(); 837 838 Node* node = m_private->node(); 839 if (!node) 840 return WebNode(); 841 842 return WebNode(node); 843 } 844 845 WebDocument WebAXObject::document() const 846 { 847 if (isDetached()) 848 return WebDocument(); 849 850 Document* document = m_private->document(); 851 if (!document) 852 return WebDocument(); 853 854 return WebDocument(document); 855 } 856 857 bool WebAXObject::hasComputedStyle() const 858 { 859 if (isDetached()) 860 return false; 861 862 Document* document = m_private->document(); 863 if (document) 864 document->updateRenderTreeIfNeeded(); 865 866 Node* node = m_private->node(); 867 if (!node) 868 return false; 869 870 return node->computedStyle(); 871 } 872 873 WebString WebAXObject::computedStyleDisplay() const 874 { 875 if (isDetached()) 876 return WebString(); 877 878 Document* document = m_private->document(); 879 if (document) 880 document->updateRenderTreeIfNeeded(); 881 882 Node* node = m_private->node(); 883 if (!node) 884 return WebString(); 885 886 RenderStyle* renderStyle = node->computedStyle(); 887 if (!renderStyle) 888 return WebString(); 889 890 return WebString(CSSPrimitiveValue::create(renderStyle->display())->getStringValue()); 891 } 892 893 bool WebAXObject::accessibilityIsIgnored() const 894 { 895 if (isDetached()) 896 return false; 897 898 return m_private->accessibilityIsIgnored(); 899 } 900 901 bool WebAXObject::lineBreaks(WebVector<int>& result) const 902 { 903 if (isDetached()) 904 return false; 905 906 Vector<int> lineBreaksVector; 907 m_private->lineBreaks(lineBreaksVector); 908 909 size_t vectorSize = lineBreaksVector.size(); 910 WebVector<int> lineBreaksWebVector(vectorSize); 911 for (size_t i = 0; i< vectorSize; i++) 912 lineBreaksWebVector[i] = lineBreaksVector[i]; 913 result.swap(lineBreaksWebVector); 914 915 return true; 916 } 917 918 unsigned WebAXObject::columnCount() const 919 { 920 if (isDetached()) 921 return false; 922 923 if (!m_private->isAXTable()) 924 return 0; 925 926 return toAXTable(m_private.get())->columnCount(); 927 } 928 929 unsigned WebAXObject::rowCount() const 930 { 931 if (isDetached()) 932 return false; 933 934 if (!m_private->isAXTable()) 935 return 0; 936 937 return toAXTable(m_private.get())->rowCount(); 938 } 939 940 WebAXObject WebAXObject::cellForColumnAndRow(unsigned column, unsigned row) const 941 { 942 if (isDetached()) 943 return WebAXObject(); 944 945 if (!m_private->isAXTable()) 946 return WebAXObject(); 947 948 AXTableCell* cell = toAXTable(m_private.get())->cellForColumnAndRow(column, row); 949 return WebAXObject(static_cast<AXObject*>(cell)); 950 } 951 952 WebAXObject WebAXObject::headerContainerObject() const 953 { 954 if (isDetached()) 955 return WebAXObject(); 956 957 if (!m_private->isAXTable()) 958 return WebAXObject(); 959 960 return WebAXObject(toAXTable(m_private.get())->headerContainer()); 961 } 962 963 WebAXObject WebAXObject::rowAtIndex(unsigned rowIndex) const 964 { 965 if (isDetached()) 966 return WebAXObject(); 967 968 if (!m_private->isAXTable()) 969 return WebAXObject(); 970 971 const AXObject::AccessibilityChildrenVector& rows = toAXTable(m_private.get())->rows(); 972 if (rowIndex < rows.size()) 973 return WebAXObject(rows[rowIndex]); 974 975 return WebAXObject(); 976 } 977 978 WebAXObject WebAXObject::columnAtIndex(unsigned columnIndex) const 979 { 980 if (isDetached()) 981 return WebAXObject(); 982 983 if (!m_private->isAXTable()) 984 return WebAXObject(); 985 986 const AXObject::AccessibilityChildrenVector& columns = toAXTable(m_private.get())->columns(); 987 if (columnIndex < columns.size()) 988 return WebAXObject(columns[columnIndex]); 989 990 return WebAXObject(); 991 } 992 993 unsigned WebAXObject::rowIndex() const 994 { 995 if (isDetached()) 996 return 0; 997 998 if (!m_private->isTableRow()) 999 return 0; 1000 1001 return toAXTableRow(m_private.get())->rowIndex(); 1002 } 1003 1004 WebAXObject WebAXObject::rowHeader() const 1005 { 1006 if (isDetached()) 1007 return WebAXObject(); 1008 1009 if (!m_private->isTableRow()) 1010 return WebAXObject(); 1011 1012 return WebAXObject(toAXTableRow(m_private.get())->headerObject()); 1013 } 1014 1015 unsigned WebAXObject::columnIndex() const 1016 { 1017 if (isDetached()) 1018 return 0; 1019 1020 if (m_private->roleValue() != ColumnRole) 1021 return 0; 1022 1023 return toAXTableColumn(m_private.get())->columnIndex(); 1024 } 1025 1026 WebAXObject WebAXObject::columnHeader() const 1027 { 1028 if (isDetached()) 1029 return WebAXObject(); 1030 1031 if (m_private->roleValue() != ColumnRole) 1032 return WebAXObject(); 1033 1034 return WebAXObject(toAXTableColumn(m_private.get())->headerObject()); 1035 } 1036 1037 unsigned WebAXObject::cellColumnIndex() const 1038 { 1039 if (isDetached()) 1040 return 0; 1041 1042 if (!m_private->isTableCell()) 1043 return 0; 1044 1045 pair<unsigned, unsigned> columnRange; 1046 toAXTableCell(m_private.get())->columnIndexRange(columnRange); 1047 return columnRange.first; 1048 } 1049 1050 unsigned WebAXObject::cellColumnSpan() const 1051 { 1052 if (isDetached()) 1053 return 0; 1054 1055 if (!m_private->isTableCell()) 1056 return 0; 1057 1058 pair<unsigned, unsigned> columnRange; 1059 toAXTableCell(m_private.get())->columnIndexRange(columnRange); 1060 return columnRange.second; 1061 } 1062 1063 unsigned WebAXObject::cellRowIndex() const 1064 { 1065 if (isDetached()) 1066 return 0; 1067 1068 if (!m_private->isTableCell()) 1069 return 0; 1070 1071 pair<unsigned, unsigned> rowRange; 1072 toAXTableCell(m_private.get())->rowIndexRange(rowRange); 1073 return rowRange.first; 1074 } 1075 1076 unsigned WebAXObject::cellRowSpan() const 1077 { 1078 if (isDetached()) 1079 return 0; 1080 1081 if (!m_private->isTableCell()) 1082 return 0; 1083 1084 pair<unsigned, unsigned> rowRange; 1085 toAXTableCell(m_private.get())->rowIndexRange(rowRange); 1086 return rowRange.second; 1087 } 1088 1089 WebAXTextDirection WebAXObject::textDirection() const 1090 { 1091 if (isDetached()) 1092 return WebAXTextDirectionLR; 1093 1094 return static_cast<WebAXTextDirection>(m_private->textDirection()); 1095 } 1096 1097 void WebAXObject::characterOffsets(WebVector<int>& offsets) const 1098 { 1099 if (isDetached()) 1100 return; 1101 1102 Vector<int> offsetsVector; 1103 m_private->textCharacterOffsets(offsetsVector); 1104 1105 size_t vectorSize = offsetsVector.size(); 1106 WebVector<int> offsetsWebVector(vectorSize); 1107 for (size_t i = 0; i < vectorSize; i++) 1108 offsetsWebVector[i] = offsetsVector[i]; 1109 offsets.swap(offsetsWebVector); 1110 } 1111 1112 void WebAXObject::wordBoundaries(WebVector<int>& starts, WebVector<int>& ends) const 1113 { 1114 if (isDetached()) 1115 return; 1116 1117 Vector<AXObject::PlainTextRange> words; 1118 m_private->wordBoundaries(words); 1119 1120 WebVector<int> startsWebVector(words.size()); 1121 WebVector<int> endsWebVector(words.size()); 1122 for (size_t i = 0; i < words.size(); i++) { 1123 startsWebVector[i] = words[i].start; 1124 endsWebVector[i] = words[i].start + words[i].length; 1125 } 1126 starts.swap(startsWebVector); 1127 ends.swap(endsWebVector); 1128 } 1129 1130 void WebAXObject::scrollToMakeVisible() const 1131 { 1132 if (!isDetached()) 1133 m_private->scrollToMakeVisible(); 1134 } 1135 1136 void WebAXObject::scrollToMakeVisibleWithSubFocus(const WebRect& subfocus) const 1137 { 1138 if (!isDetached()) 1139 m_private->scrollToMakeVisibleWithSubFocus(subfocus); 1140 } 1141 1142 void WebAXObject::scrollToGlobalPoint(const WebPoint& point) const 1143 { 1144 if (!isDetached()) 1145 m_private->scrollToGlobalPoint(point); 1146 } 1147 1148 WebAXObject::WebAXObject(const WTF::PassRefPtr<AXObject>& object) 1149 : m_private(object) 1150 { 1151 } 1152 1153 WebAXObject& WebAXObject::operator=(const WTF::PassRefPtr<AXObject>& object) 1154 { 1155 m_private = object; 1156 return *this; 1157 } 1158 1159 WebAXObject::operator WTF::PassRefPtr<AXObject>() const 1160 { 1161 return m_private.get(); 1162 } 1163 1164 } // namespace blink 1165