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