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 57namespace 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. 62static 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 71void WebAXObject::reset() 72{ 73 m_private.reset(); 74} 75 76void WebAXObject::assign(const WebAXObject& other) 77{ 78 m_private = other.m_private; 79} 80 81bool WebAXObject::equals(const WebAXObject& n) const 82{ 83 return m_private.get() == n.m_private.get(); 84} 85 86bool WebAXObject::isDetached() const 87{ 88 if (m_private.isNull()) 89 return true; 90 91 return m_private->isDetached(); 92} 93 94int WebAXObject::axID() const 95{ 96 if (isDetached()) 97 return -1; 98 99 return m_private->axObjectID(); 100} 101 102bool 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 115bool WebAXObject::updateBackingStoreAndCheckValidity() 116{ 117 return updateLayoutAndCheckValidity(); 118} 119 120WebString 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 130WebString WebAXObject::actionVerb() const 131{ 132 if (isDetached()) 133 return WebString(); 134 135 return m_private->actionVerb(); 136} 137 138bool WebAXObject::canDecrement() const 139{ 140 if (isDetached()) 141 return false; 142 143 return m_private->isSlider(); 144} 145 146bool WebAXObject::canIncrement() const 147{ 148 if (isDetached()) 149 return false; 150 151 return m_private->isSlider(); 152} 153 154bool WebAXObject::canPress() const 155{ 156 if (isDetached()) 157 return false; 158 159 return m_private->actionElement() || m_private->isButton() || m_private->isMenuRelated(); 160} 161 162bool WebAXObject::canSetFocusAttribute() const 163{ 164 if (isDetached()) 165 return false; 166 167 return m_private->canSetFocusAttribute(); 168} 169 170bool WebAXObject::canSetValueAttribute() const 171{ 172 if (isDetached()) 173 return false; 174 175 return m_private->canSetValueAttribute(); 176} 177 178unsigned WebAXObject::childCount() const 179{ 180 if (isDetached()) 181 return 0; 182 183 return m_private->children().size(); 184} 185 186WebAXObject 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 197WebAXObject WebAXObject::parentObject() const 198{ 199 if (isDetached()) 200 return WebAXObject(); 201 202 return WebAXObject(m_private->parentObject()); 203} 204 205bool WebAXObject::canSetSelectedAttribute() const 206{ 207 if (isDetached()) 208 return 0; 209 210 return m_private->canSetSelectedAttribute(); 211} 212 213bool WebAXObject::isAnchor() const 214{ 215 if (isDetached()) 216 return 0; 217 218 return m_private->isAnchor(); 219} 220 221bool WebAXObject::isAriaReadOnly() const 222{ 223 if (isDetached()) 224 return 0; 225 226 return equalIgnoringCase(m_private->getAttribute(HTMLNames::aria_readonlyAttr), "true"); 227} 228 229bool WebAXObject::isButtonStateMixed() const 230{ 231 if (isDetached()) 232 return 0; 233 234 return m_private->checkboxOrRadioValue() == ButtonStateMixed; 235} 236 237bool WebAXObject::isChecked() const 238{ 239 if (isDetached()) 240 return 0; 241 242 return m_private->isChecked(); 243} 244 245bool WebAXObject::isClickable() const 246{ 247 if (isDetached()) 248 return 0; 249 250 return m_private->isClickable(); 251} 252 253bool WebAXObject::isCollapsed() const 254{ 255 if (isDetached()) 256 return 0; 257 258 return m_private->isCollapsed(); 259} 260 261bool WebAXObject::isControl() const 262{ 263 if (isDetached()) 264 return 0; 265 266 return m_private->isControl(); 267} 268 269bool WebAXObject::isEnabled() const 270{ 271 if (isDetached()) 272 return 0; 273 274 return m_private->isEnabled(); 275} 276 277bool WebAXObject::isFocused() const 278{ 279 if (isDetached()) 280 return 0; 281 282 return m_private->isFocused(); 283} 284 285bool WebAXObject::isHovered() const 286{ 287 if (isDetached()) 288 return 0; 289 290 return m_private->isHovered(); 291} 292 293bool WebAXObject::isIndeterminate() const 294{ 295 if (isDetached()) 296 return 0; 297 298 return m_private->isIndeterminate(); 299} 300 301bool WebAXObject::isLinked() const 302{ 303 if (isDetached()) 304 return 0; 305 306 return m_private->isLinked(); 307} 308 309bool WebAXObject::isLoaded() const 310{ 311 if (isDetached()) 312 return 0; 313 314 return m_private->isLoaded(); 315} 316 317bool WebAXObject::isMultiSelectable() const 318{ 319 if (isDetached()) 320 return 0; 321 322 return m_private->isMultiSelectable(); 323} 324 325bool WebAXObject::isOffScreen() const 326{ 327 if (isDetached()) 328 return 0; 329 330 return m_private->isOffScreen(); 331} 332 333bool WebAXObject::isPasswordField() const 334{ 335 if (isDetached()) 336 return 0; 337 338 return m_private->isPasswordField(); 339} 340 341bool WebAXObject::isPressed() const 342{ 343 if (isDetached()) 344 return 0; 345 346 return m_private->isPressed(); 347} 348 349bool WebAXObject::isReadOnly() const 350{ 351 if (isDetached()) 352 return 0; 353 354 return m_private->isReadOnly(); 355} 356 357bool WebAXObject::isRequired() const 358{ 359 if (isDetached()) 360 return 0; 361 362 return m_private->isRequired(); 363} 364 365bool WebAXObject::isSelected() const 366{ 367 if (isDetached()) 368 return 0; 369 370 return m_private->isSelected(); 371} 372 373bool WebAXObject::isSelectedOptionActive() const 374{ 375 if (isDetached()) 376 return false; 377 378 return m_private->isSelectedOptionActive(); 379} 380 381bool WebAXObject::isVertical() const 382{ 383 if (isDetached()) 384 return 0; 385 386 return m_private->orientation() == AccessibilityOrientationVertical; 387} 388 389bool WebAXObject::isVisible() const 390{ 391 if (isDetached()) 392 return 0; 393 394 return m_private->isVisible(); 395} 396 397bool WebAXObject::isVisited() const 398{ 399 if (isDetached()) 400 return 0; 401 402 return m_private->isVisited(); 403} 404 405WebString WebAXObject::accessKey() const 406{ 407 if (isDetached()) 408 return WebString(); 409 410 return WebString(m_private->accessKey()); 411} 412 413WebAXObject WebAXObject::ariaActiveDescendant() const 414{ 415 if (isDetached()) 416 return WebAXObject(); 417 418 return WebAXObject(m_private->activeDescendant()); 419} 420 421bool 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 437bool 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 453bool WebAXObject::ariaHasPopup() const 454{ 455 if (isDetached()) 456 return 0; 457 458 return m_private->ariaHasPopup(); 459} 460 461bool 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 477bool 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 493bool WebAXObject::ariaLiveRegionAtomic() const 494{ 495 if (isDetached()) 496 return 0; 497 498 return m_private->ariaLiveRegionAtomic(); 499} 500 501bool WebAXObject::ariaLiveRegionBusy() const 502{ 503 if (isDetached()) 504 return 0; 505 506 return m_private->ariaLiveRegionBusy(); 507} 508 509WebString WebAXObject::ariaLiveRegionRelevant() const 510{ 511 if (isDetached()) 512 return WebString(); 513 514 return m_private->ariaLiveRegionRelevant(); 515} 516 517WebString WebAXObject::ariaLiveRegionStatus() const 518{ 519 if (isDetached()) 520 return WebString(); 521 522 return m_private->ariaLiveRegionStatus(); 523} 524 525bool 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 541WebRect 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 551bool WebAXObject::canvasHasFallbackContent() const 552{ 553 if (isDetached()) 554 return false; 555 556 return m_private->canvasHasFallbackContent(); 557} 558 559WebPoint WebAXObject::clickPoint() const 560{ 561 if (isDetached()) 562 return WebPoint(); 563 564 return WebPoint(m_private->clickPoint()); 565} 566 567void 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 575double WebAXObject::estimatedLoadingProgress() const 576{ 577 if (isDetached()) 578 return 0.0; 579 580 return m_private->estimatedLoadingProgress(); 581} 582 583WebString WebAXObject::helpText() const 584{ 585 if (isDetached()) 586 return WebString(); 587 588 return m_private->helpText(); 589} 590 591int WebAXObject::headingLevel() const 592{ 593 if (isDetached()) 594 return 0; 595 596 return m_private->headingLevel(); 597} 598 599int WebAXObject::hierarchicalLevel() const 600{ 601 if (isDetached()) 602 return 0; 603 604 return m_private->hierarchicalLevel(); 605} 606 607WebAXObject 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 624WebString 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 654bool WebAXObject::performDefaultAction() const 655{ 656 if (isDetached()) 657 return false; 658 659 return m_private->performDefaultAction(); 660} 661 662bool 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 674bool 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 686bool WebAXObject::press() const 687{ 688 if (isDetached()) 689 return false; 690 691 return m_private->press(); 692} 693 694WebAXRole WebAXObject::role() const 695{ 696 if (isDetached()) 697 return WebAXRoleUnknown; 698 699 return static_cast<WebAXRole>(m_private->roleValue()); 700} 701 702unsigned WebAXObject::selectionEnd() const 703{ 704 if (isDetached()) 705 return 0; 706 707 return m_private->selectedTextRange().start + m_private->selectedTextRange().length; 708} 709 710unsigned WebAXObject::selectionStart() const 711{ 712 if (isDetached()) 713 return 0; 714 715 return m_private->selectedTextRange().start; 716} 717 718unsigned 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 730unsigned 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 742void WebAXObject::setFocused(bool on) const 743{ 744 if (!isDetached()) 745 m_private->setFocused(on); 746} 747 748void 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 756WebString WebAXObject::stringValue() const 757{ 758 if (isDetached()) 759 return WebString(); 760 761 return m_private->stringValue(); 762} 763 764WebString 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 774WebAXObject 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 785WebURL WebAXObject::url() const 786{ 787 if (isDetached()) 788 return WebURL(); 789 790 return m_private->url(); 791} 792 793bool WebAXObject::supportsRangeValue() const 794{ 795 if (isDetached()) 796 return false; 797 798 return m_private->supportsRangeValue(); 799} 800 801WebString WebAXObject::valueDescription() const 802{ 803 if (isDetached()) 804 return WebString(); 805 806 return m_private->valueDescription(); 807} 808 809float WebAXObject::valueForRange() const 810{ 811 if (isDetached()) 812 return 0.0; 813 814 return m_private->valueForRange(); 815} 816 817float WebAXObject::maxValueForRange() const 818{ 819 if (isDetached()) 820 return 0.0; 821 822 return m_private->maxValueForRange(); 823} 824 825float WebAXObject::minValueForRange() const 826{ 827 if (isDetached()) 828 return 0.0; 829 830 return m_private->minValueForRange(); 831} 832 833WebNode 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 845WebDocument 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 857bool 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 873WebString 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 893bool WebAXObject::accessibilityIsIgnored() const 894{ 895 if (isDetached()) 896 return false; 897 898 return m_private->accessibilityIsIgnored(); 899} 900 901bool 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 918unsigned 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 929unsigned 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 940WebAXObject 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 952WebAXObject 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 963WebAXObject 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 978WebAXObject 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 993unsigned 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 1004WebAXObject 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 1015unsigned 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 1026WebAXObject 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 1037unsigned 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 1050unsigned 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 1063unsigned 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 1076unsigned 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 1089WebAXTextDirection WebAXObject::textDirection() const 1090{ 1091 if (isDetached()) 1092 return WebAXTextDirectionLR; 1093 1094 return static_cast<WebAXTextDirection>(m_private->textDirection()); 1095} 1096 1097void 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 1112void 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 1130void WebAXObject::scrollToMakeVisible() const 1131{ 1132 if (!isDetached()) 1133 m_private->scrollToMakeVisible(); 1134} 1135 1136void WebAXObject::scrollToMakeVisibleWithSubFocus(const WebRect& subfocus) const 1137{ 1138 if (!isDetached()) 1139 m_private->scrollToMakeVisibleWithSubFocus(subfocus); 1140} 1141 1142void WebAXObject::scrollToGlobalPoint(const WebPoint& point) const 1143{ 1144 if (!isDetached()) 1145 m_private->scrollToGlobalPoint(point); 1146} 1147 1148WebAXObject::WebAXObject(const WTF::PassRefPtr<AXObject>& object) 1149 : m_private(object) 1150{ 1151} 1152 1153WebAXObject& WebAXObject::operator=(const WTF::PassRefPtr<AXObject>& object) 1154{ 1155 m_private = object; 1156 return *this; 1157} 1158 1159WebAXObject::operator WTF::PassRefPtr<AXObject>() const 1160{ 1161 return m_private.get(); 1162} 1163 1164} // namespace blink 1165