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