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