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 "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