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