Home | History | Annotate | Download | only in accessibility
      1 /*
      2 * Copyright (C) 2008 Apple 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
      6 * are met:
      7 *
      8 * 1.  Redistributions of source code must retain the above copyright
      9 *     notice, this list of conditions and the following disclaimer.
     10 * 2.  Redistributions in binary form must reproduce the above copyright
     11 *     notice, this list of conditions and the following disclaimer in the
     12 *     documentation and/or other materials provided with the distribution.
     13 * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
     14 *     its contributors may be used to endorse or promote products derived
     15 *     from this software without specific prior written permission.
     16 *
     17 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
     18 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     19 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
     20 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
     21 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
     22 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
     23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
     24 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     27 */
     28 
     29 #include "config.h"
     30 #include "core/accessibility/AXRenderObject.h"
     31 
     32 #include "bindings/v8/ExceptionStatePlaceholder.h"
     33 #include "core/accessibility/AXImageMapLink.h"
     34 #include "core/accessibility/AXInlineTextBox.h"
     35 #include "core/accessibility/AXObjectCache.h"
     36 #include "core/accessibility/AXSVGRoot.h"
     37 #include "core/accessibility/AXSpinButton.h"
     38 #include "core/accessibility/AXTable.h"
     39 #include "core/dom/ElementTraversal.h"
     40 #include "core/dom/shadow/ShadowRoot.h"
     41 #include "core/editing/FrameSelection.h"
     42 #include "core/editing/RenderedPosition.h"
     43 #include "core/editing/TextIterator.h"
     44 #include "core/editing/VisibleUnits.h"
     45 #include "core/editing/htmlediting.h"
     46 #include "core/frame/LocalFrame.h"
     47 #include "core/html/HTMLImageElement.h"
     48 #include "core/html/HTMLLabelElement.h"
     49 #include "core/html/HTMLOptionElement.h"
     50 #include "core/html/HTMLSelectElement.h"
     51 #include "core/html/HTMLTextAreaElement.h"
     52 #include "core/html/shadow/ShadowElementNames.h"
     53 #include "core/loader/ProgressTracker.h"
     54 #include "core/page/Page.h"
     55 #include "core/rendering/HitTestResult.h"
     56 #include "core/rendering/RenderFieldset.h"
     57 #include "core/rendering/RenderFileUploadControl.h"
     58 #include "core/rendering/RenderHTMLCanvas.h"
     59 #include "core/rendering/RenderImage.h"
     60 #include "core/rendering/RenderInline.h"
     61 #include "core/rendering/RenderLayer.h"
     62 #include "core/rendering/RenderListMarker.h"
     63 #include "core/rendering/RenderMenuList.h"
     64 #include "core/rendering/RenderTextControlSingleLine.h"
     65 #include "core/rendering/RenderTextFragment.h"
     66 #include "core/rendering/RenderView.h"
     67 #include "core/rendering/RenderWidget.h"
     68 #include "core/svg/SVGDocumentExtensions.h"
     69 #include "core/svg/SVGSVGElement.h"
     70 #include "core/svg/graphics/SVGImage.h"
     71 #include "platform/text/PlatformLocale.h"
     72 #include "wtf/StdLibExtras.h"
     73 
     74 using blink::WebLocalizedString;
     75 
     76 namespace WebCore {
     77 
     78 using namespace HTMLNames;
     79 
     80 static inline RenderObject* firstChildInContinuation(const RenderInline& renderer)
     81 {
     82     RenderBoxModelObject* r = renderer.continuation();
     83 
     84     while (r) {
     85         if (r->isRenderBlock())
     86             return r;
     87         if (RenderObject* child = r->slowFirstChild())
     88             return child;
     89         r = toRenderInline(r)->continuation();
     90     }
     91 
     92     return 0;
     93 }
     94 
     95 static inline bool isInlineWithContinuation(RenderObject* object)
     96 {
     97     if (!object->isBoxModelObject())
     98         return false;
     99 
    100     RenderBoxModelObject* renderer = toRenderBoxModelObject(object);
    101     if (!renderer->isRenderInline())
    102         return false;
    103 
    104     return toRenderInline(renderer)->continuation();
    105 }
    106 
    107 static inline RenderObject* firstChildConsideringContinuation(RenderObject* renderer)
    108 {
    109     RenderObject* firstChild = renderer->slowFirstChild();
    110 
    111     if (!firstChild && isInlineWithContinuation(renderer))
    112         firstChild = firstChildInContinuation(toRenderInline(*renderer));
    113 
    114     return firstChild;
    115 }
    116 
    117 static inline RenderInline* startOfContinuations(RenderObject* r)
    118 {
    119     if (r->isInlineElementContinuation()) {
    120         return toRenderInline(r->node()->renderer());
    121     }
    122 
    123     // Blocks with a previous continuation always have a next continuation
    124     if (r->isRenderBlock() && toRenderBlock(r)->inlineElementContinuation())
    125         return toRenderInline(toRenderBlock(r)->inlineElementContinuation()->node()->renderer());
    126 
    127     return 0;
    128 }
    129 
    130 static inline RenderObject* endOfContinuations(RenderObject* renderer)
    131 {
    132     RenderObject* prev = renderer;
    133     RenderObject* cur = renderer;
    134 
    135     if (!cur->isRenderInline() && !cur->isRenderBlock())
    136         return renderer;
    137 
    138     while (cur) {
    139         prev = cur;
    140         if (cur->isRenderInline()) {
    141             cur = toRenderInline(cur)->inlineElementContinuation();
    142             ASSERT(cur || !toRenderInline(prev)->continuation());
    143         } else {
    144             cur = toRenderBlock(cur)->inlineElementContinuation();
    145         }
    146     }
    147 
    148     return prev;
    149 }
    150 
    151 static inline bool lastChildHasContinuation(RenderObject* renderer)
    152 {
    153     RenderObject* lastChild = renderer->slowLastChild();
    154     return lastChild && isInlineWithContinuation(lastChild);
    155 }
    156 
    157 static RenderBoxModelObject* nextContinuation(RenderObject* renderer)
    158 {
    159     ASSERT(renderer);
    160     if (renderer->isRenderInline() && !renderer->isReplaced())
    161         return toRenderInline(renderer)->continuation();
    162     if (renderer->isRenderBlock())
    163         return toRenderBlock(renderer)->inlineElementContinuation();
    164     return 0;
    165 }
    166 
    167 AXRenderObject::AXRenderObject(RenderObject* renderer)
    168     : AXNodeObject(renderer->node())
    169     , m_renderer(renderer)
    170     , m_cachedElementRectDirty(true)
    171 {
    172 #ifndef NDEBUG
    173     m_renderer->setHasAXObject(true);
    174 #endif
    175 }
    176 
    177 PassRefPtr<AXRenderObject> AXRenderObject::create(RenderObject* renderer)
    178 {
    179     return adoptRef(new AXRenderObject(renderer));
    180 }
    181 
    182 AXRenderObject::~AXRenderObject()
    183 {
    184     ASSERT(isDetached());
    185 }
    186 
    187 LayoutRect AXRenderObject::elementRect() const
    188 {
    189     if (!m_explicitElementRect.isEmpty())
    190         return m_explicitElementRect;
    191     if (!m_renderer)
    192         return LayoutRect();
    193     if (!m_renderer->isBox())
    194         return computeElementRect();
    195 
    196     for (const AXObject* obj = this; obj; obj = obj->parentObject()) {
    197         if (obj->isAXRenderObject())
    198             toAXRenderObject(obj)->checkCachedElementRect();
    199     }
    200     for (const AXObject* obj = this; obj; obj = obj->parentObject()) {
    201         if (obj->isAXRenderObject())
    202             toAXRenderObject(obj)->updateCachedElementRect();
    203     }
    204 
    205     return m_cachedElementRect;
    206 }
    207 
    208 void AXRenderObject::setRenderer(RenderObject* renderer)
    209 {
    210     m_renderer = renderer;
    211     setNode(renderer->node());
    212 }
    213 
    214 RenderBoxModelObject* AXRenderObject::renderBoxModelObject() const
    215 {
    216     if (!m_renderer || !m_renderer->isBoxModelObject())
    217         return 0;
    218     return toRenderBoxModelObject(m_renderer);
    219 }
    220 
    221 Document* AXRenderObject::topDocument() const
    222 {
    223     if (!document())
    224         return 0;
    225     return &document()->topDocument();
    226 }
    227 
    228 bool AXRenderObject::shouldNotifyActiveDescendant() const
    229 {
    230     // We want to notify that the combo box has changed its active descendant,
    231     // but we do not want to change the focus, because focus should remain with the combo box.
    232     if (isComboBox())
    233         return true;
    234 
    235     return shouldFocusActiveDescendant();
    236 }
    237 
    238 ScrollableArea* AXRenderObject::getScrollableAreaIfScrollable() const
    239 {
    240     // If the parent is a scroll view, then this object isn't really scrollable, the parent ScrollView should handle the scrolling.
    241     if (parentObject() && parentObject()->isAXScrollView())
    242         return 0;
    243 
    244     if (!m_renderer || !m_renderer->isBox())
    245         return 0;
    246 
    247     RenderBox* box = toRenderBox(m_renderer);
    248     if (!box->canBeScrolledAndHasScrollableArea())
    249         return 0;
    250 
    251     return box->scrollableArea();
    252 }
    253 
    254 AccessibilityRole AXRenderObject::determineAccessibilityRole()
    255 {
    256     if (!m_renderer)
    257         return UnknownRole;
    258 
    259     m_ariaRole = determineAriaRoleAttribute();
    260 
    261     Node* node = m_renderer->node();
    262     AccessibilityRole ariaRole = ariaRoleAttribute();
    263     if (ariaRole != UnknownRole)
    264         return ariaRole;
    265 
    266     RenderBoxModelObject* cssBox = renderBoxModelObject();
    267 
    268     if (node && node->isLink()) {
    269         if (cssBox && cssBox->isImage())
    270             return ImageMapRole;
    271         return LinkRole;
    272     }
    273     if (cssBox && cssBox->isListItem())
    274         return ListItemRole;
    275     if (m_renderer->isListMarker())
    276         return ListMarkerRole;
    277     if (isHTMLButtonElement(node))
    278         return buttonRoleType();
    279     if (isHTMLLegendElement(node))
    280         return LegendRole;
    281     if (m_renderer->isText())
    282         return StaticTextRole;
    283     if (cssBox && cssBox->isImage()) {
    284         if (isHTMLInputElement(node))
    285             return ariaHasPopup() ? PopUpButtonRole : ButtonRole;
    286         if (isSVGImage())
    287             return SVGRootRole;
    288         return ImageRole;
    289     }
    290 
    291     // Note: if JavaScript is disabled, the renderer won't be a RenderHTMLCanvas.
    292     if (isHTMLCanvasElement(node) && m_renderer->isCanvas())
    293         return CanvasRole;
    294 
    295     if (cssBox && cssBox->isRenderView())
    296         return WebAreaRole;
    297 
    298     if (cssBox && cssBox->isTextField())
    299         return TextFieldRole;
    300 
    301     if (cssBox && cssBox->isTextArea())
    302         return TextAreaRole;
    303 
    304     if (isHTMLInputElement(node)) {
    305         HTMLInputElement& input = toHTMLInputElement(*node);
    306         if (input.isCheckbox())
    307             return CheckBoxRole;
    308         if (input.isRadioButton())
    309             return RadioButtonRole;
    310         if (input.isTextButton())
    311             return buttonRoleType();
    312 
    313         const AtomicString& type = input.getAttribute(typeAttr);
    314         if (equalIgnoringCase(type, "color"))
    315             return ColorWellRole;
    316     }
    317 
    318     if (isFileUploadButton())
    319         return ButtonRole;
    320 
    321     if (cssBox && cssBox->isMenuList())
    322         return PopUpButtonRole;
    323 
    324     if (headingLevel())
    325         return HeadingRole;
    326 
    327     if (m_renderer->isSVGImage())
    328         return ImageRole;
    329     if (m_renderer->isSVGRoot())
    330         return SVGRootRole;
    331 
    332     if (node && node->hasTagName(ddTag))
    333         return DescriptionListDetailRole;
    334 
    335     if (node && node->hasTagName(dtTag))
    336         return DescriptionListTermRole;
    337 
    338     if (node && (node->hasTagName(rpTag) || node->hasTagName(rtTag)))
    339         return AnnotationRole;
    340 
    341     // Table sections should be ignored.
    342     if (m_renderer->isTableSection())
    343         return IgnoredRole;
    344 
    345     if (m_renderer->isHR())
    346         return HorizontalRuleRole;
    347 
    348     if (isHTMLParagraphElement(node))
    349         return ParagraphRole;
    350 
    351     if (isHTMLLabelElement(node))
    352         return LabelRole;
    353 
    354     if (isHTMLDivElement(node))
    355         return DivRole;
    356 
    357     if (isHTMLFormElement(node))
    358         return FormRole;
    359 
    360     if (node && node->hasTagName(articleTag))
    361         return ArticleRole;
    362 
    363     if (node && node->hasTagName(mainTag))
    364         return MainRole;
    365 
    366     if (node && node->hasTagName(navTag))
    367         return NavigationRole;
    368 
    369     if (node && node->hasTagName(asideTag))
    370         return ComplementaryRole;
    371 
    372     if (node && node->hasTagName(sectionTag))
    373         return RegionRole;
    374 
    375     if (node && node->hasTagName(addressTag))
    376         return ContentInfoRole;
    377 
    378     if (node && node->hasTagName(dialogTag))
    379         return DialogRole;
    380 
    381     // The HTML element should not be exposed as an element. That's what the RenderView element does.
    382     if (isHTMLHtmlElement(node))
    383         return IgnoredRole;
    384 
    385     if (node && node->hasTagName(iframeTag))
    386         return IframeRole;
    387 
    388     if (isEmbeddedObject())
    389         return EmbeddedObjectRole;
    390 
    391     // There should only be one banner/contentInfo per page. If header/footer are being used within an article or section
    392     // then it should not be exposed as whole page's banner/contentInfo
    393     if (node && node->hasTagName(headerTag) && !isDescendantOfElementType(articleTag) && !isDescendantOfElementType(sectionTag))
    394         return BannerRole;
    395     if (node && node->hasTagName(footerTag) && !isDescendantOfElementType(articleTag) && !isDescendantOfElementType(sectionTag))
    396         return FooterRole;
    397 
    398     if (isHTMLAnchorElement(node) && isClickable())
    399         return LinkRole;
    400 
    401     if (m_renderer->isRenderBlockFlow())
    402         return GroupRole;
    403 
    404     // If the element does not have role, but it has ARIA attributes, accessibility should fallback to exposing it as a group.
    405     if (supportsARIAAttributes())
    406         return GroupRole;
    407 
    408     return UnknownRole;
    409 }
    410 
    411 void AXRenderObject::init()
    412 {
    413     AXNodeObject::init();
    414 }
    415 
    416 void AXRenderObject::detach()
    417 {
    418     AXNodeObject::detach();
    419 
    420     detachRemoteSVGRoot();
    421 
    422 #ifndef NDEBUG
    423     if (m_renderer)
    424         m_renderer->setHasAXObject(false);
    425 #endif
    426     m_renderer = 0;
    427 }
    428 
    429 //
    430 // Check object role or purpose.
    431 //
    432 
    433 bool AXRenderObject::isAttachment() const
    434 {
    435     RenderBoxModelObject* renderer = renderBoxModelObject();
    436     if (!renderer)
    437         return false;
    438     // Widgets are the replaced elements that we represent to AX as attachments
    439     bool isWidget = renderer->isWidget();
    440     ASSERT(!isWidget || (renderer->isReplaced() && !isImage()));
    441     return isWidget;
    442 }
    443 
    444 bool AXRenderObject::isFileUploadButton() const
    445 {
    446     if (m_renderer && isHTMLInputElement(m_renderer->node())) {
    447         HTMLInputElement& input = toHTMLInputElement(*m_renderer->node());
    448         return input.isFileUpload();
    449     }
    450 
    451     return false;
    452 }
    453 
    454 static bool isLinkable(const AXObject& object)
    455 {
    456     if (!object.renderer())
    457         return false;
    458 
    459     // See https://wiki.mozilla.org/Accessibility/AT-Windows-API for the elements
    460     // Mozilla considers linkable.
    461     return object.isLink() || object.isImage() || object.renderer()->isText();
    462 }
    463 
    464 bool AXRenderObject::isLinked() const
    465 {
    466     if (!isLinkable(*this))
    467         return false;
    468 
    469     Element* anchor = anchorElement();
    470     if (!isHTMLAnchorElement(anchor))
    471         return false;
    472 
    473     return !toHTMLAnchorElement(*anchor).href().isEmpty();
    474 }
    475 
    476 bool AXRenderObject::isLoaded() const
    477 {
    478     return !m_renderer->document().parser();
    479 }
    480 
    481 bool AXRenderObject::isOffScreen() const
    482 {
    483     ASSERT(m_renderer);
    484     IntRect contentRect = pixelSnappedIntRect(m_renderer->absoluteClippedOverflowRect());
    485     FrameView* view = m_renderer->frame()->view();
    486     IntRect viewRect = view->visibleContentRect();
    487     viewRect.intersect(contentRect);
    488     return viewRect.isEmpty();
    489 }
    490 
    491 bool AXRenderObject::isReadOnly() const
    492 {
    493     ASSERT(m_renderer);
    494 
    495     if (isWebArea()) {
    496         Document& document = m_renderer->document();
    497         HTMLElement* body = document.body();
    498         if (body && body->rendererIsEditable())
    499             return false;
    500 
    501         return !document.rendererIsEditable();
    502     }
    503 
    504     return AXNodeObject::isReadOnly();
    505 }
    506 
    507 bool AXRenderObject::isVisited() const
    508 {
    509     // FIXME: Is it a privacy violation to expose visited information to accessibility APIs?
    510     return m_renderer->style()->isLink() && m_renderer->style()->insideLink() == InsideVisitedLink;
    511 }
    512 
    513 //
    514 // Check object state.
    515 //
    516 
    517 bool AXRenderObject::isFocused() const
    518 {
    519     if (!m_renderer)
    520         return false;
    521 
    522     Document& document = m_renderer->document();
    523     Element* focusedElement = document.focusedElement();
    524     if (!focusedElement)
    525         return false;
    526 
    527     // A web area is represented by the Document node in the DOM tree, which isn't focusable.
    528     // Check instead if the frame's selection controller is focused
    529     if (focusedElement == m_renderer->node()
    530         || (roleValue() == WebAreaRole && document.frame()->selection().isFocusedAndActive()))
    531         return true;
    532 
    533     return false;
    534 }
    535 
    536 bool AXRenderObject::isSelected() const
    537 {
    538     if (!m_renderer)
    539         return false;
    540 
    541     Node* node = m_renderer->node();
    542     if (!node)
    543         return false;
    544 
    545     const AtomicString& ariaSelected = getAttribute(aria_selectedAttr);
    546     if (equalIgnoringCase(ariaSelected, "true"))
    547         return true;
    548 
    549     if (isTabItem() && isTabItemSelected())
    550         return true;
    551 
    552     return false;
    553 }
    554 
    555 //
    556 // Whether objects are ignored, i.e. not included in the tree.
    557 //
    558 
    559 AXObjectInclusion AXRenderObject::defaultObjectInclusion() const
    560 {
    561     // The following cases can apply to any element that's a subclass of AXRenderObject.
    562 
    563     if (!m_renderer)
    564         return IgnoreObject;
    565 
    566     if (m_renderer->style()->visibility() != VISIBLE) {
    567         // aria-hidden is meant to override visibility as the determinant in AX hierarchy inclusion.
    568         if (equalIgnoringCase(getAttribute(aria_hiddenAttr), "false"))
    569             return DefaultBehavior;
    570 
    571         return IgnoreObject;
    572     }
    573 
    574     return AXObject::defaultObjectInclusion();
    575 }
    576 
    577 bool AXRenderObject::computeAccessibilityIsIgnored() const
    578 {
    579 #ifndef NDEBUG
    580     ASSERT(m_initialized);
    581 #endif
    582 
    583     // Check first if any of the common reasons cause this element to be ignored.
    584     // Then process other use cases that need to be applied to all the various roles
    585     // that AXRenderObjects take on.
    586     AXObjectInclusion decision = defaultObjectInclusion();
    587     if (decision == IncludeObject)
    588         return false;
    589     if (decision == IgnoreObject)
    590         return true;
    591 
    592     // If this element is within a parent that cannot have children, it should not be exposed.
    593     if (isDescendantOfBarrenParent())
    594         return true;
    595 
    596     if (roleValue() == IgnoredRole)
    597         return true;
    598 
    599     if (roleValue() == PresentationalRole || inheritsPresentationalRole())
    600         return true;
    601 
    602     // An ARIA tree can only have tree items and static text as children.
    603     if (!isAllowedChildOfTree())
    604         return true;
    605 
    606     // TODO: we should refactor this - but right now this is necessary to make
    607     // sure scroll areas stay in the tree.
    608     if (isAttachment())
    609         return false;
    610 
    611     // ignore popup menu items because AppKit does
    612     for (RenderObject* parent = m_renderer->parent(); parent; parent = parent->parent()) {
    613         if (parent->isBoxModelObject() && toRenderBoxModelObject(parent)->isMenuList())
    614             return true;
    615     }
    616 
    617     // find out if this element is inside of a label element.
    618     // if so, it may be ignored because it's the label for a checkbox or radio button
    619     AXObject* controlObject = correspondingControlForLabelElement();
    620     if (controlObject && !controlObject->exposesTitleUIElement() && controlObject->isCheckboxOrRadio())
    621         return true;
    622 
    623     // NOTE: BRs always have text boxes now, so the text box check here can be removed
    624     if (m_renderer->isText()) {
    625         // static text beneath MenuItems and MenuButtons are just reported along with the menu item, so it's ignored on an individual level
    626         AXObject* parent = parentObjectUnignored();
    627         if (parent && (parent->ariaRoleAttribute() == MenuItemRole || parent->ariaRoleAttribute() == MenuButtonRole))
    628             return true;
    629         RenderText* renderText = toRenderText(m_renderer);
    630         if (m_renderer->isBR() || !renderText->firstTextBox())
    631             return true;
    632 
    633         // Don't ignore static text in editable text controls.
    634         for (AXObject* parent = parentObject(); parent; parent = parent->parentObject()) {
    635             if (parent->roleValue() == TextFieldRole || parent->roleValue() == TextAreaRole)
    636                 return false;
    637         }
    638 
    639         // text elements that are just empty whitespace should not be returned
    640         // FIXME(dmazzoni): we probably shouldn't ignore this if the style is 'pre', or similar...
    641         return renderText->text().impl()->containsOnlyWhitespace();
    642     }
    643 
    644     if (isHeading())
    645         return false;
    646 
    647     if (isLandmarkRelated())
    648         return false;
    649 
    650     if (isLink())
    651         return false;
    652 
    653     // all controls are accessible
    654     if (isControl())
    655         return false;
    656 
    657     if (ariaRoleAttribute() != UnknownRole)
    658         return false;
    659 
    660     // don't ignore labels, because they serve as TitleUIElements
    661     Node* node = m_renderer->node();
    662     if (isHTMLLabelElement(node))
    663         return false;
    664 
    665     // Anything that is content editable should not be ignored.
    666     // However, one cannot just call node->rendererIsEditable() since that will ask if its parents
    667     // are also editable. Only the top level content editable region should be exposed.
    668     if (hasContentEditableAttributeSet())
    669         return false;
    670 
    671     // List items play an important role in defining the structure of lists. They should not be ignored.
    672     if (roleValue() == ListItemRole)
    673         return false;
    674 
    675     if (roleValue() == DialogRole)
    676         return false;
    677 
    678     // if this element has aria attributes on it, it should not be ignored.
    679     if (supportsARIAAttributes())
    680         return false;
    681 
    682     // <span> tags are inline tags and not meant to convey information if they have no other aria
    683     // information on them. If we don't ignore them, they may emit signals expected to come from
    684     // their parent. In addition, because included spans are GroupRole objects, and GroupRole
    685     // objects are often containers with meaningful information, the inclusion of a span can have
    686     // the side effect of causing the immediate parent accessible to be ignored. This is especially
    687     // problematic for platforms which have distinct roles for textual block elements.
    688     if (isHTMLSpanElement(node))
    689         return true;
    690 
    691     if (m_renderer->isRenderBlockFlow() && m_renderer->childrenInline() && !canSetFocusAttribute())
    692         return !toRenderBlock(m_renderer)->firstLineBox() && !mouseButtonListener();
    693 
    694     // ignore images seemingly used as spacers
    695     if (isImage()) {
    696 
    697         // If the image can take focus, it should not be ignored, lest the user not be able to interact with something important.
    698         if (canSetFocusAttribute())
    699             return false;
    700 
    701         if (node && node->isElementNode()) {
    702             Element* elt = toElement(node);
    703             const AtomicString& alt = elt->getAttribute(altAttr);
    704             // don't ignore an image that has an alt tag
    705             if (!alt.string().containsOnlyWhitespace())
    706                 return false;
    707             // informal standard is to ignore images with zero-length alt strings
    708             if (!alt.isNull())
    709                 return true;
    710         }
    711 
    712         if (isNativeImage() && m_renderer->isImage()) {
    713             // check for one-dimensional image
    714             RenderImage* image = toRenderImage(m_renderer);
    715             if (image->height() <= 1 || image->width() <= 1)
    716                 return true;
    717 
    718             // check whether rendered image was stretched from one-dimensional file image
    719             if (image->cachedImage()) {
    720                 LayoutSize imageSize = image->cachedImage()->imageSizeForRenderer(m_renderer, image->view()->zoomFactor());
    721                 return imageSize.height() <= 1 || imageSize.width() <= 1;
    722             }
    723         }
    724         return false;
    725     }
    726 
    727     if (isCanvas()) {
    728         if (canvasHasFallbackContent())
    729             return false;
    730         RenderHTMLCanvas* canvas = toRenderHTMLCanvas(m_renderer);
    731         if (canvas->height() <= 1 || canvas->width() <= 1)
    732             return true;
    733         // Otherwise fall through; use presence of help text, title, or description to decide.
    734     }
    735 
    736     if (isWebArea() || m_renderer->isListMarker())
    737         return false;
    738 
    739     // Using the help text, title or accessibility description (so we
    740     // check if there's some kind of accessible name for the element)
    741     // to decide an element's visibility is not as definitive as
    742     // previous checks, so this should remain as one of the last.
    743     //
    744     // These checks are simplified in the interest of execution speed;
    745     // for example, any element having an alt attribute will make it
    746     // not ignored, rather than just images.
    747     if (!getAttribute(aria_helpAttr).isEmpty() || !getAttribute(aria_describedbyAttr).isEmpty() || !getAttribute(altAttr).isEmpty() || !getAttribute(titleAttr).isEmpty())
    748         return false;
    749 
    750     // Don't ignore generic focusable elements like <div tabindex=0>
    751     // unless they're completely empty, with no children.
    752     if (isGenericFocusableElement() && node->firstChild())
    753         return false;
    754 
    755     if (!ariaAccessibilityDescription().isEmpty())
    756         return false;
    757 
    758     // By default, objects should be ignored so that the AX hierarchy is not
    759     // filled with unnecessary items.
    760     return true;
    761 }
    762 
    763 //
    764 // Properties of static elements.
    765 //
    766 
    767 const AtomicString& AXRenderObject::accessKey() const
    768 {
    769     Node* node = m_renderer->node();
    770     if (!node)
    771         return nullAtom;
    772     if (!node->isElementNode())
    773         return nullAtom;
    774     return toElement(node)->getAttribute(accesskeyAttr);
    775 }
    776 
    777 AccessibilityOrientation AXRenderObject::orientation() const
    778 {
    779     const AtomicString& ariaOrientation = getAttribute(aria_orientationAttr);
    780     if (equalIgnoringCase(ariaOrientation, "horizontal"))
    781         return AccessibilityOrientationHorizontal;
    782     if (equalIgnoringCase(ariaOrientation, "vertical"))
    783         return AccessibilityOrientationVertical;
    784 
    785     return AXObject::orientation();
    786 }
    787 
    788 String AXRenderObject::text() const
    789 {
    790     if (isPasswordField())
    791         return String();
    792 
    793     return AXNodeObject::text();
    794 }
    795 
    796 int AXRenderObject::textLength() const
    797 {
    798     if (!isTextControl())
    799         return -1;
    800 
    801     if (isPasswordField())
    802         return -1; // need to return something distinct from 0
    803 
    804     return text().length();
    805 }
    806 
    807 KURL AXRenderObject::url() const
    808 {
    809     if (isAnchor() && isHTMLAnchorElement(m_renderer->node())) {
    810         if (HTMLAnchorElement* anchor = toHTMLAnchorElement(anchorElement()))
    811             return anchor->href();
    812     }
    813 
    814     if (isWebArea())
    815         return m_renderer->document().url();
    816 
    817     if (isImage() && isHTMLImageElement(m_renderer->node()))
    818         return toHTMLImageElement(*m_renderer->node()).src();
    819 
    820     if (isInputImage())
    821         return toHTMLInputElement(m_renderer->node())->src();
    822 
    823     return KURL();
    824 }
    825 
    826 //
    827 // Properties of interactive elements.
    828 //
    829 
    830 static String queryString(WebLocalizedString::Name name)
    831 {
    832     return Locale::defaultLocale().queryString(name);
    833 }
    834 
    835 String AXRenderObject::actionVerb() const
    836 {
    837     switch (roleValue()) {
    838     case ButtonRole:
    839     case ToggleButtonRole:
    840         return queryString(WebLocalizedString::AXButtonActionVerb);
    841     case TextFieldRole:
    842     case TextAreaRole:
    843         return queryString(WebLocalizedString::AXTextFieldActionVerb);
    844     case RadioButtonRole:
    845         return queryString(WebLocalizedString::AXRadioButtonActionVerb);
    846     case CheckBoxRole:
    847         return queryString(isChecked() ? WebLocalizedString::AXCheckedCheckBoxActionVerb : WebLocalizedString::AXUncheckedCheckBoxActionVerb);
    848     case LinkRole:
    849         return queryString(WebLocalizedString::AXLinkActionVerb);
    850     default:
    851         return emptyString();
    852     }
    853 }
    854 
    855 String AXRenderObject::stringValue() const
    856 {
    857     if (!m_renderer)
    858         return String();
    859 
    860     if (isPasswordField())
    861         return String();
    862 
    863     RenderBoxModelObject* cssBox = renderBoxModelObject();
    864 
    865     if (ariaRoleAttribute() == StaticTextRole) {
    866         String staticText = text();
    867         if (!staticText.length())
    868             staticText = textUnderElement();
    869         return staticText;
    870     }
    871 
    872     if (m_renderer->isText())
    873         return textUnderElement();
    874 
    875     if (cssBox && cssBox->isMenuList()) {
    876         // RenderMenuList will go straight to the text() of its selected item.
    877         // This has to be overridden in the case where the selected item has an ARIA label.
    878         HTMLSelectElement* selectElement = toHTMLSelectElement(m_renderer->node());
    879         int selectedIndex = selectElement->selectedIndex();
    880         const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& listItems = selectElement->listItems();
    881         if (selectedIndex >= 0 && static_cast<size_t>(selectedIndex) < listItems.size()) {
    882             const AtomicString& overriddenDescription = listItems[selectedIndex]->fastGetAttribute(aria_labelAttr);
    883             if (!overriddenDescription.isNull())
    884                 return overriddenDescription;
    885         }
    886         return toRenderMenuList(m_renderer)->text();
    887     }
    888 
    889     if (m_renderer->isListMarker())
    890         return toRenderListMarker(m_renderer)->text();
    891 
    892     if (isWebArea()) {
    893         // FIXME: Why would a renderer exist when the Document isn't attached to a frame?
    894         if (m_renderer->frame())
    895             return String();
    896 
    897         ASSERT_NOT_REACHED();
    898     }
    899 
    900     if (isTextControl())
    901         return text();
    902 
    903     if (m_renderer->isFileUploadControl())
    904         return toRenderFileUploadControl(m_renderer)->fileTextValue();
    905 
    906     // FIXME: We might need to implement a value here for more types
    907     // FIXME: It would be better not to advertise a value at all for the types for which we don't implement one;
    908     // this would require subclassing or making accessibilityAttributeNames do something other than return a
    909     // single static array.
    910     return String();
    911 }
    912 
    913 //
    914 // ARIA attributes.
    915 //
    916 
    917 AXObject* AXRenderObject::activeDescendant() const
    918 {
    919     if (!m_renderer)
    920         return 0;
    921 
    922     if (m_renderer->node() && !m_renderer->node()->isElementNode())
    923         return 0;
    924 
    925     Element* element = toElement(m_renderer->node());
    926     if (!element)
    927         return 0;
    928 
    929     const AtomicString& activeDescendantAttrStr = element->getAttribute(aria_activedescendantAttr);
    930     if (activeDescendantAttrStr.isNull() || activeDescendantAttrStr.isEmpty())
    931         return 0;
    932 
    933     Element* target = element->treeScope().getElementById(activeDescendantAttrStr);
    934     if (!target)
    935         return 0;
    936 
    937     AXObject* obj = axObjectCache()->getOrCreate(target);
    938 
    939     // An activedescendant is only useful if it has a renderer, because that's what's needed to post the notification.
    940     if (obj && obj->isAXRenderObject())
    941         return obj;
    942 
    943     return 0;
    944 }
    945 
    946 void AXRenderObject::accessibilityChildrenFromAttribute(QualifiedName attr, AccessibilityChildrenVector& children) const
    947 {
    948     Vector<Element*> elements;
    949     elementsFromAttribute(elements, attr);
    950 
    951     AXObjectCache* cache = axObjectCache();
    952     unsigned count = elements.size();
    953     for (unsigned k = 0; k < count; ++k) {
    954         Element* element = elements[k];
    955         AXObject* child = cache->getOrCreate(element);
    956         if (child)
    957             children.append(child);
    958     }
    959 }
    960 
    961 void AXRenderObject::ariaFlowToElements(AccessibilityChildrenVector& flowTo) const
    962 {
    963     accessibilityChildrenFromAttribute(aria_flowtoAttr, flowTo);
    964 }
    965 
    966 void AXRenderObject::ariaControlsElements(AccessibilityChildrenVector& controls) const
    967 {
    968     accessibilityChildrenFromAttribute(aria_controlsAttr, controls);
    969 }
    970 
    971 void AXRenderObject::ariaDescribedbyElements(AccessibilityChildrenVector& describedby) const
    972 {
    973     accessibilityChildrenFromAttribute(aria_describedbyAttr, describedby);
    974 }
    975 
    976 void AXRenderObject::ariaLabelledbyElements(AccessibilityChildrenVector& labelledby) const
    977 {
    978     accessibilityChildrenFromAttribute(aria_labelledbyAttr, labelledby);
    979 }
    980 
    981 void AXRenderObject::ariaOwnsElements(AccessibilityChildrenVector& owns) const
    982 {
    983     accessibilityChildrenFromAttribute(aria_ownsAttr, owns);
    984 }
    985 
    986 bool AXRenderObject::ariaHasPopup() const
    987 {
    988     return elementAttributeValue(aria_haspopupAttr);
    989 }
    990 
    991 bool AXRenderObject::ariaRoleHasPresentationalChildren() const
    992 {
    993     switch (m_ariaRole) {
    994     case ButtonRole:
    995     case SliderRole:
    996     case ImageRole:
    997     case ProgressIndicatorRole:
    998     case SpinButtonRole:
    999     // case SeparatorRole:
   1000         return true;
   1001     default:
   1002         return false;
   1003     }
   1004 }
   1005 
   1006 bool AXRenderObject::isPresentationalChildOfAriaRole() const
   1007 {
   1008     // Walk the parent chain looking for a parent that has presentational children
   1009     AXObject* parent;
   1010     for (parent = parentObject(); parent && !parent->ariaRoleHasPresentationalChildren(); parent = parent->parentObject())
   1011     { }
   1012 
   1013     return parent;
   1014 }
   1015 
   1016 bool AXRenderObject::shouldFocusActiveDescendant() const
   1017 {
   1018     switch (ariaRoleAttribute()) {
   1019     case ComboBoxRole:
   1020     case GridRole:
   1021     case GroupRole:
   1022     case ListBoxRole:
   1023     case MenuRole:
   1024     case MenuBarRole:
   1025     case OutlineRole:
   1026     case PopUpButtonRole:
   1027     case ProgressIndicatorRole:
   1028     case RadioGroupRole:
   1029     case RowRole:
   1030     case TabListRole:
   1031     case ToolbarRole:
   1032     case TreeRole:
   1033     case TreeGridRole:
   1034         return true;
   1035     default:
   1036         return false;
   1037     }
   1038 }
   1039 
   1040 bool AXRenderObject::supportsARIADragging() const
   1041 {
   1042     const AtomicString& grabbed = getAttribute(aria_grabbedAttr);
   1043     return equalIgnoringCase(grabbed, "true") || equalIgnoringCase(grabbed, "false");
   1044 }
   1045 
   1046 bool AXRenderObject::supportsARIADropping() const
   1047 {
   1048     const AtomicString& dropEffect = getAttribute(aria_dropeffectAttr);
   1049     return !dropEffect.isEmpty();
   1050 }
   1051 
   1052 bool AXRenderObject::supportsARIAFlowTo() const
   1053 {
   1054     return !getAttribute(aria_flowtoAttr).isEmpty();
   1055 }
   1056 
   1057 bool AXRenderObject::supportsARIAOwns() const
   1058 {
   1059     if (!m_renderer)
   1060         return false;
   1061     const AtomicString& ariaOwns = getAttribute(aria_ownsAttr);
   1062 
   1063     return !ariaOwns.isEmpty();
   1064 }
   1065 
   1066 //
   1067 // ARIA live-region features.
   1068 //
   1069 
   1070 const AtomicString& AXRenderObject::ariaLiveRegionStatus() const
   1071 {
   1072     DEFINE_STATIC_LOCAL(const AtomicString, liveRegionStatusAssertive, ("assertive", AtomicString::ConstructFromLiteral));
   1073     DEFINE_STATIC_LOCAL(const AtomicString, liveRegionStatusPolite, ("polite", AtomicString::ConstructFromLiteral));
   1074     DEFINE_STATIC_LOCAL(const AtomicString, liveRegionStatusOff, ("off", AtomicString::ConstructFromLiteral));
   1075 
   1076     const AtomicString& liveRegionStatus = getAttribute(aria_liveAttr);
   1077     // These roles have implicit live region status.
   1078     if (liveRegionStatus.isEmpty()) {
   1079         switch (roleValue()) {
   1080         case AlertDialogRole:
   1081         case AlertRole:
   1082             return liveRegionStatusAssertive;
   1083         case LogRole:
   1084         case StatusRole:
   1085             return liveRegionStatusPolite;
   1086         case TimerRole:
   1087         case MarqueeRole:
   1088             return liveRegionStatusOff;
   1089         default:
   1090             break;
   1091         }
   1092     }
   1093 
   1094     return liveRegionStatus;
   1095 }
   1096 
   1097 const AtomicString& AXRenderObject::ariaLiveRegionRelevant() const
   1098 {
   1099     DEFINE_STATIC_LOCAL(const AtomicString, defaultLiveRegionRelevant, ("additions text", AtomicString::ConstructFromLiteral));
   1100     const AtomicString& relevant = getAttribute(aria_relevantAttr);
   1101 
   1102     // Default aria-relevant = "additions text".
   1103     if (relevant.isEmpty())
   1104         return defaultLiveRegionRelevant;
   1105 
   1106     return relevant;
   1107 }
   1108 
   1109 bool AXRenderObject::ariaLiveRegionAtomic() const
   1110 {
   1111     return elementAttributeValue(aria_atomicAttr);
   1112 }
   1113 
   1114 bool AXRenderObject::ariaLiveRegionBusy() const
   1115 {
   1116     return elementAttributeValue(aria_busyAttr);
   1117 }
   1118 
   1119 //
   1120 // Accessibility Text.
   1121 //
   1122 
   1123 String AXRenderObject::textUnderElement() const
   1124 {
   1125     if (!m_renderer)
   1126         return String();
   1127 
   1128     if (m_renderer->isFileUploadControl())
   1129         return toRenderFileUploadControl(m_renderer)->buttonValue();
   1130 
   1131     if (m_renderer->isText())
   1132         return toRenderText(m_renderer)->plainText();
   1133 
   1134     return AXNodeObject::textUnderElement();
   1135 }
   1136 
   1137 //
   1138 // Accessibility Text - (To be deprecated).
   1139 //
   1140 
   1141 String AXRenderObject::helpText() const
   1142 {
   1143     if (!m_renderer)
   1144         return String();
   1145 
   1146     const AtomicString& ariaHelp = getAttribute(aria_helpAttr);
   1147     if (!ariaHelp.isEmpty())
   1148         return ariaHelp;
   1149 
   1150     String describedBy = ariaDescribedByAttribute();
   1151     if (!describedBy.isEmpty())
   1152         return describedBy;
   1153 
   1154     String description = accessibilityDescription();
   1155     for (RenderObject* curr = m_renderer; curr; curr = curr->parent()) {
   1156         if (curr->node() && curr->node()->isHTMLElement()) {
   1157             const AtomicString& summary = toElement(curr->node())->getAttribute(summaryAttr);
   1158             if (!summary.isEmpty())
   1159                 return summary;
   1160 
   1161             // The title attribute should be used as help text unless it is already being used as descriptive text.
   1162             const AtomicString& title = toElement(curr->node())->getAttribute(titleAttr);
   1163             if (!title.isEmpty() && description != title)
   1164                 return title;
   1165         }
   1166 
   1167         // Only take help text from an ancestor element if its a group or an unknown role. If help was
   1168         // added to those kinds of elements, it is likely it was meant for a child element.
   1169         AXObject* axObj = axObjectCache()->getOrCreate(curr);
   1170         if (axObj) {
   1171             AccessibilityRole role = axObj->roleValue();
   1172             if (role != GroupRole && role != UnknownRole)
   1173                 break;
   1174         }
   1175     }
   1176 
   1177     return String();
   1178 }
   1179 
   1180 //
   1181 // Position and size.
   1182 //
   1183 
   1184 void AXRenderObject::checkCachedElementRect() const
   1185 {
   1186     if (m_cachedElementRectDirty)
   1187         return;
   1188 
   1189     if (!m_renderer)
   1190         return;
   1191 
   1192     if (!m_renderer->isBox())
   1193         return;
   1194 
   1195     bool dirty = false;
   1196     RenderBox* box = toRenderBox(m_renderer);
   1197     if (box->frameRect() != m_cachedFrameRect)
   1198         dirty = true;
   1199 
   1200     if (box->canBeScrolledAndHasScrollableArea()) {
   1201         ScrollableArea* scrollableArea = box->scrollableArea();
   1202         if (scrollableArea && scrollableArea->scrollPosition() != m_cachedScrollPosition)
   1203             dirty = true;
   1204     }
   1205 
   1206     if (dirty)
   1207         markCachedElementRectDirty();
   1208 }
   1209 
   1210 void AXRenderObject::updateCachedElementRect() const
   1211 {
   1212     if (!m_cachedElementRectDirty)
   1213         return;
   1214 
   1215     if (!m_renderer)
   1216         return;
   1217 
   1218     if (!m_renderer->isBox())
   1219         return;
   1220 
   1221     RenderBox* box = toRenderBox(m_renderer);
   1222     m_cachedFrameRect = box->frameRect();
   1223 
   1224     if (box->canBeScrolledAndHasScrollableArea()) {
   1225         ScrollableArea* scrollableArea = box->scrollableArea();
   1226         if (scrollableArea)
   1227             m_cachedScrollPosition = scrollableArea->scrollPosition();
   1228     }
   1229 
   1230     m_cachedElementRect = computeElementRect();
   1231     m_cachedElementRectDirty = false;
   1232 }
   1233 
   1234 void AXRenderObject::markCachedElementRectDirty() const
   1235 {
   1236     if (m_cachedElementRectDirty)
   1237         return;
   1238 
   1239     // Marks children recursively, if this element changed.
   1240     m_cachedElementRectDirty = true;
   1241     for (AXObject* child = firstChild(); child; child = child->nextSibling())
   1242         child->markCachedElementRectDirty();
   1243 }
   1244 
   1245 IntPoint AXRenderObject::clickPoint()
   1246 {
   1247     // Headings are usually much wider than their textual content. If the mid point is used, often it can be wrong.
   1248     if (isHeading() && children().size() == 1)
   1249         return children()[0]->clickPoint();
   1250 
   1251     // use the default position unless this is an editable web area, in which case we use the selection bounds.
   1252     if (!isWebArea() || isReadOnly())
   1253         return AXObject::clickPoint();
   1254 
   1255     IntRect bounds = pixelSnappedIntRect(elementRect());
   1256     return IntPoint(bounds.x() + (bounds.width() / 2), bounds.y() - (bounds.height() / 2));
   1257 }
   1258 
   1259 //
   1260 // Hit testing.
   1261 //
   1262 
   1263 AXObject* AXRenderObject::accessibilityHitTest(const IntPoint& point) const
   1264 {
   1265     if (!m_renderer || !m_renderer->hasLayer())
   1266         return 0;
   1267 
   1268     RenderLayer* layer = toRenderBox(m_renderer)->layer();
   1269 
   1270     HitTestRequest request(HitTestRequest::ReadOnly | HitTestRequest::Active);
   1271     HitTestResult hitTestResult = HitTestResult(point);
   1272     layer->hitTest(request, hitTestResult);
   1273     if (!hitTestResult.innerNode())
   1274         return 0;
   1275     Node* node = hitTestResult.innerNode()->deprecatedShadowAncestorNode();
   1276 
   1277     if (isHTMLAreaElement(node))
   1278         return accessibilityImageMapHitTest(toHTMLAreaElement(node), point);
   1279 
   1280     if (isHTMLOptionElement(node))
   1281         node = toHTMLOptionElement(*node).ownerSelectElement();
   1282 
   1283     RenderObject* obj = node->renderer();
   1284     if (!obj)
   1285         return 0;
   1286 
   1287     AXObject* result = obj->document().axObjectCache()->getOrCreate(obj);
   1288     result->updateChildrenIfNecessary();
   1289 
   1290     // Allow the element to perform any hit-testing it might need to do to reach non-render children.
   1291     result = result->elementAccessibilityHitTest(point);
   1292 
   1293     if (result && result->accessibilityIsIgnored()) {
   1294         // If this element is the label of a control, a hit test should return the control.
   1295         if (result->isAXRenderObject()) {
   1296             AXObject* controlObject = toAXRenderObject(result)->correspondingControlForLabelElement();
   1297             if (controlObject && !controlObject->exposesTitleUIElement())
   1298                 return controlObject;
   1299         }
   1300 
   1301         result = result->parentObjectUnignored();
   1302     }
   1303 
   1304     return result;
   1305 }
   1306 
   1307 AXObject* AXRenderObject::elementAccessibilityHitTest(const IntPoint& point) const
   1308 {
   1309     if (isSVGImage())
   1310         return remoteSVGElementHitTest(point);
   1311 
   1312     return AXObject::elementAccessibilityHitTest(point);
   1313 }
   1314 
   1315 //
   1316 // High-level accessibility tree access.
   1317 //
   1318 
   1319 AXObject* AXRenderObject::parentObject() const
   1320 {
   1321     if (!m_renderer)
   1322         return 0;
   1323 
   1324     if (ariaRoleAttribute() == MenuBarRole)
   1325         return axObjectCache()->getOrCreate(m_renderer->parent());
   1326 
   1327     // menuButton and its corresponding menu are DOM siblings, but Accessibility needs them to be parent/child
   1328     if (ariaRoleAttribute() == MenuRole) {
   1329         AXObject* parent = menuButtonForMenu();
   1330         if (parent)
   1331             return parent;
   1332     }
   1333 
   1334     RenderObject* parentObj = renderParentObject();
   1335     if (parentObj)
   1336         return axObjectCache()->getOrCreate(parentObj);
   1337 
   1338     // WebArea's parent should be the scroll view containing it.
   1339     if (isWebArea())
   1340         return axObjectCache()->getOrCreate(m_renderer->frame()->view());
   1341 
   1342     return 0;
   1343 }
   1344 
   1345 AXObject* AXRenderObject::parentObjectIfExists() const
   1346 {
   1347     // WebArea's parent should be the scroll view containing it.
   1348     if (isWebArea())
   1349         return axObjectCache()->get(m_renderer->frame()->view());
   1350 
   1351     return axObjectCache()->get(renderParentObject());
   1352 }
   1353 
   1354 //
   1355 // Low-level accessibility tree exploration, only for use within the accessibility module.
   1356 //
   1357 
   1358 AXObject* AXRenderObject::firstChild() const
   1359 {
   1360     if (!m_renderer)
   1361         return 0;
   1362 
   1363     RenderObject* firstChild = firstChildConsideringContinuation(m_renderer);
   1364 
   1365     if (!firstChild)
   1366         return 0;
   1367 
   1368     return axObjectCache()->getOrCreate(firstChild);
   1369 }
   1370 
   1371 AXObject* AXRenderObject::nextSibling() const
   1372 {
   1373     if (!m_renderer)
   1374         return 0;
   1375 
   1376     RenderObject* nextSibling = 0;
   1377 
   1378     RenderInline* inlineContinuation;
   1379     if (m_renderer->isRenderBlock() && (inlineContinuation = toRenderBlock(m_renderer)->inlineElementContinuation())) {
   1380         // Case 1: node is a block and has an inline continuation. Next sibling is the inline continuation's first child.
   1381         nextSibling = firstChildConsideringContinuation(inlineContinuation);
   1382     } else if (m_renderer->isAnonymousBlock() && lastChildHasContinuation(m_renderer)) {
   1383         // Case 2: Anonymous block parent of the start of a continuation - skip all the way to
   1384         // after the parent of the end, since everything in between will be linked up via the continuation.
   1385         RenderObject* lastParent = endOfContinuations(toRenderBlock(m_renderer)->lastChild())->parent();
   1386         while (lastChildHasContinuation(lastParent))
   1387             lastParent = endOfContinuations(lastParent->slowLastChild())->parent();
   1388         nextSibling = lastParent->nextSibling();
   1389     } else if (RenderObject* ns = m_renderer->nextSibling()) {
   1390         // Case 3: node has an actual next sibling
   1391         nextSibling = ns;
   1392     } else if (isInlineWithContinuation(m_renderer)) {
   1393         // Case 4: node is an inline with a continuation. Next sibling is the next sibling of the end
   1394         // of the continuation chain.
   1395         nextSibling = endOfContinuations(m_renderer)->nextSibling();
   1396     } else if (isInlineWithContinuation(m_renderer->parent())) {
   1397         // Case 5: node has no next sibling, and its parent is an inline with a continuation.
   1398         RenderObject* continuation = toRenderInline(m_renderer->parent())->continuation();
   1399 
   1400         if (continuation->isRenderBlock()) {
   1401             // Case 5a: continuation is a block - in this case the block itself is the next sibling.
   1402             nextSibling = continuation;
   1403         } else {
   1404             // Case 5b: continuation is an inline - in this case the inline's first child is the next sibling.
   1405             nextSibling = firstChildConsideringContinuation(continuation);
   1406         }
   1407     }
   1408 
   1409     if (!nextSibling)
   1410         return 0;
   1411 
   1412     return axObjectCache()->getOrCreate(nextSibling);
   1413 }
   1414 
   1415 void AXRenderObject::addChildren()
   1416 {
   1417     // If the need to add more children in addition to existing children arises,
   1418     // childrenChanged should have been called, leaving the object with no children.
   1419     ASSERT(!m_haveChildren);
   1420 
   1421     m_haveChildren = true;
   1422 
   1423     if (!canHaveChildren())
   1424         return;
   1425 
   1426     for (RefPtr<AXObject> obj = firstChild(); obj; obj = obj->nextSibling())
   1427         addChild(obj.get());
   1428 
   1429     addHiddenChildren();
   1430     addAttachmentChildren();
   1431     addImageMapChildren();
   1432     addTextFieldChildren();
   1433     addCanvasChildren();
   1434     addRemoteSVGChildren();
   1435     addInlineTextBoxChildren();
   1436 }
   1437 
   1438 bool AXRenderObject::canHaveChildren() const
   1439 {
   1440     if (!m_renderer)
   1441         return false;
   1442 
   1443     return AXNodeObject::canHaveChildren();
   1444 }
   1445 
   1446 void AXRenderObject::updateChildrenIfNecessary()
   1447 {
   1448     if (needsToUpdateChildren())
   1449         clearChildren();
   1450 
   1451     AXObject::updateChildrenIfNecessary();
   1452 }
   1453 
   1454 void AXRenderObject::clearChildren()
   1455 {
   1456     AXObject::clearChildren();
   1457     m_childrenDirty = false;
   1458 }
   1459 
   1460 AXObject* AXRenderObject::observableObject() const
   1461 {
   1462     // Find the object going up the parent chain that is used in accessibility to monitor certain notifications.
   1463     for (RenderObject* renderer = m_renderer; renderer && renderer->node(); renderer = renderer->parent()) {
   1464         if (renderObjectIsObservable(renderer))
   1465             return axObjectCache()->getOrCreate(renderer);
   1466     }
   1467 
   1468     return 0;
   1469 }
   1470 
   1471 //
   1472 // Properties of the object's owning document or page.
   1473 //
   1474 
   1475 double AXRenderObject::estimatedLoadingProgress() const
   1476 {
   1477     if (!m_renderer)
   1478         return 0;
   1479 
   1480     if (isLoaded())
   1481         return 1.0;
   1482 
   1483     if (LocalFrame* frame = m_renderer->document().frame())
   1484         return frame->loader().progress().estimatedProgress();
   1485     return 0;
   1486 }
   1487 
   1488 //
   1489 // DOM and Render tree access.
   1490 //
   1491 
   1492 Node* AXRenderObject::node() const
   1493 {
   1494     return m_renderer ? m_renderer->node() : 0;
   1495 }
   1496 
   1497 Document* AXRenderObject::document() const
   1498 {
   1499     if (!m_renderer)
   1500         return 0;
   1501     return &m_renderer->document();
   1502 }
   1503 
   1504 FrameView* AXRenderObject::documentFrameView() const
   1505 {
   1506     if (!m_renderer)
   1507         return 0;
   1508 
   1509     // this is the RenderObject's Document's LocalFrame's FrameView
   1510     return m_renderer->document().view();
   1511 }
   1512 
   1513 Element* AXRenderObject::anchorElement() const
   1514 {
   1515     if (!m_renderer)
   1516         return 0;
   1517 
   1518     AXObjectCache* cache = axObjectCache();
   1519     RenderObject* currRenderer;
   1520 
   1521     // Search up the render tree for a RenderObject with a DOM node. Defer to an earlier continuation, though.
   1522     for (currRenderer = m_renderer; currRenderer && !currRenderer->node(); currRenderer = currRenderer->parent()) {
   1523         if (currRenderer->isAnonymousBlock()) {
   1524             RenderObject* continuation = toRenderBlock(currRenderer)->continuation();
   1525             if (continuation)
   1526                 return cache->getOrCreate(continuation)->anchorElement();
   1527         }
   1528     }
   1529 
   1530     // bail if none found
   1531     if (!currRenderer)
   1532         return 0;
   1533 
   1534     // search up the DOM tree for an anchor element
   1535     // NOTE: this assumes that any non-image with an anchor is an HTMLAnchorElement
   1536     Node* node = currRenderer->node();
   1537     for ( ; node; node = node->parentNode()) {
   1538         if (isHTMLAnchorElement(*node) || (node->renderer() && cache->getOrCreate(node->renderer())->isAnchor()))
   1539             return toElement(node);
   1540     }
   1541 
   1542     return 0;
   1543 }
   1544 
   1545 Widget* AXRenderObject::widgetForAttachmentView() const
   1546 {
   1547     if (!isAttachment())
   1548         return 0;
   1549     return toRenderWidget(m_renderer)->widget();
   1550 }
   1551 
   1552 //
   1553 // Selected text.
   1554 //
   1555 
   1556 AXObject::PlainTextRange AXRenderObject::selectedTextRange() const
   1557 {
   1558     if (!isTextControl())
   1559         return PlainTextRange();
   1560 
   1561     if (isPasswordField())
   1562         return PlainTextRange();
   1563 
   1564     AccessibilityRole ariaRole = ariaRoleAttribute();
   1565     if (isNativeTextControl() && ariaRole == UnknownRole && m_renderer->isTextControl()) {
   1566         HTMLTextFormControlElement* textControl = toRenderTextControl(m_renderer)->textFormControlElement();
   1567         return PlainTextRange(textControl->selectionStart(), textControl->selectionEnd() - textControl->selectionStart());
   1568     }
   1569 
   1570     if (ariaRole == UnknownRole)
   1571         return PlainTextRange();
   1572 
   1573     return ariaSelectedTextRange();
   1574 }
   1575 
   1576 VisibleSelection AXRenderObject::selection() const
   1577 {
   1578     return m_renderer->frame()->selection().selection();
   1579 }
   1580 
   1581 //
   1582 // Modify or take an action on an object.
   1583 //
   1584 
   1585 void AXRenderObject::setSelectedTextRange(const PlainTextRange& range)
   1586 {
   1587     if (isNativeTextControl() && m_renderer->isTextControl()) {
   1588         HTMLTextFormControlElement* textControl = toRenderTextControl(m_renderer)->textFormControlElement();
   1589         textControl->setSelectionRange(range.start, range.start + range.length);
   1590         return;
   1591     }
   1592 
   1593     Document& document = m_renderer->document();
   1594     LocalFrame* frame = document.frame();
   1595     if (!frame)
   1596         return;
   1597     Node* node = m_renderer->node();
   1598     frame->selection().setSelection(VisibleSelection(Position(node, range.start, Position::PositionIsOffsetInAnchor),
   1599         Position(node, range.start + range.length, Position::PositionIsOffsetInAnchor), DOWNSTREAM));
   1600 }
   1601 
   1602 void AXRenderObject::setValue(const String& string)
   1603 {
   1604     if (!node() || !node()->isElementNode())
   1605         return;
   1606     if (!m_renderer || !m_renderer->isBoxModelObject())
   1607         return;
   1608 
   1609     RenderBoxModelObject* renderer = toRenderBoxModelObject(m_renderer);
   1610     if (renderer->isTextField() && isHTMLInputElement(*node()))
   1611         toHTMLInputElement(*node()).setValue(string);
   1612     else if (renderer->isTextArea() && isHTMLTextAreaElement(*node()))
   1613         toHTMLTextAreaElement(*node()).setValue(string);
   1614 }
   1615 
   1616 // FIXME: This function should use an IntSize to avoid the conversion below.
   1617 void AXRenderObject::scrollTo(const IntPoint& point) const
   1618 {
   1619     if (!m_renderer || !m_renderer->isBox())
   1620         return;
   1621 
   1622     RenderBox* box = toRenderBox(m_renderer);
   1623     if (!box->canBeScrolledAndHasScrollableArea())
   1624         return;
   1625 
   1626     box->scrollToOffset(IntSize(point.x(), point.y()));
   1627 }
   1628 
   1629 //
   1630 // Notifications that this object may have changed.
   1631 //
   1632 
   1633 void AXRenderObject::handleActiveDescendantChanged()
   1634 {
   1635     Element* element = toElement(renderer()->node());
   1636     if (!element)
   1637         return;
   1638     Document& doc = renderer()->document();
   1639     if (!doc.frame()->selection().isFocusedAndActive() || doc.focusedElement() != element)
   1640         return;
   1641     AXRenderObject* activedescendant = toAXRenderObject(activeDescendant());
   1642 
   1643     if (activedescendant && shouldNotifyActiveDescendant())
   1644         doc.axObjectCache()->postNotification(m_renderer, AXObjectCache::AXActiveDescendantChanged, true);
   1645 }
   1646 
   1647 void AXRenderObject::handleAriaExpandedChanged()
   1648 {
   1649     // Find if a parent of this object should handle aria-expanded changes.
   1650     AXObject* containerParent = this->parentObject();
   1651     while (containerParent) {
   1652         bool foundParent = false;
   1653 
   1654         switch (containerParent->roleValue()) {
   1655         case TreeRole:
   1656         case TreeGridRole:
   1657         case GridRole:
   1658         case TableRole:
   1659         case BrowserRole:
   1660             foundParent = true;
   1661             break;
   1662         default:
   1663             break;
   1664         }
   1665 
   1666         if (foundParent)
   1667             break;
   1668 
   1669         containerParent = containerParent->parentObject();
   1670     }
   1671 
   1672     // Post that the row count changed.
   1673     if (containerParent)
   1674         axObjectCache()->postNotification(containerParent, document(), AXObjectCache::AXRowCountChanged, true);
   1675 
   1676     // Post that the specific row either collapsed or expanded.
   1677     if (roleValue() == RowRole || roleValue() == TreeItemRole)
   1678         axObjectCache()->postNotification(this, document(), isExpanded() ? AXObjectCache::AXRowExpanded : AXObjectCache::AXRowCollapsed, true);
   1679 }
   1680 
   1681 void AXRenderObject::textChanged()
   1682 {
   1683     if (!m_renderer)
   1684         return;
   1685 
   1686     if (AXObjectCache::inlineTextBoxAccessibility() && roleValue() == StaticTextRole)
   1687         childrenChanged();
   1688 
   1689     // Do this last - AXNodeObject::textChanged posts live region announcements,
   1690     // and we should update the inline text boxes first.
   1691     AXNodeObject::textChanged();
   1692 }
   1693 
   1694 //
   1695 // Text metrics. Most of these should be deprecated, needs major cleanup.
   1696 //
   1697 
   1698 // NOTE: Consider providing this utility method as AX API
   1699 int AXRenderObject::index(const VisiblePosition& position) const
   1700 {
   1701     if (position.isNull() || !isTextControl())
   1702         return -1;
   1703 
   1704     if (renderObjectContainsPosition(m_renderer, position.deepEquivalent()))
   1705         return indexForVisiblePosition(position);
   1706 
   1707     return -1;
   1708 }
   1709 
   1710 VisiblePosition AXRenderObject::visiblePositionForIndex(int index) const
   1711 {
   1712     if (!m_renderer)
   1713         return VisiblePosition();
   1714 
   1715     if (isNativeTextControl() && m_renderer->isTextControl())
   1716         return toRenderTextControl(m_renderer)->textFormControlElement()->visiblePositionForIndex(index);
   1717 
   1718     if (!allowsTextRanges() && !m_renderer->isText())
   1719         return VisiblePosition();
   1720 
   1721     Node* node = m_renderer->node();
   1722     if (!node)
   1723         return VisiblePosition();
   1724 
   1725     if (index <= 0)
   1726         return VisiblePosition(firstPositionInOrBeforeNode(node), DOWNSTREAM);
   1727 
   1728     RefPtrWillBeRawPtr<Range> range = Range::create(m_renderer->document());
   1729     range->selectNodeContents(node, IGNORE_EXCEPTION);
   1730     CharacterIterator it(range.get());
   1731     it.advance(index - 1);
   1732     return VisiblePosition(Position(it.range()->endContainer(), it.range()->endOffset(), Position::PositionIsOffsetInAnch\
   1733 or), UPSTREAM);
   1734 }
   1735 
   1736 int AXRenderObject::indexForVisiblePosition(const VisiblePosition& pos) const
   1737 {
   1738     if (isNativeTextControl() && m_renderer->isTextControl()) {
   1739         HTMLTextFormControlElement* textControl = toRenderTextControl(m_renderer)->textFormControlElement();
   1740         return textControl->indexForVisiblePosition(pos);
   1741     }
   1742 
   1743     if (!isTextControl())
   1744         return 0;
   1745 
   1746     Node* node = m_renderer->node();
   1747     if (!node)
   1748         return 0;
   1749 
   1750     Position indexPosition = pos.deepEquivalent();
   1751     if (indexPosition.isNull() || highestEditableRoot(indexPosition, HasEditableAXRole) != node)
   1752         return 0;
   1753 
   1754     RefPtrWillBeRawPtr<Range> range = Range::create(m_renderer->document());
   1755     range->setStart(node, 0, IGNORE_EXCEPTION);
   1756     range->setEnd(indexPosition, IGNORE_EXCEPTION);
   1757 
   1758     return TextIterator::rangeLength(range.get());
   1759 }
   1760 
   1761 void AXRenderObject::addInlineTextBoxChildren()
   1762 {
   1763     if (!axObjectCache()->inlineTextBoxAccessibility())
   1764         return;
   1765 
   1766     if (!renderer() || !renderer()->isText())
   1767         return;
   1768 
   1769     if (renderer()->needsLayout()) {
   1770         // If a RenderText needs layout, its inline text boxes are either
   1771         // nonexistent or invalid, so defer until the layout happens and
   1772         // the renderer calls AXObjectCache::inlineTextBoxesUpdated.
   1773         return;
   1774     }
   1775 
   1776     RenderText* renderText = toRenderText(renderer());
   1777     for (RefPtr<AbstractInlineTextBox> box = renderText->firstAbstractInlineTextBox(); box.get(); box = box->nextInlineTextBox()) {
   1778         AXObject* axObject = axObjectCache()->getOrCreate(box.get());
   1779         if (!axObject->accessibilityIsIgnored())
   1780             m_children.append(axObject);
   1781     }
   1782 }
   1783 
   1784 void AXRenderObject::lineBreaks(Vector<int>& lineBreaks) const
   1785 {
   1786     if (!isTextControl())
   1787         return;
   1788 
   1789     VisiblePosition visiblePos = visiblePositionForIndex(0);
   1790     VisiblePosition savedVisiblePos = visiblePos;
   1791     visiblePos = nextLinePosition(visiblePos, 0);
   1792     while (!visiblePos.isNull() && visiblePos != savedVisiblePos) {
   1793         lineBreaks.append(indexForVisiblePosition(visiblePos));
   1794         savedVisiblePos = visiblePos;
   1795         visiblePos = nextLinePosition(visiblePos, 0);
   1796     }
   1797 }
   1798 
   1799 //
   1800 // Private.
   1801 //
   1802 
   1803 bool AXRenderObject::isAllowedChildOfTree() const
   1804 {
   1805     // Determine if this is in a tree. If so, we apply special behavior to make it work like an AXOutline.
   1806     AXObject* axObj = parentObject();
   1807     bool isInTree = false;
   1808     while (axObj) {
   1809         if (axObj->isTree()) {
   1810             isInTree = true;
   1811             break;
   1812         }
   1813         axObj = axObj->parentObject();
   1814     }
   1815 
   1816     // If the object is in a tree, only tree items should be exposed (and the children of tree items).
   1817     if (isInTree) {
   1818         AccessibilityRole role = roleValue();
   1819         if (role != TreeItemRole && role != StaticTextRole)
   1820             return false;
   1821     }
   1822     return true;
   1823 }
   1824 
   1825 void AXRenderObject::ariaListboxSelectedChildren(AccessibilityChildrenVector& result)
   1826 {
   1827     bool isMulti = isMultiSelectable();
   1828 
   1829     AccessibilityChildrenVector childObjects = children();
   1830     unsigned childrenSize = childObjects.size();
   1831     for (unsigned k = 0; k < childrenSize; ++k) {
   1832         // Every child should have aria-role option, and if so, check for selected attribute/state.
   1833         AXObject* child = childObjects[k].get();
   1834         if (child->isSelected() && child->ariaRoleAttribute() == ListBoxOptionRole) {
   1835             result.append(child);
   1836             if (!isMulti)
   1837                 return;
   1838         }
   1839     }
   1840 }
   1841 
   1842 AXObject::PlainTextRange AXRenderObject::ariaSelectedTextRange() const
   1843 {
   1844     Node* node = m_renderer->node();
   1845     if (!node)
   1846         return PlainTextRange();
   1847 
   1848     VisibleSelection visibleSelection = selection();
   1849     RefPtrWillBeRawPtr<Range> currentSelectionRange = visibleSelection.toNormalizedRange();
   1850     if (!currentSelectionRange || !currentSelectionRange->intersectsNode(node, IGNORE_EXCEPTION))
   1851         return PlainTextRange();
   1852 
   1853     int start = indexForVisiblePosition(visibleSelection.visibleStart());
   1854     int end = indexForVisiblePosition(visibleSelection.visibleEnd());
   1855 
   1856     return PlainTextRange(start, end - start);
   1857 }
   1858 
   1859 bool AXRenderObject::nodeIsTextControl(const Node* node) const
   1860 {
   1861     if (!node)
   1862         return false;
   1863 
   1864     const AXObject* axObjectForNode = axObjectCache()->getOrCreate(const_cast<Node*>(node));
   1865     if (!axObjectForNode)
   1866         return false;
   1867 
   1868     return axObjectForNode->isTextControl();
   1869 }
   1870 
   1871 bool AXRenderObject::isTabItemSelected() const
   1872 {
   1873     if (!isTabItem() || !m_renderer)
   1874         return false;
   1875 
   1876     Node* node = m_renderer->node();
   1877     if (!node || !node->isElementNode())
   1878         return false;
   1879 
   1880     // The ARIA spec says a tab item can also be selected if it is aria-labeled by a tabpanel
   1881     // that has keyboard focus inside of it, or if a tabpanel in its aria-controls list has KB
   1882     // focus inside of it.
   1883     AXObject* focusedElement = focusedUIElement();
   1884     if (!focusedElement)
   1885         return false;
   1886 
   1887     Vector<Element*> elements;
   1888     elementsFromAttribute(elements, aria_controlsAttr);
   1889 
   1890     unsigned count = elements.size();
   1891     for (unsigned k = 0; k < count; ++k) {
   1892         Element* element = elements[k];
   1893         AXObject* tabPanel = axObjectCache()->getOrCreate(element);
   1894 
   1895         // A tab item should only control tab panels.
   1896         if (!tabPanel || tabPanel->roleValue() != TabPanelRole)
   1897             continue;
   1898 
   1899         AXObject* checkFocusElement = focusedElement;
   1900         // Check if the focused element is a descendant of the element controlled by the tab item.
   1901         while (checkFocusElement) {
   1902             if (tabPanel == checkFocusElement)
   1903                 return true;
   1904             checkFocusElement = checkFocusElement->parentObject();
   1905         }
   1906     }
   1907 
   1908     return false;
   1909 }
   1910 
   1911 AXObject* AXRenderObject::accessibilityImageMapHitTest(HTMLAreaElement* area, const IntPoint& point) const
   1912 {
   1913     if (!area)
   1914         return 0;
   1915 
   1916     AXObject* parent = axObjectCache()->getOrCreate(area->imageElement());
   1917     if (!parent)
   1918         return 0;
   1919 
   1920     AXObject::AccessibilityChildrenVector children = parent->children();
   1921     unsigned count = children.size();
   1922     for (unsigned k = 0; k < count; ++k) {
   1923         if (children[k]->elementRect().contains(point))
   1924             return children[k].get();
   1925     }
   1926 
   1927     return 0;
   1928 }
   1929 
   1930 bool AXRenderObject::renderObjectIsObservable(RenderObject* renderer) const
   1931 {
   1932     // AX clients will listen for AXValueChange on a text control.
   1933     if (renderer->isTextControl())
   1934         return true;
   1935 
   1936     // AX clients will listen for AXSelectedChildrenChanged on listboxes.
   1937     Node* node = renderer->node();
   1938     if (nodeHasRole(node, "listbox") || (renderer->isBoxModelObject() && toRenderBoxModelObject(renderer)->isListBox()))
   1939         return true;
   1940 
   1941     // Textboxes should send out notifications.
   1942     if (nodeHasRole(node, "textbox"))
   1943         return true;
   1944 
   1945     return false;
   1946 }
   1947 
   1948 RenderObject* AXRenderObject::renderParentObject() const
   1949 {
   1950     if (!m_renderer)
   1951         return 0;
   1952 
   1953     RenderObject* parent = m_renderer->parent();
   1954 
   1955     RenderObject* startOfConts = 0;
   1956     RenderObject* firstChild = 0;
   1957     if (m_renderer->isRenderBlock() && (startOfConts = startOfContinuations(m_renderer))) {
   1958         // Case 1: node is a block and is an inline's continuation. Parent
   1959         // is the start of the continuation chain.
   1960         parent = startOfConts;
   1961     } else if (parent && parent->isRenderInline() && (startOfConts = startOfContinuations(parent))) {
   1962         // Case 2: node's parent is an inline which is some node's continuation; parent is
   1963         // the earliest node in the continuation chain.
   1964         parent = startOfConts;
   1965     } else if (parent && (firstChild = parent->slowFirstChild()) && firstChild->node()) {
   1966         // Case 3: The first sibling is the beginning of a continuation chain. Find the origin of that continuation.
   1967         // Get the node's renderer and follow that continuation chain until the first child is found.
   1968         RenderObject* nodeRenderFirstChild = firstChild->node()->renderer();
   1969         while (nodeRenderFirstChild != firstChild) {
   1970             for (RenderObject* contsTest = nodeRenderFirstChild; contsTest; contsTest = nextContinuation(contsTest)) {
   1971                 if (contsTest == firstChild) {
   1972                     parent = nodeRenderFirstChild->parent();
   1973                     break;
   1974                 }
   1975             }
   1976             RenderObject* newFirstChild = parent->slowFirstChild();
   1977             if (firstChild == newFirstChild)
   1978                 break;
   1979             firstChild = newFirstChild;
   1980             if (!firstChild->node())
   1981                 break;
   1982             nodeRenderFirstChild = firstChild->node()->renderer();
   1983         }
   1984     }
   1985 
   1986     return parent;
   1987 }
   1988 
   1989 bool AXRenderObject::isDescendantOfElementType(const QualifiedName& tagName) const
   1990 {
   1991     for (RenderObject* parent = m_renderer->parent(); parent; parent = parent->parent()) {
   1992         if (parent->node() && parent->node()->hasTagName(tagName))
   1993             return true;
   1994     }
   1995     return false;
   1996 }
   1997 
   1998 bool AXRenderObject::isSVGImage() const
   1999 {
   2000     return remoteSVGRootElement();
   2001 }
   2002 
   2003 void AXRenderObject::detachRemoteSVGRoot()
   2004 {
   2005     if (AXSVGRoot* root = remoteSVGRootElement())
   2006         root->setParent(0);
   2007 }
   2008 
   2009 AXSVGRoot* AXRenderObject::remoteSVGRootElement() const
   2010 {
   2011     if (!m_renderer || !m_renderer->isRenderImage())
   2012         return 0;
   2013 
   2014     ImageResource* cachedImage = toRenderImage(m_renderer)->cachedImage();
   2015     if (!cachedImage)
   2016         return 0;
   2017 
   2018     Image* image = cachedImage->image();
   2019     if (!image || !image->isSVGImage())
   2020         return 0;
   2021 
   2022     FrameView* frameView = toSVGImage(image)->frameView();
   2023     if (!frameView)
   2024         return 0;
   2025     Document* doc = frameView->frame().document();
   2026     if (!doc || !doc->isSVGDocument())
   2027         return 0;
   2028 
   2029     SVGSVGElement* rootElement = doc->accessSVGExtensions().rootElement();
   2030     if (!rootElement)
   2031         return 0;
   2032     RenderObject* rendererRoot = rootElement->renderer();
   2033     if (!rendererRoot)
   2034         return 0;
   2035 
   2036     AXObject* rootSVGObject = doc->axObjectCache()->getOrCreate(rendererRoot);
   2037 
   2038     // In order to connect the AX hierarchy from the SVG root element from the loaded resource
   2039     // the parent must be set, because there's no other way to get back to who created the image.
   2040     ASSERT(rootSVGObject && rootSVGObject->isAXSVGRoot());
   2041     if (!rootSVGObject->isAXSVGRoot())
   2042         return 0;
   2043 
   2044     return toAXSVGRoot(rootSVGObject);
   2045 }
   2046 
   2047 AXObject* AXRenderObject::remoteSVGElementHitTest(const IntPoint& point) const
   2048 {
   2049     AXObject* remote = remoteSVGRootElement();
   2050     if (!remote)
   2051         return 0;
   2052 
   2053     IntSize offset = point - roundedIntPoint(elementRect().location());
   2054     return remote->accessibilityHitTest(IntPoint(offset));
   2055 }
   2056 
   2057 // The boundingBox for elements within the remote SVG element needs to be offset by its position
   2058 // within the parent page, otherwise they are in relative coordinates only.
   2059 void AXRenderObject::offsetBoundingBoxForRemoteSVGElement(LayoutRect& rect) const
   2060 {
   2061     for (AXObject* parent = parentObject(); parent; parent = parent->parentObject()) {
   2062         if (parent->isAXSVGRoot()) {
   2063             rect.moveBy(parent->parentObject()->elementRect().location());
   2064             break;
   2065         }
   2066     }
   2067 }
   2068 
   2069 // Hidden children are those that are not rendered or visible, but are specifically marked as aria-hidden=false,
   2070 // meaning that they should be exposed to the AX hierarchy.
   2071 void AXRenderObject::addHiddenChildren()
   2072 {
   2073     Node* node = this->node();
   2074     if (!node)
   2075         return;
   2076 
   2077     // First do a quick run through to determine if we have any hidden nodes (most often we will not).
   2078     // If we do have hidden nodes, we need to determine where to insert them so they match DOM order as close as possible.
   2079     bool shouldInsertHiddenNodes = false;
   2080     for (Node* child = node->firstChild(); child; child = child->nextSibling()) {
   2081         if (!child->renderer() && isNodeAriaVisible(child)) {
   2082             shouldInsertHiddenNodes = true;
   2083             break;
   2084         }
   2085     }
   2086 
   2087     if (!shouldInsertHiddenNodes)
   2088         return;
   2089 
   2090     // Iterate through all of the children, including those that may have already been added, and
   2091     // try to insert hidden nodes in the correct place in the DOM order.
   2092     unsigned insertionIndex = 0;
   2093     for (Node* child = node->firstChild(); child; child = child->nextSibling()) {
   2094         if (child->renderer()) {
   2095             // Find out where the last render sibling is located within m_children.
   2096             AXObject* childObject = axObjectCache()->get(child->renderer());
   2097             if (childObject && childObject->accessibilityIsIgnored()) {
   2098                 AccessibilityChildrenVector children = childObject->children();
   2099                 if (children.size())
   2100                     childObject = children.last().get();
   2101                 else
   2102                     childObject = 0;
   2103             }
   2104 
   2105             if (childObject)
   2106                 insertionIndex = m_children.find(childObject) + 1;
   2107             continue;
   2108         }
   2109 
   2110         if (!isNodeAriaVisible(child))
   2111             continue;
   2112 
   2113         unsigned previousSize = m_children.size();
   2114         if (insertionIndex > previousSize)
   2115             insertionIndex = previousSize;
   2116 
   2117         insertChild(axObjectCache()->getOrCreate(child), insertionIndex);
   2118         insertionIndex += (m_children.size() - previousSize);
   2119     }
   2120 }
   2121 
   2122 void AXRenderObject::addTextFieldChildren()
   2123 {
   2124     Node* node = this->node();
   2125     if (!isHTMLInputElement(node))
   2126         return;
   2127 
   2128     HTMLInputElement& input = toHTMLInputElement(*node);
   2129     Element* spinButtonElement = input.userAgentShadowRoot()->getElementById(ShadowElementNames::spinButton());
   2130     if (!spinButtonElement || !spinButtonElement->isSpinButtonElement())
   2131         return;
   2132 
   2133     AXSpinButton* axSpinButton = toAXSpinButton(axObjectCache()->getOrCreate(SpinButtonRole));
   2134     axSpinButton->setSpinButtonElement(toSpinButtonElement(spinButtonElement));
   2135     axSpinButton->setParent(this);
   2136     m_children.append(axSpinButton);
   2137 }
   2138 
   2139 void AXRenderObject::addImageMapChildren()
   2140 {
   2141     RenderBoxModelObject* cssBox = renderBoxModelObject();
   2142     if (!cssBox || !cssBox->isRenderImage())
   2143         return;
   2144 
   2145     HTMLMapElement* map = toRenderImage(cssBox)->imageMap();
   2146     if (!map)
   2147         return;
   2148 
   2149     for (HTMLAreaElement* area = Traversal<HTMLAreaElement>::firstWithin(*map); area; area = Traversal<HTMLAreaElement>::next(*area, map)) {
   2150         // add an <area> element for this child if it has a link
   2151         if (area->isLink()) {
   2152             AXImageMapLink* areaObject = toAXImageMapLink(axObjectCache()->getOrCreate(ImageMapLinkRole));
   2153             areaObject->setHTMLAreaElement(area);
   2154             areaObject->setHTMLMapElement(map);
   2155             areaObject->setParent(this);
   2156             if (!areaObject->accessibilityIsIgnored())
   2157                 m_children.append(areaObject);
   2158             else
   2159                 axObjectCache()->remove(areaObject->axObjectID());
   2160         }
   2161     }
   2162 }
   2163 
   2164 void AXRenderObject::addCanvasChildren()
   2165 {
   2166     if (!isHTMLCanvasElement(node()))
   2167         return;
   2168 
   2169     // If it's a canvas, it won't have rendered children, but it might have accessible fallback content.
   2170     // Clear m_haveChildren because AXNodeObject::addChildren will expect it to be false.
   2171     ASSERT(!m_children.size());
   2172     m_haveChildren = false;
   2173     AXNodeObject::addChildren();
   2174 }
   2175 
   2176 void AXRenderObject::addAttachmentChildren()
   2177 {
   2178     if (!isAttachment())
   2179         return;
   2180 
   2181     // FrameView's need to be inserted into the AX hierarchy when encountered.
   2182     Widget* widget = widgetForAttachmentView();
   2183     if (!widget || !widget->isFrameView())
   2184         return;
   2185 
   2186     AXObject* axWidget = axObjectCache()->getOrCreate(widget);
   2187     if (!axWidget->accessibilityIsIgnored())
   2188         m_children.append(axWidget);
   2189 }
   2190 
   2191 void AXRenderObject::addRemoteSVGChildren()
   2192 {
   2193     AXSVGRoot* root = remoteSVGRootElement();
   2194     if (!root)
   2195         return;
   2196 
   2197     root->setParent(this);
   2198 
   2199     if (root->accessibilityIsIgnored()) {
   2200         AccessibilityChildrenVector children = root->children();
   2201         unsigned length = children.size();
   2202         for (unsigned i = 0; i < length; ++i)
   2203             m_children.append(children[i]);
   2204     } else {
   2205         m_children.append(root);
   2206     }
   2207 }
   2208 
   2209 void AXRenderObject::ariaSelectedRows(AccessibilityChildrenVector& result)
   2210 {
   2211     // Get all the rows.
   2212     AccessibilityChildrenVector allRows;
   2213     if (isTree())
   2214         ariaTreeRows(allRows);
   2215     else if (isAXTable() && toAXTable(this)->supportsSelectedRows())
   2216         allRows = toAXTable(this)->rows();
   2217 
   2218     // Determine which rows are selected.
   2219     bool isMulti = isMultiSelectable();
   2220 
   2221     // Prefer active descendant over aria-selected.
   2222     AXObject* activeDesc = activeDescendant();
   2223     if (activeDesc && (activeDesc->isTreeItem() || activeDesc->isTableRow())) {
   2224         result.append(activeDesc);
   2225         if (!isMulti)
   2226             return;
   2227     }
   2228 
   2229     unsigned count = allRows.size();
   2230     for (unsigned k = 0; k < count; ++k) {
   2231         if (allRows[k]->isSelected()) {
   2232             result.append(allRows[k]);
   2233             if (!isMulti)
   2234                 break;
   2235         }
   2236     }
   2237 }
   2238 
   2239 bool AXRenderObject::elementAttributeValue(const QualifiedName& attributeName) const
   2240 {
   2241     if (!m_renderer)
   2242         return false;
   2243 
   2244     return equalIgnoringCase(getAttribute(attributeName), "true");
   2245 }
   2246 
   2247 bool AXRenderObject::inheritsPresentationalRole() const
   2248 {
   2249     // ARIA states if an item can get focus, it should not be presentational.
   2250     if (canSetFocusAttribute())
   2251         return false;
   2252 
   2253     // ARIA spec says that when a parent object is presentational, and it has required child elements,
   2254     // those child elements are also presentational. For example, <li> becomes presentational from <ul>.
   2255     // http://www.w3.org/WAI/PF/aria/complete#presentation
   2256     if (roleValue() != ListItemRole && roleValue() != ListMarkerRole)
   2257         return false;
   2258 
   2259     AXObject* parent = parentObject();
   2260     if (!parent->isAXRenderObject())
   2261         return false;
   2262 
   2263     Node* elementNode = toAXRenderObject(parent)->node();
   2264     if (!elementNode || !elementNode->isElementNode())
   2265         return false;
   2266 
   2267     QualifiedName tagName = toElement(elementNode)->tagQName();
   2268     if (tagName == ulTag || tagName == olTag || tagName == dlTag)
   2269         return parent->roleValue() == PresentationalRole;
   2270 
   2271     return false;
   2272 }
   2273 
   2274 LayoutRect AXRenderObject::computeElementRect() const
   2275 {
   2276     RenderObject* obj = m_renderer;
   2277 
   2278     if (!obj)
   2279         return LayoutRect();
   2280 
   2281     if (obj->node()) // If we are a continuation, we want to make sure to use the primary renderer.
   2282         obj = obj->node()->renderer();
   2283 
   2284     // absoluteFocusRingQuads will query the hierarchy below this element, which for large webpages can be very slow.
   2285     // For a web area, which will have the most elements of any element, absoluteQuads should be used.
   2286     // We should also use absoluteQuads for SVG elements, otherwise transforms won't be applied.
   2287     Vector<FloatQuad> quads;
   2288 
   2289     if (obj->isText())
   2290         toRenderText(obj)->absoluteQuads(quads, 0, RenderText::ClipToEllipsis);
   2291     else if (isWebArea() || obj->isSVGRoot())
   2292         obj->absoluteQuads(quads);
   2293     else
   2294         obj->absoluteFocusRingQuads(quads);
   2295 
   2296     LayoutRect result = boundingBoxForQuads(obj, quads);
   2297 
   2298     Document* document = this->document();
   2299     if (document && document->isSVGDocument())
   2300         offsetBoundingBoxForRemoteSVGElement(result);
   2301 
   2302     // The size of the web area should be the content size, not the clipped size.
   2303     if (isWebArea() && obj->frame()->view())
   2304         result.setSize(obj->frame()->view()->contentsSize());
   2305 
   2306     // Checkboxes and radio buttons include their label as part of their rect.
   2307     if (isCheckboxOrRadio()) {
   2308         HTMLLabelElement* label = labelForElement(toElement(m_renderer->node()));
   2309         if (label && label->renderer()) {
   2310             LayoutRect labelRect = axObjectCache()->getOrCreate(label)->elementRect();
   2311             result.unite(labelRect);
   2312         }
   2313     }
   2314 
   2315     return result;
   2316 }
   2317 
   2318 } // namespace WebCore
   2319