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