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 "AccessibilityRenderObject.h"
     31 
     32 #include "AXObjectCache.h"
     33 #include "AccessibilityImageMapLink.h"
     34 #include "AccessibilityListBox.h"
     35 #include "EventNames.h"
     36 #include "FloatRect.h"
     37 #include "Frame.h"
     38 #include "FrameLoader.h"
     39 #include "HTMLAreaElement.h"
     40 #include "HTMLFormElement.h"
     41 #include "HTMLFrameElementBase.h"
     42 #include "HTMLImageElement.h"
     43 #include "HTMLInputElement.h"
     44 #include "HTMLLabelElement.h"
     45 #include "HTMLMapElement.h"
     46 #include "HTMLOptGroupElement.h"
     47 #include "HTMLOptionElement.h"
     48 #include "HTMLOptionsCollection.h"
     49 #include "HTMLSelectElement.h"
     50 #include "HTMLTextAreaElement.h"
     51 #include "HitTestRequest.h"
     52 #include "HitTestResult.h"
     53 #include "LocalizedStrings.h"
     54 #include "MathMLNames.h"
     55 #include "NodeList.h"
     56 #include "ProgressTracker.h"
     57 #include "RenderButton.h"
     58 #include "RenderFieldset.h"
     59 #include "RenderFileUploadControl.h"
     60 #include "RenderHTMLCanvas.h"
     61 #include "RenderImage.h"
     62 #include "RenderInline.h"
     63 #include "RenderLayer.h"
     64 #include "RenderListBox.h"
     65 #include "RenderListMarker.h"
     66 #include "RenderMenuList.h"
     67 #include "RenderText.h"
     68 #include "RenderTextControl.h"
     69 #include "RenderTextFragment.h"
     70 #include "RenderTheme.h"
     71 #include "RenderView.h"
     72 #include "RenderWidget.h"
     73 #include "SelectElement.h"
     74 #include "SelectionController.h"
     75 #include "Text.h"
     76 #include "TextIterator.h"
     77 #include "htmlediting.h"
     78 #include "visible_units.h"
     79 #include <wtf/StdLibExtras.h>
     80 #include <wtf/text/StringBuilder.h>
     81 #include <wtf/unicode/CharacterNames.h>
     82 
     83 using namespace std;
     84 
     85 namespace WebCore {
     86 
     87 using namespace HTMLNames;
     88 
     89 AccessibilityRenderObject::AccessibilityRenderObject(RenderObject* renderer)
     90     : AccessibilityObject()
     91     , m_renderer(renderer)
     92     , m_ariaRole(UnknownRole)
     93     , m_childrenDirty(false)
     94     , m_roleForMSAA(UnknownRole)
     95 {
     96     m_role = determineAccessibilityRole();
     97 
     98 #ifndef NDEBUG
     99     m_renderer->setHasAXObject(true);
    100 #endif
    101 }
    102 
    103 AccessibilityRenderObject::~AccessibilityRenderObject()
    104 {
    105     ASSERT(isDetached());
    106 }
    107 
    108 PassRefPtr<AccessibilityRenderObject> AccessibilityRenderObject::create(RenderObject* renderer)
    109 {
    110     return adoptRef(new AccessibilityRenderObject(renderer));
    111 }
    112 
    113 void AccessibilityRenderObject::detach()
    114 {
    115     clearChildren();
    116     AccessibilityObject::detach();
    117 
    118 #ifndef NDEBUG
    119     if (m_renderer)
    120         m_renderer->setHasAXObject(false);
    121 #endif
    122     m_renderer = 0;
    123 }
    124 
    125 RenderBoxModelObject* AccessibilityRenderObject::renderBoxModelObject() const
    126 {
    127     if (!m_renderer || !m_renderer->isBoxModelObject())
    128         return 0;
    129     return toRenderBoxModelObject(m_renderer);
    130 }
    131 
    132 static inline bool isInlineWithContinuation(RenderObject* object)
    133 {
    134     if (!object->isBoxModelObject())
    135         return false;
    136 
    137     RenderBoxModelObject* renderer = toRenderBoxModelObject(object);
    138     if (!renderer->isRenderInline())
    139         return false;
    140 
    141     return toRenderInline(renderer)->continuation();
    142 }
    143 
    144 static inline RenderObject* firstChildInContinuation(RenderObject* renderer)
    145 {
    146     RenderObject* r = toRenderInline(renderer)->continuation();
    147 
    148     while (r) {
    149         if (r->isRenderBlock())
    150             return r;
    151         if (RenderObject* child = r->firstChild())
    152             return child;
    153         r = toRenderInline(r)->continuation();
    154     }
    155 
    156     return 0;
    157 }
    158 
    159 static inline RenderObject* firstChildConsideringContinuation(RenderObject* renderer)
    160 {
    161     RenderObject* firstChild = renderer->firstChild();
    162 
    163     if (!firstChild && isInlineWithContinuation(renderer))
    164         firstChild = firstChildInContinuation(renderer);
    165 
    166     return firstChild;
    167 }
    168 
    169 
    170 static inline RenderObject* lastChildConsideringContinuation(RenderObject* renderer)
    171 {
    172     RenderObject* lastChild = renderer->lastChild();
    173     RenderObject* prev;
    174     RenderObject* cur = renderer;
    175 
    176     if (!cur->isRenderInline() && !cur->isRenderBlock())
    177         return renderer;
    178 
    179     while (cur) {
    180         prev = cur;
    181 
    182         if (RenderObject* lc = cur->lastChild())
    183             lastChild = lc;
    184 
    185         if (cur->isRenderInline()) {
    186             cur = toRenderInline(cur)->inlineElementContinuation();
    187             ASSERT(cur || !toRenderInline(prev)->continuation());
    188         } else
    189             cur = toRenderBlock(cur)->inlineElementContinuation();
    190     }
    191 
    192     return lastChild;
    193 }
    194 
    195 AccessibilityObject* AccessibilityRenderObject::firstChild() const
    196 {
    197     if (!m_renderer)
    198         return 0;
    199 
    200     RenderObject* firstChild = firstChildConsideringContinuation(m_renderer);
    201 
    202     if (!firstChild)
    203         return 0;
    204 
    205     return axObjectCache()->getOrCreate(firstChild);
    206 }
    207 
    208 AccessibilityObject* AccessibilityRenderObject::lastChild() const
    209 {
    210     if (!m_renderer)
    211         return 0;
    212 
    213     RenderObject* lastChild = lastChildConsideringContinuation(m_renderer);
    214 
    215     if (!lastChild)
    216         return 0;
    217 
    218     return axObjectCache()->getOrCreate(lastChild);
    219 }
    220 
    221 static inline RenderInline* startOfContinuations(RenderObject* r)
    222 {
    223     if (r->isInlineElementContinuation())
    224         return toRenderInline(r->node()->renderer());
    225 
    226     // Blocks with a previous continuation always have a next continuation
    227     if (r->isRenderBlock() && toRenderBlock(r)->inlineElementContinuation())
    228         return toRenderInline(toRenderBlock(r)->inlineElementContinuation()->node()->renderer());
    229 
    230     return 0;
    231 }
    232 
    233 static inline RenderObject* endOfContinuations(RenderObject* renderer)
    234 {
    235     RenderObject* prev = renderer;
    236     RenderObject* cur = renderer;
    237 
    238     if (!cur->isRenderInline() && !cur->isRenderBlock())
    239         return renderer;
    240 
    241     while (cur) {
    242         prev = cur;
    243         if (cur->isRenderInline()) {
    244             cur = toRenderInline(cur)->inlineElementContinuation();
    245             ASSERT(cur || !toRenderInline(prev)->continuation());
    246         } else
    247             cur = toRenderBlock(cur)->inlineElementContinuation();
    248     }
    249 
    250     return prev;
    251 }
    252 
    253 
    254 static inline RenderObject* childBeforeConsideringContinuations(RenderInline* r, RenderObject* child)
    255 {
    256     RenderBoxModelObject* curContainer = r;
    257     RenderObject* cur = 0;
    258     RenderObject* prev = 0;
    259 
    260     while (curContainer) {
    261         if (curContainer->isRenderInline()) {
    262             cur = curContainer->firstChild();
    263             while (cur) {
    264                 if (cur == child)
    265                     return prev;
    266                 prev = cur;
    267                 cur = cur->nextSibling();
    268             }
    269 
    270             curContainer = toRenderInline(curContainer)->continuation();
    271         } else if (curContainer->isRenderBlock()) {
    272             if (curContainer == child)
    273                 return prev;
    274 
    275             prev = curContainer;
    276             curContainer = toRenderBlock(curContainer)->inlineElementContinuation();
    277         }
    278     }
    279 
    280     ASSERT_NOT_REACHED();
    281 
    282     return 0;
    283 }
    284 
    285 static inline bool firstChildIsInlineContinuation(RenderObject* renderer)
    286 {
    287     return renderer->firstChild() && renderer->firstChild()->isInlineElementContinuation();
    288 }
    289 
    290 AccessibilityObject* AccessibilityRenderObject::previousSibling() const
    291 {
    292     if (!m_renderer)
    293         return 0;
    294 
    295     RenderObject* previousSibling = 0;
    296 
    297     // Case 1: The node is a block and is an inline's continuation. In that case, the inline's
    298     // last child is our previous sibling (or further back in the continuation chain)
    299     RenderInline* startOfConts;
    300     if (m_renderer->isRenderBlock() && (startOfConts = startOfContinuations(m_renderer)))
    301         previousSibling = childBeforeConsideringContinuations(startOfConts, m_renderer);
    302 
    303     // Case 2: Anonymous block parent of the end of a continuation - skip all the way to before
    304     // the parent of the start, since everything in between will be linked up via the continuation.
    305     else if (m_renderer->isAnonymousBlock() && firstChildIsInlineContinuation(m_renderer))
    306         previousSibling = startOfContinuations(m_renderer->firstChild())->parent()->previousSibling();
    307 
    308     // Case 3: The node has an actual previous sibling
    309     else if (RenderObject* ps = m_renderer->previousSibling())
    310         previousSibling = ps;
    311 
    312     // Case 4: This node has no previous siblings, but its parent is an inline,
    313     // and is another node's inline continutation. Follow the continuation chain.
    314     else if (m_renderer->parent()->isRenderInline() && (startOfConts = startOfContinuations(m_renderer->parent())))
    315         previousSibling = childBeforeConsideringContinuations(startOfConts, m_renderer->parent()->firstChild());
    316 
    317     if (!previousSibling)
    318         return 0;
    319 
    320     return axObjectCache()->getOrCreate(previousSibling);
    321 }
    322 
    323 static inline bool lastChildHasContinuation(RenderObject* renderer)
    324 {
    325     return renderer->lastChild() && isInlineWithContinuation(renderer->lastChild());
    326 }
    327 
    328 AccessibilityObject* AccessibilityRenderObject::nextSibling() const
    329 {
    330     if (!m_renderer)
    331         return 0;
    332 
    333     RenderObject* nextSibling = 0;
    334 
    335     // Case 1: node is a block and has an inline continuation. Next sibling is the inline continuation's
    336     // first child.
    337     RenderInline* inlineContinuation;
    338     if (m_renderer->isRenderBlock() && (inlineContinuation = toRenderBlock(m_renderer)->inlineElementContinuation()))
    339         nextSibling = firstChildConsideringContinuation(inlineContinuation);
    340 
    341     // Case 2: Anonymous block parent of the start of a continuation - skip all the way to
    342     // after the parent of the end, since everything in between will be linked up via the continuation.
    343     else if (m_renderer->isAnonymousBlock() && lastChildHasContinuation(m_renderer))
    344         nextSibling = endOfContinuations(m_renderer->lastChild())->parent()->nextSibling();
    345 
    346     // Case 3: node has an actual next sibling
    347     else if (RenderObject* ns = m_renderer->nextSibling())
    348         nextSibling = ns;
    349 
    350     // Case 4: node is an inline with a continuation. Next sibling is the next sibling of the end
    351     // of the continuation chain.
    352     else if (isInlineWithContinuation(m_renderer))
    353         nextSibling = endOfContinuations(m_renderer)->nextSibling();
    354 
    355     // Case 5: node has no next sibling, and its parent is an inline with a continuation.
    356     else if (isInlineWithContinuation(m_renderer->parent())) {
    357         RenderObject* continuation = toRenderInline(m_renderer->parent())->continuation();
    358 
    359         // Case 5a: continuation is a block - in this case the block itself is the next sibling.
    360         if (continuation->isRenderBlock())
    361             nextSibling = continuation;
    362         // Case 5b: continuation is an inline - in this case the inline's first child is the next sibling
    363         else
    364             nextSibling = firstChildConsideringContinuation(continuation);
    365     }
    366 
    367     if (!nextSibling)
    368         return 0;
    369 
    370     return axObjectCache()->getOrCreate(nextSibling);
    371 }
    372 
    373 static RenderBoxModelObject* nextContinuation(RenderObject* renderer)
    374 {
    375     ASSERT(renderer);
    376     if (renderer->isRenderInline() && !renderer->isReplaced())
    377         return toRenderInline(renderer)->continuation();
    378     if (renderer->isRenderBlock())
    379         return toRenderBlock(renderer)->inlineElementContinuation();
    380     return 0;
    381 }
    382 
    383 RenderObject* AccessibilityRenderObject::renderParentObject() const
    384 {
    385     if (!m_renderer)
    386         return 0;
    387 
    388     RenderObject* parent = m_renderer->parent();
    389 
    390     // Case 1: node is a block and is an inline's continuation. Parent
    391     // is the start of the continuation chain.
    392     RenderObject* startOfConts = 0;
    393     RenderObject* firstChild = 0;
    394     if (m_renderer->isRenderBlock() && (startOfConts = startOfContinuations(m_renderer)))
    395         parent = startOfConts;
    396 
    397     // Case 2: node's parent is an inline which is some node's continuation; parent is
    398     // the earliest node in the continuation chain.
    399     else if (parent && parent->isRenderInline() && (startOfConts = startOfContinuations(parent)))
    400         parent = startOfConts;
    401 
    402     // Case 3: The first sibling is the beginning of a continuation chain. Find the origin of that continuation.
    403     else if (parent && (firstChild = parent->firstChild()) && firstChild->node()) {
    404         // Get the node's renderer and follow that continuation chain until the first child is found
    405         RenderObject* nodeRenderFirstChild = firstChild->node()->renderer();
    406         if (nodeRenderFirstChild != firstChild) {
    407             for (RenderObject* contsTest = nodeRenderFirstChild; contsTest; contsTest = nextContinuation(contsTest)) {
    408                 if (contsTest == firstChild) {
    409                     parent = nodeRenderFirstChild->parent();
    410                     break;
    411                 }
    412             }
    413         }
    414     }
    415 
    416     return parent;
    417 }
    418 
    419 AccessibilityObject* AccessibilityRenderObject::parentObjectIfExists() const
    420 {
    421     return axObjectCache()->get(renderParentObject());
    422 }
    423 
    424 AccessibilityObject* AccessibilityRenderObject::parentObject() const
    425 {
    426     if (!m_renderer)
    427         return 0;
    428 
    429     if (ariaRoleAttribute() == MenuBarRole)
    430         return axObjectCache()->getOrCreate(m_renderer->parent());
    431 
    432     // menuButton and its corresponding menu are DOM siblings, but Accessibility needs them to be parent/child
    433     if (ariaRoleAttribute() == MenuRole) {
    434         AccessibilityObject* parent = menuButtonForMenu();
    435         if (parent)
    436             return parent;
    437     }
    438 
    439     RenderObject* parentObj = renderParentObject();
    440     if (parentObj)
    441         return axObjectCache()->getOrCreate(parentObj);
    442 
    443     // WebArea's parent should be the scroll view containing it.
    444     if (isWebArea())
    445         return axObjectCache()->getOrCreate(m_renderer->frame()->view());
    446 
    447     return 0;
    448 }
    449 
    450 bool AccessibilityRenderObject::isWebArea() const
    451 {
    452     return roleValue() == WebAreaRole;
    453 }
    454 
    455 bool AccessibilityRenderObject::isImageButton() const
    456 {
    457     return isNativeImage() && roleValue() == ButtonRole;
    458 }
    459 
    460 bool AccessibilityRenderObject::isAnchor() const
    461 {
    462     return !isNativeImage() && isLink();
    463 }
    464 
    465 bool AccessibilityRenderObject::isNativeTextControl() const
    466 {
    467     return m_renderer->isTextControl();
    468 }
    469 
    470 bool AccessibilityRenderObject::isNativeImage() const
    471 {
    472     return m_renderer->isBoxModelObject() && toRenderBoxModelObject(m_renderer)->isImage();
    473 }
    474 
    475 bool AccessibilityRenderObject::isImage() const
    476 {
    477     return roleValue() == ImageRole;
    478 }
    479 
    480 bool AccessibilityRenderObject::isAttachment() const
    481 {
    482     RenderBoxModelObject* renderer = renderBoxModelObject();
    483     if (!renderer)
    484         return false;
    485     // Widgets are the replaced elements that we represent to AX as attachments
    486     bool isWidget = renderer->isWidget();
    487     ASSERT(!isWidget || (renderer->isReplaced() && !isImage()));
    488     return isWidget && ariaRoleAttribute() == UnknownRole;
    489 }
    490 
    491 bool AccessibilityRenderObject::isPasswordField() const
    492 {
    493     ASSERT(m_renderer);
    494     if (!m_renderer->node() || !m_renderer->node()->isHTMLElement())
    495         return false;
    496     if (ariaRoleAttribute() != UnknownRole)
    497         return false;
    498 
    499     InputElement* inputElement = m_renderer->node()->toInputElement();
    500     if (!inputElement)
    501         return false;
    502 
    503     return inputElement->isPasswordField();
    504 }
    505 
    506 bool AccessibilityRenderObject::isFileUploadButton() const
    507 {
    508     if (m_renderer && m_renderer->node() && m_renderer->node()->hasTagName(inputTag)) {
    509         HTMLInputElement* input = static_cast<HTMLInputElement*>(m_renderer->node());
    510         return input->isFileUpload();
    511     }
    512 
    513     return false;
    514 }
    515 
    516 bool AccessibilityRenderObject::isInputImage() const
    517 {
    518     Node* elementNode = node();
    519     if (roleValue() == ButtonRole && elementNode && elementNode->hasTagName(inputTag)) {
    520         HTMLInputElement* input = static_cast<HTMLInputElement*>(elementNode);
    521         return input->isImageButton();
    522     }
    523 
    524     return false;
    525 }
    526 
    527 bool AccessibilityRenderObject::isProgressIndicator() const
    528 {
    529     return roleValue() == ProgressIndicatorRole;
    530 }
    531 
    532 bool AccessibilityRenderObject::isSlider() const
    533 {
    534     return roleValue() == SliderRole;
    535 }
    536 
    537 bool AccessibilityRenderObject::isMenuRelated() const
    538 {
    539     AccessibilityRole role = roleValue();
    540     return role == MenuRole
    541         || role == MenuBarRole
    542         || role == MenuButtonRole
    543         || role == MenuItemRole;
    544 }
    545 
    546 bool AccessibilityRenderObject::isMenu() const
    547 {
    548     return roleValue() == MenuRole;
    549 }
    550 
    551 bool AccessibilityRenderObject::isMenuBar() const
    552 {
    553     return roleValue() == MenuBarRole;
    554 }
    555 
    556 bool AccessibilityRenderObject::isMenuButton() const
    557 {
    558     return roleValue() == MenuButtonRole;
    559 }
    560 
    561 bool AccessibilityRenderObject::isMenuItem() const
    562 {
    563     return roleValue() == MenuItemRole;
    564 }
    565 
    566 bool AccessibilityRenderObject::isPressed() const
    567 {
    568     ASSERT(m_renderer);
    569     if (roleValue() != ButtonRole)
    570         return false;
    571 
    572     Node* node = m_renderer->node();
    573     if (!node)
    574         return false;
    575 
    576     // If this is an ARIA button, check the aria-pressed attribute rather than node()->active()
    577     if (ariaRoleAttribute() == ButtonRole) {
    578         if (equalIgnoringCase(getAttribute(aria_pressedAttr), "true"))
    579             return true;
    580         return false;
    581     }
    582 
    583     return node->active();
    584 }
    585 
    586 bool AccessibilityRenderObject::isIndeterminate() const
    587 {
    588     ASSERT(m_renderer);
    589     if (!m_renderer->node())
    590         return false;
    591 
    592     InputElement* inputElement = m_renderer->node()->toInputElement();
    593     if (!inputElement)
    594         return false;
    595 
    596     return inputElement->isIndeterminate();
    597 }
    598 
    599 bool AccessibilityRenderObject::isNativeCheckboxOrRadio() const
    600 {
    601     Node* elementNode = node();
    602     if (elementNode) {
    603         InputElement* input = elementNode->toInputElement();
    604         if (input)
    605             return input->isCheckbox() || input->isRadioButton();
    606     }
    607 
    608     return false;
    609 }
    610 
    611 bool AccessibilityRenderObject::isChecked() const
    612 {
    613     ASSERT(m_renderer);
    614     if (!m_renderer->node())
    615         return false;
    616 
    617     // First test for native checkedness semantics
    618     InputElement* inputElement = m_renderer->node()->toInputElement();
    619     if (inputElement)
    620         return inputElement->isChecked();
    621 
    622     // Else, if this is an ARIA checkbox or radio, respect the aria-checked attribute
    623     AccessibilityRole ariaRole = ariaRoleAttribute();
    624     if (ariaRole == RadioButtonRole || ariaRole == CheckBoxRole) {
    625         if (equalIgnoringCase(getAttribute(aria_checkedAttr), "true"))
    626             return true;
    627         return false;
    628     }
    629 
    630     // Otherwise it's not checked
    631     return false;
    632 }
    633 
    634 bool AccessibilityRenderObject::isHovered() const
    635 {
    636     ASSERT(m_renderer);
    637     return m_renderer->node() && m_renderer->node()->hovered();
    638 }
    639 
    640 bool AccessibilityRenderObject::isMultiSelectable() const
    641 {
    642     ASSERT(m_renderer);
    643 
    644     const AtomicString& ariaMultiSelectable = getAttribute(aria_multiselectableAttr);
    645     if (equalIgnoringCase(ariaMultiSelectable, "true"))
    646         return true;
    647     if (equalIgnoringCase(ariaMultiSelectable, "false"))
    648         return false;
    649 
    650     if (!m_renderer->isBoxModelObject() || !toRenderBoxModelObject(m_renderer)->isListBox())
    651         return false;
    652     return m_renderer->node() && static_cast<HTMLSelectElement*>(m_renderer->node())->multiple();
    653 }
    654 
    655 bool AccessibilityRenderObject::isReadOnly() const
    656 {
    657     ASSERT(m_renderer);
    658 
    659     if (isWebArea()) {
    660         Document* document = m_renderer->document();
    661         if (!document)
    662             return true;
    663 
    664         HTMLElement* body = document->body();
    665         if (body && body->isContentEditable())
    666             return false;
    667 
    668         return !document->rendererIsEditable();
    669     }
    670 
    671     if (m_renderer->isBoxModelObject()) {
    672         RenderBoxModelObject* box = toRenderBoxModelObject(m_renderer);
    673         if (box->isTextField())
    674             return static_cast<HTMLInputElement*>(box->node())->readOnly();
    675         if (box->isTextArea())
    676             return static_cast<HTMLTextAreaElement*>(box->node())->readOnly();
    677     }
    678 
    679     return !m_renderer->node() || !m_renderer->node()->rendererIsEditable();
    680 }
    681 
    682 bool AccessibilityRenderObject::isOffScreen() const
    683 {
    684     ASSERT(m_renderer);
    685     IntRect contentRect = m_renderer->absoluteClippedOverflowRect();
    686     FrameView* view = m_renderer->frame()->view();
    687     FloatRect viewRect = view->visibleContentRect();
    688     viewRect.intersect(contentRect);
    689     return viewRect.isEmpty();
    690 }
    691 
    692 int AccessibilityRenderObject::headingLevel() const
    693 {
    694     // headings can be in block flow and non-block flow
    695     Node* element = node();
    696     if (!element)
    697         return 0;
    698 
    699     if (ariaRoleAttribute() == HeadingRole)
    700         return getAttribute(aria_levelAttr).toInt();
    701 
    702     if (element->hasTagName(h1Tag))
    703         return 1;
    704 
    705     if (element->hasTagName(h2Tag))
    706         return 2;
    707 
    708     if (element->hasTagName(h3Tag))
    709         return 3;
    710 
    711     if (element->hasTagName(h4Tag))
    712         return 4;
    713 
    714     if (element->hasTagName(h5Tag))
    715         return 5;
    716 
    717     if (element->hasTagName(h6Tag))
    718         return 6;
    719 
    720     return 0;
    721 }
    722 
    723 bool AccessibilityRenderObject::isHeading() const
    724 {
    725     return roleValue() == HeadingRole;
    726 }
    727 
    728 bool AccessibilityRenderObject::isLink() const
    729 {
    730     return roleValue() == WebCoreLinkRole;
    731 }
    732 
    733 bool AccessibilityRenderObject::isControl() const
    734 {
    735     if (!m_renderer)
    736         return false;
    737 
    738     Node* node = m_renderer->node();
    739     return node && ((node->isElementNode() && static_cast<Element*>(node)->isFormControlElement())
    740                     || AccessibilityObject::isARIAControl(ariaRoleAttribute()));
    741 }
    742 
    743 bool AccessibilityRenderObject::isFieldset() const
    744 {
    745     RenderBoxModelObject* renderer = renderBoxModelObject();
    746     if (!renderer)
    747         return false;
    748     return renderer->isFieldset();
    749 }
    750 
    751 bool AccessibilityRenderObject::isGroup() const
    752 {
    753     return roleValue() == GroupRole;
    754 }
    755 
    756 AccessibilityObject* AccessibilityRenderObject::selectedRadioButton()
    757 {
    758     if (!isRadioGroup())
    759         return 0;
    760 
    761     // Find the child radio button that is selected (ie. the intValue == 1).
    762     int count = m_children.size();
    763     for (int i = 0; i < count; ++i) {
    764         AccessibilityObject* object = m_children[i].get();
    765         if (object->roleValue() == RadioButtonRole && object->checkboxOrRadioValue() == ButtonStateOn)
    766             return object;
    767     }
    768     return 0;
    769 }
    770 
    771 AccessibilityObject* AccessibilityRenderObject::selectedTabItem()
    772 {
    773     if (!isTabList())
    774         return 0;
    775 
    776     // Find the child tab item that is selected (ie. the intValue == 1).
    777     AccessibilityObject::AccessibilityChildrenVector tabs;
    778     tabChildren(tabs);
    779 
    780     int count = tabs.size();
    781     for (int i = 0; i < count; ++i) {
    782         AccessibilityObject* object = m_children[i].get();
    783         if (object->isTabItem() && object->isChecked())
    784             return object;
    785     }
    786     return 0;
    787 }
    788 
    789 Element* AccessibilityRenderObject::anchorElement() const
    790 {
    791     if (!m_renderer)
    792         return 0;
    793 
    794     AXObjectCache* cache = axObjectCache();
    795     RenderObject* currRenderer;
    796 
    797     // Search up the render tree for a RenderObject with a DOM node.  Defer to an earlier continuation, though.
    798     for (currRenderer = m_renderer; currRenderer && !currRenderer->node(); currRenderer = currRenderer->parent()) {
    799         if (currRenderer->isAnonymousBlock()) {
    800             RenderObject* continuation = toRenderBlock(currRenderer)->continuation();
    801             if (continuation)
    802                 return cache->getOrCreate(continuation)->anchorElement();
    803         }
    804     }
    805 
    806     // bail if none found
    807     if (!currRenderer)
    808         return 0;
    809 
    810     // search up the DOM tree for an anchor element
    811     // NOTE: this assumes that any non-image with an anchor is an HTMLAnchorElement
    812     Node* node = currRenderer->node();
    813     for ( ; node; node = node->parentNode()) {
    814         if (node->hasTagName(aTag) || (node->renderer() && cache->getOrCreate(node->renderer())->isAnchor()))
    815             return static_cast<Element*>(node);
    816     }
    817 
    818     return 0;
    819 }
    820 
    821 Element* AccessibilityRenderObject::actionElement() const
    822 {
    823     if (!m_renderer)
    824         return 0;
    825 
    826     Node* node = m_renderer->node();
    827     if (node) {
    828         if (node->hasTagName(inputTag)) {
    829             HTMLInputElement* input = static_cast<HTMLInputElement*>(node);
    830             if (!input->disabled() && (isCheckboxOrRadio() || input->isTextButton()))
    831                 return input;
    832         } else if (node->hasTagName(buttonTag))
    833             return static_cast<Element*>(node);
    834     }
    835 
    836     if (isFileUploadButton())
    837         return static_cast<Element*>(m_renderer->node());
    838 
    839     if (AccessibilityObject::isARIAInput(ariaRoleAttribute()))
    840         return static_cast<Element*>(m_renderer->node());
    841 
    842     if (isImageButton())
    843         return static_cast<Element*>(m_renderer->node());
    844 
    845     if (m_renderer->isBoxModelObject() && toRenderBoxModelObject(m_renderer)->isMenuList())
    846         return static_cast<Element*>(m_renderer->node());
    847 
    848     AccessibilityRole role = roleValue();
    849     if (role == ButtonRole || role == PopUpButtonRole)
    850         return static_cast<Element*>(m_renderer->node());
    851 
    852     Element* elt = anchorElement();
    853     if (!elt)
    854         elt = mouseButtonListener();
    855     return elt;
    856 }
    857 
    858 Element* AccessibilityRenderObject::mouseButtonListener() const
    859 {
    860     Node* node = m_renderer->node();
    861     if (!node)
    862         return 0;
    863 
    864     // check if our parent is a mouse button listener
    865     while (node && !node->isElementNode())
    866         node = node->parentNode();
    867 
    868     if (!node)
    869         return 0;
    870 
    871     // FIXME: Do the continuation search like anchorElement does
    872     for (Element* element = static_cast<Element*>(node); element; element = element->parentElement()) {
    873         if (element->getAttributeEventListener(eventNames().clickEvent) || element->getAttributeEventListener(eventNames().mousedownEvent) || element->getAttributeEventListener(eventNames().mouseupEvent))
    874             return element;
    875     }
    876 
    877     return 0;
    878 }
    879 
    880 void AccessibilityRenderObject::increment()
    881 {
    882     if (roleValue() != SliderRole)
    883         return;
    884 
    885     changeValueByPercent(5);
    886 }
    887 
    888 void AccessibilityRenderObject::decrement()
    889 {
    890     if (roleValue() != SliderRole)
    891         return;
    892 
    893     changeValueByPercent(-5);
    894 }
    895 
    896 static Element* siblingWithAriaRole(String role, Node* node)
    897 {
    898     Node* sibling = node->parentNode()->firstChild();
    899     while (sibling) {
    900         if (sibling->isElementNode()) {
    901             const AtomicString& siblingAriaRole = static_cast<Element*>(sibling)->getAttribute(roleAttr);
    902             if (equalIgnoringCase(siblingAriaRole, role))
    903                 return static_cast<Element*>(sibling);
    904         }
    905         sibling = sibling->nextSibling();
    906     }
    907 
    908     return 0;
    909 }
    910 
    911 Element* AccessibilityRenderObject::menuElementForMenuButton() const
    912 {
    913     if (ariaRoleAttribute() != MenuButtonRole)
    914         return 0;
    915 
    916     return siblingWithAriaRole("menu", renderer()->node());
    917 }
    918 
    919 AccessibilityObject* AccessibilityRenderObject::menuForMenuButton() const
    920 {
    921     Element* menu = menuElementForMenuButton();
    922     if (menu && menu->renderer())
    923         return axObjectCache()->getOrCreate(menu->renderer());
    924     return 0;
    925 }
    926 
    927 Element* AccessibilityRenderObject::menuItemElementForMenu() const
    928 {
    929     if (ariaRoleAttribute() != MenuRole)
    930         return 0;
    931 
    932     return siblingWithAriaRole("menuitem", renderer()->node());
    933 }
    934 
    935 AccessibilityObject* AccessibilityRenderObject::menuButtonForMenu() const
    936 {
    937     Element* menuItem = menuItemElementForMenu();
    938 
    939     if (menuItem && menuItem->renderer()) {
    940         // ARIA just has generic menu items.  AppKit needs to know if this is a top level items like MenuBarButton or MenuBarItem
    941         AccessibilityObject* menuItemAX = axObjectCache()->getOrCreate(menuItem->renderer());
    942         if (menuItemAX->isMenuButton())
    943             return menuItemAX;
    944     }
    945     return 0;
    946 }
    947 
    948 String AccessibilityRenderObject::helpText() const
    949 {
    950     if (!m_renderer)
    951         return String();
    952 
    953     const AtomicString& ariaHelp = getAttribute(aria_helpAttr);
    954     if (!ariaHelp.isEmpty())
    955         return ariaHelp;
    956 
    957     for (RenderObject* curr = m_renderer; curr; curr = curr->parent()) {
    958         if (curr->node() && curr->node()->isHTMLElement()) {
    959             const AtomicString& summary = static_cast<Element*>(curr->node())->getAttribute(summaryAttr);
    960             if (!summary.isEmpty())
    961                 return summary;
    962             const AtomicString& title = static_cast<Element*>(curr->node())->getAttribute(titleAttr);
    963             if (!title.isEmpty())
    964                 return title;
    965         }
    966 
    967         // Only take help text from an ancestor element if its a group or an unknown role. If help was
    968         // added to those kinds of elements, it is likely it was meant for a child element.
    969         AccessibilityObject* axObj = axObjectCache()->getOrCreate(curr);
    970         if (axObj) {
    971             AccessibilityRole role = axObj->roleValue();
    972             if (role != GroupRole && role != UnknownRole)
    973                 break;
    974         }
    975     }
    976 
    977     return String();
    978 }
    979 
    980 unsigned AccessibilityRenderObject::hierarchicalLevel() const
    981 {
    982     if (!m_renderer)
    983         return 0;
    984 
    985     Node* node = m_renderer->node();
    986     if (!node || !node->isElementNode())
    987         return 0;
    988     Element* element = static_cast<Element*>(node);
    989     String ariaLevel = element->getAttribute(aria_levelAttr);
    990     if (!ariaLevel.isEmpty())
    991         return ariaLevel.toInt();
    992 
    993     // Only tree item will calculate its level through the DOM currently.
    994     if (roleValue() != TreeItemRole)
    995         return 0;
    996 
    997     // Hierarchy leveling starts at 0.
    998     // We measure tree hierarchy by the number of groups that the item is within.
    999     unsigned level = 0;
   1000     AccessibilityObject* parent = parentObject();
   1001     while (parent) {
   1002         AccessibilityRole parentRole = parent->roleValue();
   1003         if (parentRole == GroupRole)
   1004             level++;
   1005         else if (parentRole == TreeRole)
   1006             break;
   1007 
   1008         parent = parent->parentObject();
   1009     }
   1010 
   1011     return level;
   1012 }
   1013 
   1014 static TextIteratorBehavior textIteratorBehaviorForTextRange()
   1015 {
   1016     TextIteratorBehavior behavior = TextIteratorIgnoresStyleVisibility;
   1017 
   1018 #if PLATFORM(GTK)
   1019     // We need to emit replaced elements for GTK, and present
   1020     // them with the 'object replacement character' (0xFFFC).
   1021     behavior = static_cast<TextIteratorBehavior>(behavior | TextIteratorEmitsObjectReplacementCharacters);
   1022 #endif
   1023 
   1024     return behavior;
   1025 }
   1026 
   1027 String AccessibilityRenderObject::textUnderElement() const
   1028 {
   1029     if (!m_renderer)
   1030         return String();
   1031 
   1032     if (isFileUploadButton())
   1033         return toRenderFileUploadControl(m_renderer)->buttonValue();
   1034 
   1035     Node* node = m_renderer->node();
   1036     if (node) {
   1037         if (Frame* frame = node->document()->frame()) {
   1038             // catch stale WebCoreAXObject (see <rdar://problem/3960196>)
   1039             if (frame->document() != node->document())
   1040                 return String();
   1041 
   1042             return plainText(rangeOfContents(node).get(), textIteratorBehaviorForTextRange());
   1043         }
   1044     }
   1045 
   1046     // Sometimes text fragments don't have Node's associated with them (like when
   1047     // CSS content is used to insert text).
   1048     if (m_renderer->isText()) {
   1049         RenderText* renderTextObject = toRenderText(m_renderer);
   1050         if (renderTextObject->isTextFragment())
   1051             return String(static_cast<RenderTextFragment*>(m_renderer)->contentString());
   1052     }
   1053 
   1054     // return the null string for anonymous text because it is non-trivial to get
   1055     // the actual text and, so far, that is not needed
   1056     return String();
   1057 }
   1058 
   1059 Node* AccessibilityRenderObject::node() const
   1060 {
   1061     return m_renderer ? m_renderer->node() : 0;
   1062 }
   1063 
   1064 AccessibilityButtonState AccessibilityRenderObject::checkboxOrRadioValue() const
   1065 {
   1066     if (isNativeCheckboxOrRadio())
   1067         return isChecked() ? ButtonStateOn : ButtonStateOff;
   1068 
   1069     return AccessibilityObject::checkboxOrRadioValue();
   1070 }
   1071 
   1072 String AccessibilityRenderObject::valueDescription() const
   1073 {
   1074     // Only sliders and progress bars support value descriptions currently.
   1075     if (!isProgressIndicator() && !isSlider())
   1076         return String();
   1077 
   1078     return getAttribute(aria_valuetextAttr).string();
   1079 }
   1080 
   1081 float AccessibilityRenderObject::valueForRange() const
   1082 {
   1083     if (!isProgressIndicator() && !isSlider() && !isScrollbar())
   1084         return 0.0f;
   1085 
   1086     return getAttribute(aria_valuenowAttr).toFloat();
   1087 }
   1088 
   1089 float AccessibilityRenderObject::maxValueForRange() const
   1090 {
   1091     if (!isProgressIndicator() && !isSlider())
   1092         return 0.0f;
   1093 
   1094     return getAttribute(aria_valuemaxAttr).toFloat();
   1095 }
   1096 
   1097 float AccessibilityRenderObject::minValueForRange() const
   1098 {
   1099     if (!isProgressIndicator() && !isSlider())
   1100         return 0.0f;
   1101 
   1102     return getAttribute(aria_valueminAttr).toFloat();
   1103 }
   1104 
   1105 String AccessibilityRenderObject::stringValue() const
   1106 {
   1107     if (!m_renderer || isPasswordField())
   1108         return String();
   1109 
   1110     RenderBoxModelObject* cssBox = renderBoxModelObject();
   1111 
   1112     if (ariaRoleAttribute() == StaticTextRole) {
   1113         String staticText = text();
   1114         if (!staticText.length())
   1115             staticText = textUnderElement();
   1116         return staticText;
   1117     }
   1118 
   1119     if (m_renderer->isText())
   1120         return textUnderElement();
   1121 
   1122     if (cssBox && cssBox->isMenuList()) {
   1123         // RenderMenuList will go straight to the text() of its selected item.
   1124         // This has to be overriden in the case where the selected item has an aria label
   1125         SelectElement* selectNode = toSelectElement(static_cast<Element*>(m_renderer->node()));
   1126         int selectedIndex = selectNode->selectedIndex();
   1127         const Vector<Element*> listItems = selectNode->listItems();
   1128 
   1129         Element* selectedOption = 0;
   1130         if (selectedIndex >= 0 && selectedIndex < (int)listItems.size())
   1131             selectedOption = listItems[selectedIndex];
   1132         if (selectedOption) {
   1133             String overridenDescription = selectedOption->getAttribute(aria_labelAttr);
   1134             if (!overridenDescription.isNull())
   1135                 return overridenDescription;
   1136         }
   1137 
   1138         return toRenderMenuList(m_renderer)->text();
   1139     }
   1140 
   1141     if (m_renderer->isListMarker())
   1142         return toRenderListMarker(m_renderer)->text();
   1143 
   1144     if (cssBox && cssBox->isRenderButton())
   1145         return toRenderButton(m_renderer)->text();
   1146 
   1147     if (isWebArea()) {
   1148         if (m_renderer->frame())
   1149             return String();
   1150 
   1151         // FIXME: should use startOfDocument and endOfDocument (or rangeForDocument?) here
   1152         VisiblePosition startVisiblePosition = m_renderer->positionForCoordinates(0, 0);
   1153         VisiblePosition endVisiblePosition = m_renderer->positionForCoordinates(INT_MAX, INT_MAX);
   1154         if (startVisiblePosition.isNull() || endVisiblePosition.isNull())
   1155             return String();
   1156 
   1157         return plainText(makeRange(startVisiblePosition, endVisiblePosition).get(),
   1158                          textIteratorBehaviorForTextRange());
   1159     }
   1160 
   1161     if (isTextControl())
   1162         return text();
   1163 
   1164     if (isFileUploadButton())
   1165         return toRenderFileUploadControl(m_renderer)->fileTextValue();
   1166 
   1167     // FIXME: We might need to implement a value here for more types
   1168     // FIXME: It would be better not to advertise a value at all for the types for which we don't implement one;
   1169     // this would require subclassing or making accessibilityAttributeNames do something other than return a
   1170     // single static array.
   1171     return String();
   1172 }
   1173 
   1174 // This function implements the ARIA accessible name as described by the Mozilla
   1175 // ARIA Implementer's Guide.
   1176 static String accessibleNameForNode(Node* node)
   1177 {
   1178     if (node->isTextNode())
   1179         return static_cast<Text*>(node)->data();
   1180 
   1181     if (node->hasTagName(inputTag))
   1182         return static_cast<HTMLInputElement*>(node)->value();
   1183 
   1184     if (node->isHTMLElement()) {
   1185         const AtomicString& alt = toHTMLElement(node)->getAttribute(altAttr);
   1186         if (!alt.isEmpty())
   1187             return alt;
   1188     }
   1189 
   1190     return String();
   1191 }
   1192 
   1193 String AccessibilityRenderObject::accessibilityDescriptionForElements(Vector<Element*> &elements) const
   1194 {
   1195     StringBuilder builder;
   1196     unsigned size = elements.size();
   1197     for (unsigned i = 0; i < size; ++i) {
   1198         Element* idElement = elements[i];
   1199 
   1200         builder.append(accessibleNameForNode(idElement));
   1201         for (Node* n = idElement->firstChild(); n; n = n->traverseNextNode(idElement))
   1202             builder.append(accessibleNameForNode(n));
   1203 
   1204         if (i != size - 1)
   1205             builder.append(' ');
   1206     }
   1207     return builder.toString();
   1208 }
   1209 
   1210 void AccessibilityRenderObject::elementsFromAttribute(Vector<Element*>& elements, const QualifiedName& attribute) const
   1211 {
   1212     Node* node = m_renderer->node();
   1213     if (!node || !node->isElementNode())
   1214         return;
   1215 
   1216     Document* document = m_renderer->document();
   1217     if (!document)
   1218         return;
   1219 
   1220     String idList = getAttribute(attribute).string();
   1221     if (idList.isEmpty())
   1222         return;
   1223 
   1224     idList.replace('\n', ' ');
   1225     Vector<String> idVector;
   1226     idList.split(' ', idVector);
   1227 
   1228     unsigned size = idVector.size();
   1229     for (unsigned i = 0; i < size; ++i) {
   1230         String idName = idVector[i];
   1231         Element* idElement = document->getElementById(idName);
   1232         if (idElement)
   1233             elements.append(idElement);
   1234     }
   1235 }
   1236 
   1237 void AccessibilityRenderObject::ariaLabeledByElements(Vector<Element*>& elements) const
   1238 {
   1239     elementsFromAttribute(elements, aria_labeledbyAttr);
   1240     if (!elements.size())
   1241         elementsFromAttribute(elements, aria_labelledbyAttr);
   1242 }
   1243 
   1244 String AccessibilityRenderObject::ariaLabeledByAttribute() const
   1245 {
   1246     Vector<Element*> elements;
   1247     ariaLabeledByElements(elements);
   1248 
   1249     return accessibilityDescriptionForElements(elements);
   1250 }
   1251 
   1252 static HTMLLabelElement* labelForElement(Element* element)
   1253 {
   1254     RefPtr<NodeList> list = element->document()->getElementsByTagName("label");
   1255     unsigned len = list->length();
   1256     for (unsigned i = 0; i < len; i++) {
   1257         if (list->item(i)->hasTagName(labelTag)) {
   1258             HTMLLabelElement* label = static_cast<HTMLLabelElement*>(list->item(i));
   1259             if (label->control() == element)
   1260                 return label;
   1261         }
   1262     }
   1263 
   1264     return 0;
   1265 }
   1266 
   1267 HTMLLabelElement* AccessibilityRenderObject::labelElementContainer() const
   1268 {
   1269     if (!m_renderer)
   1270         return 0;
   1271 
   1272     // the control element should not be considered part of the label
   1273     if (isControl())
   1274         return 0;
   1275 
   1276     // find if this has a parent that is a label
   1277     for (Node* parentNode = m_renderer->node(); parentNode; parentNode = parentNode->parentNode()) {
   1278         if (parentNode->hasTagName(labelTag))
   1279             return static_cast<HTMLLabelElement*>(parentNode);
   1280     }
   1281 
   1282     return 0;
   1283 }
   1284 
   1285 String AccessibilityRenderObject::title() const
   1286 {
   1287     AccessibilityRole ariaRole = ariaRoleAttribute();
   1288 
   1289     if (!m_renderer)
   1290         return String();
   1291 
   1292     Node* node = m_renderer->node();
   1293     if (!node)
   1294         return String();
   1295 
   1296     String ariaLabel = ariaLabeledByAttribute();
   1297     if (!ariaLabel.isEmpty())
   1298         return ariaLabel;
   1299 
   1300     const AtomicString& title = getAttribute(titleAttr);
   1301     if (!title.isEmpty())
   1302         return title;
   1303 
   1304     bool isInputTag = node->hasTagName(inputTag);
   1305     if (isInputTag) {
   1306         HTMLInputElement* input = static_cast<HTMLInputElement*>(node);
   1307         if (input->isTextButton())
   1308             return input->value();
   1309     }
   1310 
   1311     if (isInputTag || AccessibilityObject::isARIAInput(ariaRole) || isControl()) {
   1312         HTMLLabelElement* label = labelForElement(static_cast<Element*>(node));
   1313         if (label && !titleUIElement())
   1314             return label->innerText();
   1315     }
   1316 
   1317     if (roleValue() == ButtonRole
   1318         || ariaRole == ListBoxOptionRole
   1319         || ariaRole == MenuItemRole
   1320         || ariaRole == MenuButtonRole
   1321         || ariaRole == RadioButtonRole
   1322         || ariaRole == CheckBoxRole
   1323         || ariaRole == TabRole
   1324         || ariaRole == PopUpButtonRole
   1325         || isHeading()
   1326         || isLink())
   1327         return textUnderElement();
   1328 
   1329     return String();
   1330 }
   1331 
   1332 String AccessibilityRenderObject::ariaDescribedByAttribute() const
   1333 {
   1334     Vector<Element*> elements;
   1335     elementsFromAttribute(elements, aria_describedbyAttr);
   1336 
   1337     return accessibilityDescriptionForElements(elements);
   1338 }
   1339 
   1340 String AccessibilityRenderObject::ariaAccessibilityDescription() const
   1341 {
   1342     const AtomicString& ariaLabel = getAttribute(aria_labelAttr);
   1343     if (!ariaLabel.isEmpty())
   1344         return ariaLabel;
   1345 
   1346     String ariaDescription = ariaDescribedByAttribute();
   1347     if (!ariaDescription.isEmpty())
   1348         return ariaDescription;
   1349 
   1350     return String();
   1351 }
   1352 
   1353 String AccessibilityRenderObject::accessibilityDescription() const
   1354 {
   1355     if (!m_renderer)
   1356         return String();
   1357 
   1358     // Static text should not have a description, it should only have a stringValue.
   1359     if (roleValue() == StaticTextRole)
   1360         return String();
   1361 
   1362     String ariaDescription = ariaAccessibilityDescription();
   1363     if (!ariaDescription.isEmpty())
   1364         return ariaDescription;
   1365 
   1366     Node* node = m_renderer->node();
   1367     if (isImage() || isInputImage() || isNativeImage()) {
   1368         if (node && node->isHTMLElement()) {
   1369             const AtomicString& alt = toHTMLElement(node)->getAttribute(altAttr);
   1370             if (alt.isEmpty())
   1371                 return String();
   1372             return alt;
   1373         }
   1374     }
   1375 
   1376 #if ENABLE(MATHML)
   1377     if (node && node->isElementNode() && static_cast<Element*>(node)->isMathMLElement())
   1378         return getAttribute(MathMLNames::alttextAttr);
   1379 #endif
   1380 
   1381     if (isWebArea()) {
   1382         Document* document = m_renderer->document();
   1383 
   1384         // Check if the HTML element has an aria-label for the webpage.
   1385         Element* documentElement = document->documentElement();
   1386         if (documentElement) {
   1387             const AtomicString& ariaLabel = documentElement->getAttribute(aria_labelAttr);
   1388             if (!ariaLabel.isEmpty())
   1389                 return ariaLabel;
   1390         }
   1391 
   1392         Node* owner = document->ownerElement();
   1393         if (owner) {
   1394             if (owner->hasTagName(frameTag) || owner->hasTagName(iframeTag)) {
   1395                 const AtomicString& title = static_cast<HTMLFrameElementBase*>(owner)->getAttribute(titleAttr);
   1396                 if (!title.isEmpty())
   1397                     return title;
   1398                 return static_cast<HTMLFrameElementBase*>(owner)->getAttribute(nameAttr);
   1399             }
   1400             if (owner->isHTMLElement())
   1401                 return toHTMLElement(owner)->getAttribute(nameAttr);
   1402         }
   1403         owner = document->body();
   1404         if (owner && owner->isHTMLElement())
   1405             return toHTMLElement(owner)->getAttribute(nameAttr);
   1406     }
   1407 
   1408     return String();
   1409 }
   1410 
   1411 IntRect AccessibilityRenderObject::boundingBoxRect() const
   1412 {
   1413     RenderObject* obj = m_renderer;
   1414 
   1415     if (!obj)
   1416         return IntRect();
   1417 
   1418     if (obj->node()) // If we are a continuation, we want to make sure to use the primary renderer.
   1419         obj = obj->node()->renderer();
   1420 
   1421     // absoluteFocusRingQuads will query the hierarchy below this element, which for large webpages can be very slow.
   1422     // For a web area, which will have the most elements of any element, absoluteQuads should be used.
   1423     Vector<FloatQuad> quads;
   1424     if (obj->isText())
   1425         toRenderText(obj)->absoluteQuads(quads, RenderText::ClipToEllipsis);
   1426     else if (isWebArea())
   1427         obj->absoluteQuads(quads);
   1428     else
   1429         obj->absoluteFocusRingQuads(quads);
   1430     const size_t n = quads.size();
   1431     if (!n)
   1432         return IntRect();
   1433 
   1434     IntRect result;
   1435     for (size_t i = 0; i < n; ++i) {
   1436         IntRect r = quads[i].enclosingBoundingBox();
   1437         if (!r.isEmpty()) {
   1438             if (obj->style()->hasAppearance())
   1439                 obj->theme()->adjustRepaintRect(obj, r);
   1440             result.unite(r);
   1441         }
   1442     }
   1443 
   1444     // The size of the web area should be the content size, not the clipped size.
   1445     if (isWebArea() && obj->frame()->view())
   1446         result.setSize(obj->frame()->view()->contentsSize());
   1447 
   1448     return result;
   1449 }
   1450 
   1451 IntRect AccessibilityRenderObject::checkboxOrRadioRect() const
   1452 {
   1453     if (!m_renderer)
   1454         return IntRect();
   1455 
   1456     HTMLLabelElement* label = labelForElement(static_cast<Element*>(m_renderer->node()));
   1457     if (!label || !label->renderer())
   1458         return boundingBoxRect();
   1459 
   1460     IntRect labelRect = axObjectCache()->getOrCreate(label->renderer())->elementRect();
   1461     labelRect.unite(boundingBoxRect());
   1462     return labelRect;
   1463 }
   1464 
   1465 IntRect AccessibilityRenderObject::elementRect() const
   1466 {
   1467     // a checkbox or radio button should encompass its label
   1468     if (isCheckboxOrRadio())
   1469         return checkboxOrRadioRect();
   1470 
   1471     return boundingBoxRect();
   1472 }
   1473 
   1474 IntSize AccessibilityRenderObject::size() const
   1475 {
   1476     IntRect rect = elementRect();
   1477     return rect.size();
   1478 }
   1479 
   1480 IntPoint AccessibilityRenderObject::clickPoint() const
   1481 {
   1482     // use the default position unless this is an editable web area, in which case we use the selection bounds.
   1483     if (!isWebArea() || isReadOnly())
   1484         return AccessibilityObject::clickPoint();
   1485 
   1486     VisibleSelection visSelection = selection();
   1487     VisiblePositionRange range = VisiblePositionRange(visSelection.visibleStart(), visSelection.visibleEnd());
   1488     IntRect bounds = boundsForVisiblePositionRange(range);
   1489 #if PLATFORM(MAC)
   1490     bounds.setLocation(m_renderer->document()->view()->screenToContents(bounds.location()));
   1491 #endif
   1492     return IntPoint(bounds.x() + (bounds.width() / 2), bounds.y() - (bounds.height() / 2));
   1493 }
   1494 
   1495 AccessibilityObject* AccessibilityRenderObject::internalLinkElement() const
   1496 {
   1497     Element* element = anchorElement();
   1498     if (!element)
   1499         return 0;
   1500 
   1501     // Right now, we do not support ARIA links as internal link elements
   1502     if (!element->hasTagName(aTag))
   1503         return 0;
   1504     HTMLAnchorElement* anchor = static_cast<HTMLAnchorElement*>(element);
   1505 
   1506     KURL linkURL = anchor->href();
   1507     String fragmentIdentifier = linkURL.fragmentIdentifier();
   1508     if (fragmentIdentifier.isEmpty())
   1509         return 0;
   1510 
   1511     // check if URL is the same as current URL
   1512     KURL documentURL = m_renderer->document()->url();
   1513     if (!equalIgnoringFragmentIdentifier(documentURL, linkURL))
   1514         return 0;
   1515 
   1516     Node* linkedNode = m_renderer->document()->findAnchor(fragmentIdentifier);
   1517     if (!linkedNode)
   1518         return 0;
   1519 
   1520     // The element we find may not be accessible, so find the first accessible object.
   1521     return firstAccessibleObjectFromNode(linkedNode);
   1522 }
   1523 
   1524 ESpeak AccessibilityRenderObject::speakProperty() const
   1525 {
   1526     if (!m_renderer)
   1527         return AccessibilityObject::speakProperty();
   1528 
   1529     return m_renderer->style()->speak();
   1530 }
   1531 
   1532 void AccessibilityRenderObject::addRadioButtonGroupMembers(AccessibilityChildrenVector& linkedUIElements) const
   1533 {
   1534     if (!m_renderer || roleValue() != RadioButtonRole)
   1535         return;
   1536 
   1537     Node* node = m_renderer->node();
   1538     if (!node || !node->hasTagName(inputTag))
   1539         return;
   1540 
   1541     HTMLInputElement* input = static_cast<HTMLInputElement*>(node);
   1542     // if there's a form, then this is easy
   1543     if (input->form()) {
   1544         Vector<RefPtr<Node> > formElements;
   1545         input->form()->getNamedElements(input->name(), formElements);
   1546 
   1547         unsigned len = formElements.size();
   1548         for (unsigned i = 0; i < len; ++i) {
   1549             Node* associateElement = formElements[i].get();
   1550             if (AccessibilityObject* object = axObjectCache()->getOrCreate(associateElement->renderer()))
   1551                 linkedUIElements.append(object);
   1552         }
   1553     } else {
   1554         RefPtr<NodeList> list = node->document()->getElementsByTagName("input");
   1555         unsigned len = list->length();
   1556         for (unsigned i = 0; i < len; ++i) {
   1557             if (list->item(i)->hasTagName(inputTag)) {
   1558                 HTMLInputElement* associateElement = static_cast<HTMLInputElement*>(list->item(i));
   1559                 if (associateElement->isRadioButton() && associateElement->name() == input->name()) {
   1560                     if (AccessibilityObject* object = axObjectCache()->getOrCreate(associateElement->renderer()))
   1561                         linkedUIElements.append(object);
   1562                 }
   1563             }
   1564         }
   1565     }
   1566 }
   1567 
   1568 // linked ui elements could be all the related radio buttons in a group
   1569 // or an internal anchor connection
   1570 void AccessibilityRenderObject::linkedUIElements(AccessibilityChildrenVector& linkedUIElements) const
   1571 {
   1572     ariaFlowToElements(linkedUIElements);
   1573 
   1574     if (isAnchor()) {
   1575         AccessibilityObject* linkedAXElement = internalLinkElement();
   1576         if (linkedAXElement)
   1577             linkedUIElements.append(linkedAXElement);
   1578     }
   1579 
   1580     if (roleValue() == RadioButtonRole)
   1581         addRadioButtonGroupMembers(linkedUIElements);
   1582 }
   1583 
   1584 bool AccessibilityRenderObject::hasTextAlternative() const
   1585 {
   1586     // ARIA: section 2A, bullet #3 says if aria-labeledby or aria-label appears, it should
   1587     // override the "label" element association.
   1588     if (!ariaLabeledByAttribute().isEmpty() || !getAttribute(aria_labelAttr).isEmpty())
   1589         return true;
   1590 
   1591     return false;
   1592 }
   1593 
   1594 bool AccessibilityRenderObject::ariaHasPopup() const
   1595 {
   1596     return elementAttributeValue(aria_haspopupAttr);
   1597 }
   1598 
   1599 bool AccessibilityRenderObject::supportsARIAFlowTo() const
   1600 {
   1601     return !getAttribute(aria_flowtoAttr).isEmpty();
   1602 }
   1603 
   1604 void AccessibilityRenderObject::ariaFlowToElements(AccessibilityChildrenVector& flowTo) const
   1605 {
   1606     Vector<Element*> elements;
   1607     elementsFromAttribute(elements, aria_flowtoAttr);
   1608 
   1609     AXObjectCache* cache = axObjectCache();
   1610     unsigned count = elements.size();
   1611     for (unsigned k = 0; k < count; ++k) {
   1612         Element* element = elements[k];
   1613         AccessibilityObject* flowToElement = cache->getOrCreate(element->renderer());
   1614         if (flowToElement)
   1615             flowTo.append(flowToElement);
   1616     }
   1617 
   1618 }
   1619 
   1620 bool AccessibilityRenderObject::supportsARIADropping() const
   1621 {
   1622     const AtomicString& dropEffect = getAttribute(aria_dropeffectAttr);
   1623     return !dropEffect.isEmpty();
   1624 }
   1625 
   1626 bool AccessibilityRenderObject::supportsARIADragging() const
   1627 {
   1628     const AtomicString& grabbed = getAttribute(aria_grabbedAttr);
   1629     return equalIgnoringCase(grabbed, "true") || equalIgnoringCase(grabbed, "false");
   1630 }
   1631 
   1632 bool AccessibilityRenderObject::isARIAGrabbed()
   1633 {
   1634     return elementAttributeValue(aria_grabbedAttr);
   1635 }
   1636 
   1637 void AccessibilityRenderObject::setARIAGrabbed(bool grabbed)
   1638 {
   1639     setElementAttributeValue(aria_grabbedAttr, grabbed);
   1640 }
   1641 
   1642 void AccessibilityRenderObject::determineARIADropEffects(Vector<String>& effects)
   1643 {
   1644     const AtomicString& dropEffects = getAttribute(aria_dropeffectAttr);
   1645     if (dropEffects.isEmpty()) {
   1646         effects.clear();
   1647         return;
   1648     }
   1649 
   1650     String dropEffectsString = dropEffects.string();
   1651     dropEffectsString.replace('\n', ' ');
   1652     dropEffectsString.split(' ', effects);
   1653 }
   1654 
   1655 bool AccessibilityRenderObject::exposesTitleUIElement() const
   1656 {
   1657     if (!isControl())
   1658         return false;
   1659 
   1660     // checkbox or radio buttons don't expose the title ui element unless it has a title already
   1661     if (isCheckboxOrRadio() && getAttribute(titleAttr).isEmpty())
   1662         return false;
   1663 
   1664     if (hasTextAlternative())
   1665         return false;
   1666 
   1667     return true;
   1668 }
   1669 
   1670 AccessibilityObject* AccessibilityRenderObject::titleUIElement() const
   1671 {
   1672     if (!m_renderer)
   1673         return 0;
   1674 
   1675     // if isFieldset is true, the renderer is guaranteed to be a RenderFieldset
   1676     if (isFieldset())
   1677         return axObjectCache()->getOrCreate(toRenderFieldset(m_renderer)->findLegend());
   1678 
   1679     if (!exposesTitleUIElement())
   1680         return 0;
   1681 
   1682     Node* element = m_renderer->node();
   1683     HTMLLabelElement* label = labelForElement(static_cast<Element*>(element));
   1684     if (label && label->renderer())
   1685         return axObjectCache()->getOrCreate(label->renderer());
   1686 
   1687     return 0;
   1688 }
   1689 
   1690 bool AccessibilityRenderObject::ariaIsHidden() const
   1691 {
   1692     if (equalIgnoringCase(getAttribute(aria_hiddenAttr), "true"))
   1693         return true;
   1694 
   1695     // aria-hidden hides this object and any children
   1696     AccessibilityObject* object = parentObject();
   1697     while (object) {
   1698         if (object->isAccessibilityRenderObject() && equalIgnoringCase(static_cast<AccessibilityRenderObject*>(object)->getAttribute(aria_hiddenAttr), "true"))
   1699             return true;
   1700         object = object->parentObject();
   1701     }
   1702 
   1703     return false;
   1704 }
   1705 
   1706 bool AccessibilityRenderObject::isDescendantOfBarrenParent() const
   1707 {
   1708     for (AccessibilityObject* object = parentObject(); object; object = object->parentObject()) {
   1709         if (!object->canHaveChildren())
   1710             return true;
   1711     }
   1712 
   1713     return false;
   1714 }
   1715 
   1716 bool AccessibilityRenderObject::isAllowedChildOfTree() const
   1717 {
   1718     // Determine if this is in a tree. If so, we apply special behavior to make it work like an AXOutline.
   1719     AccessibilityObject* axObj = parentObject();
   1720     bool isInTree = false;
   1721     while (axObj) {
   1722         if (axObj->isTree()) {
   1723             isInTree = true;
   1724             break;
   1725         }
   1726         axObj = axObj->parentObject();
   1727     }
   1728 
   1729     // If the object is in a tree, only tree items should be exposed (and the children of tree items).
   1730     if (isInTree) {
   1731         AccessibilityRole role = roleValue();
   1732         if (role != TreeItemRole && role != StaticTextRole)
   1733             return false;
   1734     }
   1735     return true;
   1736 }
   1737 
   1738 AccessibilityObjectInclusion AccessibilityRenderObject::accessibilityIsIgnoredBase() const
   1739 {
   1740     // The following cases can apply to any element that's a subclass of AccessibilityRenderObject.
   1741 
   1742     // Ignore invisible elements.
   1743     if (!m_renderer || m_renderer->style()->visibility() != VISIBLE)
   1744         return IgnoreObject;
   1745 
   1746     // Anything marked as aria-hidden or a child of something aria-hidden must be hidden.
   1747     if (ariaIsHidden())
   1748         return IgnoreObject;
   1749 
   1750     // Anything that is a presentational role must be hidden.
   1751     if (isPresentationalChildOfAriaRole())
   1752         return IgnoreObject;
   1753 
   1754     // Allow the platform to make a decision.
   1755     AccessibilityObjectInclusion decision = accessibilityPlatformIncludesObject();
   1756     if (decision == IncludeObject)
   1757         return IncludeObject;
   1758     if (decision == IgnoreObject)
   1759         return IgnoreObject;
   1760 
   1761     return DefaultBehavior;
   1762 }
   1763 
   1764 bool AccessibilityRenderObject::accessibilityIsIgnored() const
   1765 {
   1766     // Check first if any of the common reasons cause this element to be ignored.
   1767     // Then process other use cases that need to be applied to all the various roles
   1768     // that AccessibilityRenderObjects take on.
   1769     AccessibilityObjectInclusion decision = accessibilityIsIgnoredBase();
   1770     if (decision == IncludeObject)
   1771         return false;
   1772     if (decision == IgnoreObject)
   1773         return true;
   1774 
   1775     // If this element is within a parent that cannot have children, it should not be exposed.
   1776     if (isDescendantOfBarrenParent())
   1777         return true;
   1778 
   1779     if (roleValue() == IgnoredRole)
   1780         return true;
   1781 
   1782     if (roleValue() == PresentationalRole || inheritsPresentationalRole())
   1783         return true;
   1784 
   1785     // An ARIA tree can only have tree items and static text as children.
   1786     if (!isAllowedChildOfTree())
   1787         return true;
   1788 
   1789     // Allow the platform to decide if the attachment is ignored or not.
   1790     if (isAttachment())
   1791         return accessibilityIgnoreAttachment();
   1792 
   1793     // ignore popup menu items because AppKit does
   1794     for (RenderObject* parent = m_renderer->parent(); parent; parent = parent->parent()) {
   1795         if (parent->isBoxModelObject() && toRenderBoxModelObject(parent)->isMenuList())
   1796             return true;
   1797     }
   1798 
   1799     // find out if this element is inside of a label element.
   1800     // if so, it may be ignored because it's the label for a checkbox or radio button
   1801     AccessibilityObject* controlObject = correspondingControlForLabelElement();
   1802     if (controlObject && !controlObject->exposesTitleUIElement() && controlObject->isCheckboxOrRadio())
   1803         return true;
   1804 
   1805     // NOTE: BRs always have text boxes now, so the text box check here can be removed
   1806     if (m_renderer->isText()) {
   1807         // static text beneath MenuItems and MenuButtons are just reported along with the menu item, so it's ignored on an individual level
   1808         if (parentObjectUnignored()->ariaRoleAttribute() == MenuItemRole
   1809             || parentObjectUnignored()->ariaRoleAttribute() == MenuButtonRole)
   1810             return true;
   1811         RenderText* renderText = toRenderText(m_renderer);
   1812         if (m_renderer->isBR() || !renderText->firstTextBox())
   1813             return true;
   1814 
   1815         // static text beneath TextControls is reported along with the text control text so it's ignored.
   1816         for (AccessibilityObject* parent = parentObject(); parent; parent = parent->parentObject()) {
   1817             if (parent->roleValue() == TextFieldRole)
   1818                 return true;
   1819         }
   1820 
   1821         // text elements that are just empty whitespace should not be returned
   1822         return renderText->text()->containsOnlyWhitespace();
   1823     }
   1824 
   1825     if (isHeading())
   1826         return false;
   1827 
   1828     if (isLink())
   1829         return false;
   1830 
   1831     // all controls are accessible
   1832     if (isControl())
   1833         return false;
   1834 
   1835     if (ariaRoleAttribute() != UnknownRole)
   1836         return false;
   1837 
   1838     // don't ignore labels, because they serve as TitleUIElements
   1839     Node* node = m_renderer->node();
   1840     if (node && node->hasTagName(labelTag))
   1841         return false;
   1842 
   1843     // Anything that is content editable should not be ignored.
   1844     // However, one cannot just call node->rendererIsEditable() since that will ask if its parents
   1845     // are also editable. Only the top level content editable region should be exposed.
   1846     if (node && node->isElementNode()) {
   1847         Element* element = static_cast<Element*>(node);
   1848         const AtomicString& contentEditable = element->getAttribute(contenteditableAttr);
   1849         if (equalIgnoringCase(contentEditable, "true"))
   1850             return false;
   1851     }
   1852 
   1853     // List items play an important role in defining the structure of lists. They should not be ignored.
   1854     if (roleValue() == ListItemRole)
   1855         return false;
   1856 
   1857     // if this element has aria attributes on it, it should not be ignored.
   1858     if (supportsARIAAttributes())
   1859         return false;
   1860 
   1861     if (m_renderer->isBlockFlow() && m_renderer->childrenInline())
   1862         return !toRenderBlock(m_renderer)->firstLineBox() && !mouseButtonListener();
   1863 
   1864     // ignore images seemingly used as spacers
   1865     if (isImage()) {
   1866         if (node && node->isElementNode()) {
   1867             Element* elt = static_cast<Element*>(node);
   1868             const AtomicString& alt = elt->getAttribute(altAttr);
   1869             // don't ignore an image that has an alt tag
   1870             if (!alt.isEmpty())
   1871                 return false;
   1872             // informal standard is to ignore images with zero-length alt strings
   1873             if (!alt.isNull())
   1874                 return true;
   1875         }
   1876 
   1877         if (node && node->hasTagName(canvasTag)) {
   1878             RenderHTMLCanvas* canvas = toRenderHTMLCanvas(m_renderer);
   1879             if (canvas->height() <= 1 || canvas->width() <= 1)
   1880                 return true;
   1881             return false;
   1882         }
   1883 
   1884         if (isNativeImage()) {
   1885             // check for one-dimensional image
   1886             RenderImage* image = toRenderImage(m_renderer);
   1887             if (image->height() <= 1 || image->width() <= 1)
   1888                 return true;
   1889 
   1890             // check whether rendered image was stretched from one-dimensional file image
   1891             if (image->cachedImage()) {
   1892                 IntSize imageSize = image->cachedImage()->imageSize(image->view()->zoomFactor());
   1893                 return imageSize.height() <= 1 || imageSize.width() <= 1;
   1894             }
   1895         }
   1896         return false;
   1897     }
   1898 
   1899     if (isWebArea() || m_renderer->isListMarker())
   1900         return false;
   1901 
   1902     // Using the help text to decide an element's visibility is not as definitive
   1903     // as previous checks, so this should remain as one of the last.
   1904     if (!helpText().isEmpty())
   1905         return false;
   1906 
   1907     // By default, objects should be ignored so that the AX hierarchy is not
   1908     // filled with unnecessary items.
   1909     return true;
   1910 }
   1911 
   1912 bool AccessibilityRenderObject::isLoaded() const
   1913 {
   1914     return !m_renderer->document()->parser();
   1915 }
   1916 
   1917 double AccessibilityRenderObject::estimatedLoadingProgress() const
   1918 {
   1919     if (!m_renderer)
   1920         return 0;
   1921 
   1922     if (isLoaded())
   1923         return 1.0;
   1924 
   1925     Page* page = m_renderer->document()->page();
   1926     if (!page)
   1927         return 0;
   1928 
   1929     return page->progress()->estimatedProgress();
   1930 }
   1931 
   1932 int AccessibilityRenderObject::layoutCount() const
   1933 {
   1934     if (!m_renderer->isRenderView())
   1935         return 0;
   1936     return toRenderView(m_renderer)->frameView()->layoutCount();
   1937 }
   1938 
   1939 String AccessibilityRenderObject::text() const
   1940 {
   1941     // If this is a user defined static text, use the accessible name computation.
   1942     if (ariaRoleAttribute() == StaticTextRole)
   1943         return ariaAccessibilityDescription();
   1944 
   1945     if (!isTextControl() || isPasswordField())
   1946         return String();
   1947 
   1948     if (isNativeTextControl())
   1949         return toRenderTextControl(m_renderer)->text();
   1950 
   1951     Node* node = m_renderer->node();
   1952     if (!node)
   1953         return String();
   1954     if (!node->isElementNode())
   1955         return String();
   1956 
   1957     return static_cast<Element*>(node)->innerText();
   1958 }
   1959 
   1960 int AccessibilityRenderObject::textLength() const
   1961 {
   1962     ASSERT(isTextControl());
   1963 
   1964     if (isPasswordField())
   1965         return -1; // need to return something distinct from 0
   1966 
   1967     return text().length();
   1968 }
   1969 
   1970 PlainTextRange AccessibilityRenderObject::ariaSelectedTextRange() const
   1971 {
   1972     Node* node = m_renderer->node();
   1973     if (!node)
   1974         return PlainTextRange();
   1975 
   1976     ExceptionCode ec = 0;
   1977     VisibleSelection visibleSelection = selection();
   1978     RefPtr<Range> currentSelectionRange = visibleSelection.toNormalizedRange();
   1979     if (!currentSelectionRange || !currentSelectionRange->intersectsNode(node, ec))
   1980         return PlainTextRange();
   1981 
   1982     int start = indexForVisiblePosition(visibleSelection.start());
   1983     int end = indexForVisiblePosition(visibleSelection.end());
   1984 
   1985     return PlainTextRange(start, end - start);
   1986 }
   1987 
   1988 String AccessibilityRenderObject::selectedText() const
   1989 {
   1990     ASSERT(isTextControl());
   1991 
   1992     if (isPasswordField())
   1993         return String(); // need to return something distinct from empty string
   1994 
   1995     if (isNativeTextControl()) {
   1996         RenderTextControl* textControl = toRenderTextControl(m_renderer);
   1997         return textControl->text().substring(textControl->selectionStart(), textControl->selectionEnd() - textControl->selectionStart());
   1998     }
   1999 
   2000     if (ariaRoleAttribute() == UnknownRole)
   2001         return String();
   2002 
   2003     return doAXStringForRange(ariaSelectedTextRange());
   2004 }
   2005 
   2006 const AtomicString& AccessibilityRenderObject::accessKey() const
   2007 {
   2008     Node* node = m_renderer->node();
   2009     if (!node)
   2010         return nullAtom;
   2011     if (!node->isElementNode())
   2012         return nullAtom;
   2013     return static_cast<Element*>(node)->getAttribute(accesskeyAttr);
   2014 }
   2015 
   2016 VisibleSelection AccessibilityRenderObject::selection() const
   2017 {
   2018     return m_renderer->frame()->selection()->selection();
   2019 }
   2020 
   2021 PlainTextRange AccessibilityRenderObject::selectedTextRange() const
   2022 {
   2023     ASSERT(isTextControl());
   2024 
   2025     if (isPasswordField())
   2026         return PlainTextRange();
   2027 
   2028     AccessibilityRole ariaRole = ariaRoleAttribute();
   2029     if (isNativeTextControl() && ariaRole == UnknownRole) {
   2030         RenderTextControl* textControl = toRenderTextControl(m_renderer);
   2031         return PlainTextRange(textControl->selectionStart(), textControl->selectionEnd() - textControl->selectionStart());
   2032     }
   2033 
   2034     if (ariaRole == UnknownRole)
   2035         return PlainTextRange();
   2036 
   2037     return ariaSelectedTextRange();
   2038 }
   2039 
   2040 void AccessibilityRenderObject::setSelectedTextRange(const PlainTextRange& range)
   2041 {
   2042     if (isNativeTextControl()) {
   2043         setSelectionRange(m_renderer->node(), range.start, range.start + range.length);
   2044         return;
   2045     }
   2046 
   2047     Document* document = m_renderer->document();
   2048     if (!document)
   2049         return;
   2050     Frame* frame = document->frame();
   2051     if (!frame)
   2052         return;
   2053     Node* node = m_renderer->node();
   2054     frame->selection()->setSelection(VisibleSelection(Position(node, range.start, Position::PositionIsOffsetInAnchor),
   2055         Position(node, range.start + range.length, Position::PositionIsOffsetInAnchor), DOWNSTREAM));
   2056 }
   2057 
   2058 KURL AccessibilityRenderObject::url() const
   2059 {
   2060     if (isAnchor() && m_renderer->node()->hasTagName(aTag)) {
   2061         if (HTMLAnchorElement* anchor = static_cast<HTMLAnchorElement*>(anchorElement()))
   2062             return anchor->href();
   2063     }
   2064 
   2065     if (isWebArea())
   2066         return m_renderer->document()->url();
   2067 
   2068     if (isImage() && m_renderer->node() && m_renderer->node()->hasTagName(imgTag))
   2069         return static_cast<HTMLImageElement*>(m_renderer->node())->src();
   2070 
   2071     if (isInputImage())
   2072         return static_cast<HTMLInputElement*>(m_renderer->node())->src();
   2073 
   2074     return KURL();
   2075 }
   2076 
   2077 bool AccessibilityRenderObject::isVisited() const
   2078 {
   2079     // FIXME: Is it a privacy violation to expose visited information to accessibility APIs?
   2080     return m_renderer->style()->isLink() && m_renderer->style()->insideLink() == InsideVisitedLink;
   2081 }
   2082 
   2083 void AccessibilityRenderObject::setElementAttributeValue(const QualifiedName& attributeName, bool value)
   2084 {
   2085     if (!m_renderer)
   2086         return;
   2087 
   2088     Node* node = m_renderer->node();
   2089     if (!node || !node->isElementNode())
   2090         return;
   2091 
   2092     Element* element = static_cast<Element*>(node);
   2093     element->setAttribute(attributeName, (value) ? "true" : "false");
   2094 }
   2095 
   2096 bool AccessibilityRenderObject::elementAttributeValue(const QualifiedName& attributeName) const
   2097 {
   2098     if (!m_renderer)
   2099         return false;
   2100 
   2101     return equalIgnoringCase(getAttribute(attributeName), "true");
   2102 }
   2103 
   2104 void AccessibilityRenderObject::setIsExpanded(bool isExpanded)
   2105 {
   2106     // Combo boxes, tree items and rows can be expanded (in different ways on different platforms).
   2107     // That action translates into setting the aria-expanded attribute to true.
   2108     AccessibilityRole role = roleValue();
   2109     switch (role) {
   2110     case ComboBoxRole:
   2111     case TreeItemRole:
   2112     case RowRole:
   2113         setElementAttributeValue(aria_expandedAttr, isExpanded);
   2114         break;
   2115     default:
   2116         break;
   2117     }
   2118 }
   2119 
   2120 bool AccessibilityRenderObject::isRequired() const
   2121 {
   2122     if (equalIgnoringCase(getAttribute(aria_requiredAttr), "true"))
   2123         return true;
   2124 
   2125     Node* n = node();
   2126     if (n && (n->isElementNode() && static_cast<Element*>(n)->isFormControlElement()))
   2127         return static_cast<HTMLFormControlElement*>(n)->required();
   2128 
   2129     return false;
   2130 }
   2131 
   2132 bool AccessibilityRenderObject::isSelected() const
   2133 {
   2134     if (!m_renderer)
   2135         return false;
   2136 
   2137     Node* node = m_renderer->node();
   2138     if (!node)
   2139         return false;
   2140 
   2141     const AtomicString& ariaSelected = getAttribute(aria_selectedAttr);
   2142     if (equalIgnoringCase(ariaSelected, "true"))
   2143         return true;
   2144 
   2145     if (isTabItem() && isTabItemSelected())
   2146         return true;
   2147 
   2148     return false;
   2149 }
   2150 
   2151 bool AccessibilityRenderObject::isTabItemSelected() const
   2152 {
   2153     if (!isTabItem() || !m_renderer)
   2154         return false;
   2155 
   2156     Node* node = m_renderer->node();
   2157     if (!node || !node->isElementNode())
   2158         return false;
   2159 
   2160     // The ARIA spec says a tab item can also be selected if it is aria-labeled by a tabpanel
   2161     // that has keyboard focus inside of it, or if a tabpanel in its aria-controls list has KB
   2162     // focus inside of it.
   2163     AccessibilityObject* focusedElement = focusedUIElement();
   2164     if (!focusedElement)
   2165         return false;
   2166 
   2167     Vector<Element*> elements;
   2168     elementsFromAttribute(elements, aria_controlsAttr);
   2169 
   2170     unsigned count = elements.size();
   2171     for (unsigned k = 0; k < count; ++k) {
   2172         Element* element = elements[k];
   2173         AccessibilityObject* tabPanel = axObjectCache()->getOrCreate(element->renderer());
   2174 
   2175         // A tab item should only control tab panels.
   2176         if (!tabPanel || tabPanel->roleValue() != TabPanelRole)
   2177             continue;
   2178 
   2179         AccessibilityObject* checkFocusElement = focusedElement;
   2180         // Check if the focused element is a descendant of the element controlled by the tab item.
   2181         while (checkFocusElement) {
   2182             if (tabPanel == checkFocusElement)
   2183                 return true;
   2184             checkFocusElement = checkFocusElement->parentObject();
   2185         }
   2186     }
   2187 
   2188     return false;
   2189 }
   2190 
   2191 bool AccessibilityRenderObject::isFocused() const
   2192 {
   2193     if (!m_renderer)
   2194         return false;
   2195 
   2196     Document* document = m_renderer->document();
   2197     if (!document)
   2198         return false;
   2199 
   2200     Node* focusedNode = document->focusedNode();
   2201     if (!focusedNode)
   2202         return false;
   2203 
   2204     // A web area is represented by the Document node in the DOM tree, which isn't focusable.
   2205     // Check instead if the frame's selection controller is focused
   2206     if (focusedNode == m_renderer->node()
   2207         || (roleValue() == WebAreaRole && document->frame()->selection()->isFocusedAndActive()))
   2208         return true;
   2209 
   2210     return false;
   2211 }
   2212 
   2213 void AccessibilityRenderObject::setFocused(bool on)
   2214 {
   2215     if (!canSetFocusAttribute())
   2216         return;
   2217 
   2218     if (!on)
   2219         m_renderer->document()->setFocusedNode(0);
   2220     else {
   2221         if (m_renderer->node()->isElementNode())
   2222             static_cast<Element*>(m_renderer->node())->focus();
   2223         else
   2224             m_renderer->document()->setFocusedNode(m_renderer->node());
   2225     }
   2226 }
   2227 
   2228 void AccessibilityRenderObject::changeValueByPercent(float percentChange)
   2229 {
   2230     float range = maxValueForRange() - minValueForRange();
   2231     float value = valueForRange();
   2232 
   2233     value += range * (percentChange / 100);
   2234     setValue(String::number(value));
   2235 
   2236     axObjectCache()->postNotification(m_renderer, AXObjectCache::AXValueChanged, true);
   2237 }
   2238 
   2239 void AccessibilityRenderObject::setSelected(bool enabled)
   2240 {
   2241     setElementAttributeValue(aria_selectedAttr, enabled);
   2242 }
   2243 
   2244 void AccessibilityRenderObject::setSelectedRows(AccessibilityChildrenVector& selectedRows)
   2245 {
   2246     // Setting selected only makes sense in trees and tables (and tree-tables).
   2247     AccessibilityRole role = roleValue();
   2248     if (role != TreeRole && role != TreeGridRole && role != TableRole)
   2249         return;
   2250 
   2251     bool isMulti = isMultiSelectable();
   2252     unsigned count = selectedRows.size();
   2253     if (count > 1 && !isMulti)
   2254         count = 1;
   2255 
   2256     for (unsigned k = 0; k < count; ++k)
   2257         selectedRows[k]->setSelected(true);
   2258 }
   2259 
   2260 void AccessibilityRenderObject::setValue(const String& string)
   2261 {
   2262     if (!m_renderer || !m_renderer->node() || !m_renderer->node()->isElementNode())
   2263         return;
   2264     Element* element = static_cast<Element*>(m_renderer->node());
   2265 
   2266     if (roleValue() == SliderRole)
   2267         element->setAttribute(aria_valuenowAttr, string);
   2268 
   2269     if (!m_renderer->isBoxModelObject())
   2270         return;
   2271     RenderBoxModelObject* renderer = toRenderBoxModelObject(m_renderer);
   2272 
   2273     // FIXME: Do we want to do anything here for ARIA textboxes?
   2274     if (renderer->isTextField()) {
   2275         // FIXME: This is not safe!  Other elements could have a TextField renderer.
   2276         static_cast<HTMLInputElement*>(element)->setValue(string);
   2277     } else if (renderer->isTextArea()) {
   2278         // FIXME: This is not safe!  Other elements could have a TextArea renderer.
   2279         static_cast<HTMLTextAreaElement*>(element)->setValue(string);
   2280     }
   2281 }
   2282 
   2283 void AccessibilityRenderObject::ariaOwnsElements(AccessibilityChildrenVector& axObjects) const
   2284 {
   2285     Vector<Element*> elements;
   2286     elementsFromAttribute(elements, aria_ownsAttr);
   2287 
   2288     unsigned count = elements.size();
   2289     for (unsigned k = 0; k < count; ++k) {
   2290         RenderObject* render = elements[k]->renderer();
   2291         AccessibilityObject* obj = axObjectCache()->getOrCreate(render);
   2292         if (obj)
   2293             axObjects.append(obj);
   2294     }
   2295 }
   2296 
   2297 bool AccessibilityRenderObject::supportsARIAOwns() const
   2298 {
   2299     if (!m_renderer)
   2300         return false;
   2301     const AtomicString& ariaOwns = getAttribute(aria_ownsAttr);
   2302 
   2303     return !ariaOwns.isEmpty();
   2304 }
   2305 
   2306 bool AccessibilityRenderObject::isEnabled() const
   2307 {
   2308     ASSERT(m_renderer);
   2309 
   2310     if (equalIgnoringCase(getAttribute(aria_disabledAttr), "true"))
   2311         return false;
   2312 
   2313     Node* node = m_renderer->node();
   2314     if (!node || !node->isElementNode())
   2315         return true;
   2316 
   2317     return static_cast<Element*>(node)->isEnabledFormControl();
   2318 }
   2319 
   2320 RenderView* AccessibilityRenderObject::topRenderer() const
   2321 {
   2322     return m_renderer->document()->topDocument()->renderView();
   2323 }
   2324 
   2325 Document* AccessibilityRenderObject::document() const
   2326 {
   2327     if (!m_renderer)
   2328         return 0;
   2329     return m_renderer->document();
   2330 }
   2331 
   2332 FrameView* AccessibilityRenderObject::topDocumentFrameView() const
   2333 {
   2334     return topRenderer()->view()->frameView();
   2335 }
   2336 
   2337 Widget* AccessibilityRenderObject::widget() const
   2338 {
   2339     if (!m_renderer->isBoxModelObject() || !toRenderBoxModelObject(m_renderer)->isWidget())
   2340         return 0;
   2341     return toRenderWidget(m_renderer)->widget();
   2342 }
   2343 
   2344 AccessibilityObject* AccessibilityRenderObject::accessibilityParentForImageMap(HTMLMapElement* map) const
   2345 {
   2346     // find an image that is using this map
   2347     if (!map)
   2348         return 0;
   2349 
   2350     HTMLImageElement* imageElement = map->imageElement();
   2351     if (!imageElement)
   2352         return 0;
   2353 
   2354     return axObjectCache()->getOrCreate(imageElement->renderer());
   2355 }
   2356 
   2357 void AccessibilityRenderObject::getDocumentLinks(AccessibilityChildrenVector& result)
   2358 {
   2359     Document* document = m_renderer->document();
   2360     RefPtr<HTMLCollection> coll = document->links();
   2361     Node* curr = coll->firstItem();
   2362     while (curr) {
   2363         RenderObject* obj = curr->renderer();
   2364         if (obj) {
   2365             RefPtr<AccessibilityObject> axobj = document->axObjectCache()->getOrCreate(obj);
   2366             ASSERT(axobj);
   2367             if (!axobj->accessibilityIsIgnored() && axobj->isLink())
   2368                 result.append(axobj);
   2369         } else {
   2370             Node* parent = curr->parentNode();
   2371             if (parent && curr->hasTagName(areaTag) && parent->hasTagName(mapTag)) {
   2372                 AccessibilityImageMapLink* areaObject = static_cast<AccessibilityImageMapLink*>(axObjectCache()->getOrCreate(ImageMapLinkRole));
   2373                 areaObject->setHTMLAreaElement(static_cast<HTMLAreaElement*>(curr));
   2374                 areaObject->setHTMLMapElement(static_cast<HTMLMapElement*>(parent));
   2375                 areaObject->setParent(accessibilityParentForImageMap(static_cast<HTMLMapElement*>(parent)));
   2376 
   2377                 result.append(areaObject);
   2378             }
   2379         }
   2380         curr = coll->nextItem();
   2381     }
   2382 }
   2383 
   2384 FrameView* AccessibilityRenderObject::documentFrameView() const
   2385 {
   2386     if (!m_renderer || !m_renderer->document())
   2387         return 0;
   2388 
   2389     // this is the RenderObject's Document's Frame's FrameView
   2390     return m_renderer->document()->view();
   2391 }
   2392 
   2393 Widget* AccessibilityRenderObject::widgetForAttachmentView() const
   2394 {
   2395     if (!isAttachment())
   2396         return 0;
   2397     return toRenderWidget(m_renderer)->widget();
   2398 }
   2399 
   2400 FrameView* AccessibilityRenderObject::frameViewIfRenderView() const
   2401 {
   2402     if (!m_renderer->isRenderView())
   2403         return 0;
   2404     // this is the RenderObject's Document's renderer's FrameView
   2405     return m_renderer->view()->frameView();
   2406 }
   2407 
   2408 // This function is like a cross-platform version of - (WebCoreTextMarkerRange*)textMarkerRange. It returns
   2409 // a Range that we can convert to a WebCoreTextMarkerRange in the Obj-C file
   2410 VisiblePositionRange AccessibilityRenderObject::visiblePositionRange() const
   2411 {
   2412     if (!m_renderer)
   2413         return VisiblePositionRange();
   2414 
   2415     // construct VisiblePositions for start and end
   2416     Node* node = m_renderer->node();
   2417     if (!node)
   2418         return VisiblePositionRange();
   2419 
   2420     VisiblePosition startPos = firstPositionInOrBeforeNode(node);
   2421     VisiblePosition endPos = lastPositionInOrAfterNode(node);
   2422 
   2423     // the VisiblePositions are equal for nodes like buttons, so adjust for that
   2424     // FIXME: Really?  [button, 0] and [button, 1] are distinct (before and after the button)
   2425     // I expect this code is only hit for things like empty divs?  In which case I don't think
   2426     // the behavior is correct here -- eseidel
   2427     if (startPos == endPos) {
   2428         endPos = endPos.next();
   2429         if (endPos.isNull())
   2430             endPos = startPos;
   2431     }
   2432 
   2433     return VisiblePositionRange(startPos, endPos);
   2434 }
   2435 
   2436 VisiblePositionRange AccessibilityRenderObject::visiblePositionRangeForLine(unsigned lineCount) const
   2437 {
   2438     if (!lineCount || !m_renderer)
   2439         return VisiblePositionRange();
   2440 
   2441     // iterate over the lines
   2442     // FIXME: this is wrong when lineNumber is lineCount+1,  because nextLinePosition takes you to the
   2443     // last offset of the last line
   2444     VisiblePosition visiblePos = m_renderer->document()->renderer()->positionForCoordinates(0, 0);
   2445     VisiblePosition savedVisiblePos;
   2446     while (--lineCount) {
   2447         savedVisiblePos = visiblePos;
   2448         visiblePos = nextLinePosition(visiblePos, 0);
   2449         if (visiblePos.isNull() || visiblePos == savedVisiblePos)
   2450             return VisiblePositionRange();
   2451     }
   2452 
   2453     // make a caret selection for the marker position, then extend it to the line
   2454     // NOTE: ignores results of sel.modify because it returns false when
   2455     // starting at an empty line.  The resulting selection in that case
   2456     // will be a caret at visiblePos.
   2457     SelectionController selection;
   2458     selection.setSelection(VisibleSelection(visiblePos));
   2459     selection.modify(SelectionController::AlterationExtend, DirectionRight, LineBoundary);
   2460 
   2461     return VisiblePositionRange(selection.selection().visibleStart(), selection.selection().visibleEnd());
   2462 }
   2463 
   2464 VisiblePosition AccessibilityRenderObject::visiblePositionForIndex(int index) const
   2465 {
   2466     if (!m_renderer)
   2467         return VisiblePosition();
   2468 
   2469     if (isNativeTextControl())
   2470         return toRenderTextControl(m_renderer)->visiblePositionForIndex(index);
   2471 
   2472     if (!allowsTextRanges() && !m_renderer->isText())
   2473         return VisiblePosition();
   2474 
   2475     Node* node = m_renderer->node();
   2476     if (!node)
   2477         return VisiblePosition();
   2478 
   2479     if (index <= 0)
   2480         return VisiblePosition(firstPositionInOrBeforeNode(node), DOWNSTREAM);
   2481 
   2482     ExceptionCode ec = 0;
   2483     RefPtr<Range> range = Range::create(m_renderer->document());
   2484     range->selectNodeContents(node, ec);
   2485     CharacterIterator it(range.get());
   2486     it.advance(index - 1);
   2487     return VisiblePosition(Position(it.range()->endContainer(ec), it.range()->endOffset(ec), Position::PositionIsOffsetInAnchor), UPSTREAM);
   2488 }
   2489 
   2490 int AccessibilityRenderObject::indexForVisiblePosition(const VisiblePosition& pos) const
   2491 {
   2492     if (isNativeTextControl())
   2493         return RenderTextControl::indexForVisiblePosition(toRenderTextControl(m_renderer)->innerTextElement(), pos);
   2494 
   2495     if (!isTextControl())
   2496         return 0;
   2497 
   2498     Node* node = m_renderer->node();
   2499     if (!node)
   2500         return 0;
   2501 
   2502     Position indexPosition = pos.deepEquivalent();
   2503     if (!indexPosition.anchorNode() || indexPosition.anchorNode()->rootEditableElement() != node)
   2504         return 0;
   2505 
   2506     ExceptionCode ec = 0;
   2507     RefPtr<Range> range = Range::create(m_renderer->document());
   2508     range->setStart(node, 0, ec);
   2509     range->setEnd(indexPosition.anchorNode(), indexPosition.deprecatedEditingOffset(), ec);
   2510 
   2511 #if PLATFORM(GTK)
   2512     // We need to consider replaced elements for GTK, as they will be
   2513     // presented with the 'object replacement character' (0xFFFC).
   2514     return TextIterator::rangeLength(range.get(), true);
   2515 #else
   2516     return TextIterator::rangeLength(range.get());
   2517 #endif
   2518 }
   2519 
   2520 IntRect AccessibilityRenderObject::boundsForVisiblePositionRange(const VisiblePositionRange& visiblePositionRange) const
   2521 {
   2522     if (visiblePositionRange.isNull())
   2523         return IntRect();
   2524 
   2525     // Create a mutable VisiblePositionRange.
   2526     VisiblePositionRange range(visiblePositionRange);
   2527     IntRect rect1 = range.start.absoluteCaretBounds();
   2528     IntRect rect2 = range.end.absoluteCaretBounds();
   2529 
   2530     // readjust for position at the edge of a line.  This is to exclude line rect that doesn't need to be accounted in the range bounds
   2531     if (rect2.y() != rect1.y()) {
   2532         VisiblePosition endOfFirstLine = endOfLine(range.start);
   2533         if (range.start == endOfFirstLine) {
   2534             range.start.setAffinity(DOWNSTREAM);
   2535             rect1 = range.start.absoluteCaretBounds();
   2536         }
   2537         if (range.end == endOfFirstLine) {
   2538             range.end.setAffinity(UPSTREAM);
   2539             rect2 = range.end.absoluteCaretBounds();
   2540         }
   2541     }
   2542 
   2543     IntRect ourrect = rect1;
   2544     ourrect.unite(rect2);
   2545 
   2546     // if the rectangle spans lines and contains multiple text chars, use the range's bounding box intead
   2547     if (rect1.maxY() != rect2.maxY()) {
   2548         RefPtr<Range> dataRange = makeRange(range.start, range.end);
   2549         IntRect boundingBox = dataRange->boundingBox();
   2550         String rangeString = plainText(dataRange.get());
   2551         if (rangeString.length() > 1 && !boundingBox.isEmpty())
   2552             ourrect = boundingBox;
   2553     }
   2554 
   2555 #if PLATFORM(MAC)
   2556     return m_renderer->document()->view()->contentsToScreen(ourrect);
   2557 #else
   2558     return ourrect;
   2559 #endif
   2560 }
   2561 
   2562 void AccessibilityRenderObject::setSelectedVisiblePositionRange(const VisiblePositionRange& range) const
   2563 {
   2564     if (range.start.isNull() || range.end.isNull())
   2565         return;
   2566 
   2567     // make selection and tell the document to use it. if it's zero length, then move to that position
   2568     if (range.start == range.end)
   2569         m_renderer->frame()->selection()->moveTo(range.start, true);
   2570     else {
   2571         VisibleSelection newSelection = VisibleSelection(range.start, range.end);
   2572         m_renderer->frame()->selection()->setSelection(newSelection);
   2573     }
   2574 }
   2575 
   2576 VisiblePosition AccessibilityRenderObject::visiblePositionForPoint(const IntPoint& point) const
   2577 {
   2578     if (!m_renderer)
   2579         return VisiblePosition();
   2580 
   2581     // convert absolute point to view coordinates
   2582     FrameView* frameView = m_renderer->document()->topDocument()->renderer()->view()->frameView();
   2583     RenderView* renderView = topRenderer();
   2584     Node* innerNode = 0;
   2585 
   2586     // locate the node containing the point
   2587     IntPoint pointResult;
   2588     while (1) {
   2589         IntPoint ourpoint;
   2590 #if PLATFORM(MAC)
   2591         ourpoint = frameView->screenToContents(point);
   2592 #else
   2593         ourpoint = point;
   2594 #endif
   2595         HitTestRequest request(HitTestRequest::ReadOnly |
   2596                                HitTestRequest::Active);
   2597         HitTestResult result(ourpoint);
   2598         renderView->layer()->hitTest(request, result);
   2599         innerNode = result.innerNode();
   2600         if (!innerNode)
   2601             return VisiblePosition();
   2602 
   2603         RenderObject* renderer = innerNode->renderer();
   2604         if (!renderer)
   2605             return VisiblePosition();
   2606 
   2607         pointResult = result.localPoint();
   2608 
   2609         // done if hit something other than a widget
   2610         if (!renderer->isWidget())
   2611             break;
   2612 
   2613         // descend into widget (FRAME, IFRAME, OBJECT...)
   2614         Widget* widget = toRenderWidget(renderer)->widget();
   2615         if (!widget || !widget->isFrameView())
   2616             break;
   2617         Frame* frame = static_cast<FrameView*>(widget)->frame();
   2618         if (!frame)
   2619             break;
   2620         renderView = frame->document()->renderView();
   2621         frameView = static_cast<FrameView*>(widget);
   2622     }
   2623 
   2624     return innerNode->renderer()->positionForPoint(pointResult);
   2625 }
   2626 
   2627 // NOTE: Consider providing this utility method as AX API
   2628 VisiblePosition AccessibilityRenderObject::visiblePositionForIndex(unsigned indexValue, bool lastIndexOK) const
   2629 {
   2630     if (!isTextControl())
   2631         return VisiblePosition();
   2632 
   2633     // lastIndexOK specifies whether the position after the last character is acceptable
   2634     if (indexValue >= text().length()) {
   2635         if (!lastIndexOK || indexValue > text().length())
   2636             return VisiblePosition();
   2637     }
   2638     VisiblePosition position = visiblePositionForIndex(indexValue);
   2639     position.setAffinity(DOWNSTREAM);
   2640     return position;
   2641 }
   2642 
   2643 // NOTE: Consider providing this utility method as AX API
   2644 int AccessibilityRenderObject::index(const VisiblePosition& position) const
   2645 {
   2646     if (!isTextControl())
   2647         return -1;
   2648 
   2649     Node* node = position.deepEquivalent().deprecatedNode();
   2650     if (!node)
   2651         return -1;
   2652 
   2653     for (RenderObject* renderer = node->renderer(); renderer && renderer->node(); renderer = renderer->parent()) {
   2654         if (renderer == m_renderer)
   2655             return indexForVisiblePosition(position);
   2656     }
   2657 
   2658     return -1;
   2659 }
   2660 
   2661 // Given a line number, the range of characters of the text associated with this accessibility
   2662 // object that contains the line number.
   2663 PlainTextRange AccessibilityRenderObject::doAXRangeForLine(unsigned lineNumber) const
   2664 {
   2665     if (!isTextControl())
   2666         return PlainTextRange();
   2667 
   2668     // iterate to the specified line
   2669     VisiblePosition visiblePos = visiblePositionForIndex(0);
   2670     VisiblePosition savedVisiblePos;
   2671     for (unsigned lineCount = lineNumber; lineCount; lineCount -= 1) {
   2672         savedVisiblePos = visiblePos;
   2673         visiblePos = nextLinePosition(visiblePos, 0);
   2674         if (visiblePos.isNull() || visiblePos == savedVisiblePos)
   2675             return PlainTextRange();
   2676     }
   2677 
   2678     // Get the end of the line based on the starting position.
   2679     VisiblePosition endPosition = endOfLine(visiblePos);
   2680 
   2681     int index1 = indexForVisiblePosition(visiblePos);
   2682     int index2 = indexForVisiblePosition(endPosition);
   2683 
   2684     // add one to the end index for a line break not caused by soft line wrap (to match AppKit)
   2685     if (endPosition.affinity() == DOWNSTREAM && endPosition.next().isNotNull())
   2686         index2 += 1;
   2687 
   2688     // return nil rather than an zero-length range (to match AppKit)
   2689     if (index1 == index2)
   2690         return PlainTextRange();
   2691 
   2692     return PlainTextRange(index1, index2 - index1);
   2693 }
   2694 
   2695 // The composed character range in the text associated with this accessibility object that
   2696 // is specified by the given index value. This parameterized attribute returns the complete
   2697 // range of characters (including surrogate pairs of multi-byte glyphs) at the given index.
   2698 PlainTextRange AccessibilityRenderObject::doAXRangeForIndex(unsigned index) const
   2699 {
   2700     if (!isTextControl())
   2701         return PlainTextRange();
   2702 
   2703     String elementText = text();
   2704     if (!elementText.length() || index > elementText.length() - 1)
   2705         return PlainTextRange();
   2706 
   2707     return PlainTextRange(index, 1);
   2708 }
   2709 
   2710 // A substring of the text associated with this accessibility object that is
   2711 // specified by the given character range.
   2712 String AccessibilityRenderObject::doAXStringForRange(const PlainTextRange& range) const
   2713 {
   2714     if (isPasswordField())
   2715         return String();
   2716 
   2717     if (!range.length)
   2718         return String();
   2719 
   2720     if (!isTextControl())
   2721         return String();
   2722 
   2723     String elementText = text();
   2724     if (range.start + range.length > elementText.length())
   2725         return String();
   2726 
   2727     return elementText.substring(range.start, range.length);
   2728 }
   2729 
   2730 // The bounding rectangle of the text associated with this accessibility object that is
   2731 // specified by the given range. This is the bounding rectangle a sighted user would see
   2732 // on the display screen, in pixels.
   2733 IntRect AccessibilityRenderObject::doAXBoundsForRange(const PlainTextRange& range) const
   2734 {
   2735     if (allowsTextRanges())
   2736         return boundsForVisiblePositionRange(visiblePositionRangeForRange(range));
   2737     return IntRect();
   2738 }
   2739 
   2740 AccessibilityObject* AccessibilityRenderObject::accessibilityImageMapHitTest(HTMLAreaElement* area, const IntPoint& point) const
   2741 {
   2742     if (!area)
   2743         return 0;
   2744 
   2745     HTMLMapElement* map = static_cast<HTMLMapElement*>(area->parentNode());
   2746     AccessibilityObject* parent = accessibilityParentForImageMap(map);
   2747     if (!parent)
   2748         return 0;
   2749 
   2750     AccessibilityObject::AccessibilityChildrenVector children = parent->children();
   2751 
   2752     unsigned count = children.size();
   2753     for (unsigned k = 0; k < count; ++k) {
   2754         if (children[k]->elementRect().contains(point))
   2755             return children[k].get();
   2756     }
   2757 
   2758     return 0;
   2759 }
   2760 
   2761 AccessibilityObject* AccessibilityRenderObject::accessibilityHitTest(const IntPoint& point) const
   2762 {
   2763     if (!m_renderer || !m_renderer->hasLayer())
   2764         return 0;
   2765 
   2766     RenderLayer* layer = toRenderBox(m_renderer)->layer();
   2767 
   2768     HitTestRequest request(HitTestRequest::ReadOnly | HitTestRequest::Active);
   2769     HitTestResult hitTestResult = HitTestResult(point);
   2770     layer->hitTest(request, hitTestResult);
   2771     if (!hitTestResult.innerNode())
   2772         return 0;
   2773     Node* node = hitTestResult.innerNode()->shadowAncestorNode();
   2774 
   2775     if (node->hasTagName(areaTag))
   2776         return accessibilityImageMapHitTest(static_cast<HTMLAreaElement*>(node), point);
   2777 
   2778     if (node->hasTagName(optionTag))
   2779         node = static_cast<HTMLOptionElement*>(node)->ownerSelectElement();
   2780 
   2781     RenderObject* obj = node->renderer();
   2782     if (!obj)
   2783         return 0;
   2784 
   2785     AccessibilityObject* result = obj->document()->axObjectCache()->getOrCreate(obj);
   2786     result->updateChildrenIfNecessary();
   2787 
   2788     // Allow the element to perform any hit-testing it might need to do to reach non-render children.
   2789     result = result->elementAccessibilityHitTest(point);
   2790 
   2791     if (result->accessibilityIsIgnored()) {
   2792         // If this element is the label of a control, a hit test should return the control.
   2793         AccessibilityObject* controlObject = result->correspondingControlForLabelElement();
   2794         if (controlObject && !controlObject->exposesTitleUIElement())
   2795             return controlObject;
   2796 
   2797         result = result->parentObjectUnignored();
   2798     }
   2799 
   2800     return result;
   2801 }
   2802 
   2803 bool AccessibilityRenderObject::shouldFocusActiveDescendant() const
   2804 {
   2805     switch (ariaRoleAttribute()) {
   2806     case GroupRole:
   2807     case ComboBoxRole:
   2808     case ListBoxRole:
   2809     case MenuRole:
   2810     case MenuBarRole:
   2811     case RadioGroupRole:
   2812     case RowRole:
   2813     case PopUpButtonRole:
   2814     case ProgressIndicatorRole:
   2815     case ToolbarRole:
   2816     case OutlineRole:
   2817     case TreeRole:
   2818     case GridRole:
   2819     /* FIXME: replace these with actual roles when they are added to AccessibilityRole
   2820     composite
   2821     alert
   2822     alertdialog
   2823     status
   2824     timer
   2825     */
   2826         return true;
   2827     default:
   2828         return false;
   2829     }
   2830 }
   2831 
   2832 AccessibilityObject* AccessibilityRenderObject::activeDescendant() const
   2833 {
   2834     if (!m_renderer)
   2835         return 0;
   2836 
   2837     if (m_renderer->node() && !m_renderer->node()->isElementNode())
   2838         return 0;
   2839     Element* element = static_cast<Element*>(m_renderer->node());
   2840 
   2841     const AtomicString& activeDescendantAttrStr = element->getAttribute(aria_activedescendantAttr);
   2842     if (activeDescendantAttrStr.isNull() || activeDescendantAttrStr.isEmpty())
   2843         return 0;
   2844 
   2845     Element* target = document()->getElementById(activeDescendantAttrStr);
   2846     if (!target)
   2847         return 0;
   2848 
   2849     AccessibilityObject* obj = axObjectCache()->getOrCreate(target->renderer());
   2850     if (obj && obj->isAccessibilityRenderObject())
   2851     // an activedescendant is only useful if it has a renderer, because that's what's needed to post the notification
   2852         return obj;
   2853     return 0;
   2854 }
   2855 
   2856 void AccessibilityRenderObject::handleAriaExpandedChanged()
   2857 {
   2858     // Find if a parent of this object should handle aria-expanded changes.
   2859     AccessibilityObject* containerParent = this->parentObject();
   2860     while (containerParent) {
   2861         bool foundParent = false;
   2862 
   2863         switch (containerParent->roleValue()) {
   2864         case TreeRole:
   2865         case TreeGridRole:
   2866         case GridRole:
   2867         case TableRole:
   2868         case BrowserRole:
   2869             foundParent = true;
   2870             break;
   2871         default:
   2872             break;
   2873         }
   2874 
   2875         if (foundParent)
   2876             break;
   2877 
   2878         containerParent = containerParent->parentObject();
   2879     }
   2880 
   2881     // Post that the row count changed.
   2882     if (containerParent)
   2883         axObjectCache()->postNotification(containerParent, document(), AXObjectCache::AXRowCountChanged, true);
   2884 
   2885     // Post that the specific row either collapsed or expanded.
   2886     if (roleValue() == RowRole || roleValue() == TreeItemRole)
   2887         axObjectCache()->postNotification(this, document(), isExpanded() ? AXObjectCache::AXRowExpanded : AXObjectCache::AXRowCollapsed, true);
   2888 }
   2889 
   2890 void AccessibilityRenderObject::handleActiveDescendantChanged()
   2891 {
   2892     Element* element = static_cast<Element*>(renderer()->node());
   2893     if (!element)
   2894         return;
   2895     Document* doc = renderer()->document();
   2896     if (!doc->frame()->selection()->isFocusedAndActive() || doc->focusedNode() != element)
   2897         return;
   2898     AccessibilityRenderObject* activedescendant = static_cast<AccessibilityRenderObject*>(activeDescendant());
   2899 
   2900     if (activedescendant && shouldFocusActiveDescendant())
   2901         doc->axObjectCache()->postNotification(m_renderer, AXObjectCache::AXActiveDescendantChanged, true);
   2902 }
   2903 
   2904 AccessibilityObject* AccessibilityRenderObject::correspondingControlForLabelElement() const
   2905 {
   2906     HTMLLabelElement* labelElement = labelElementContainer();
   2907     if (!labelElement)
   2908         return 0;
   2909 
   2910     HTMLElement* correspondingControl = labelElement->control();
   2911     if (!correspondingControl)
   2912         return 0;
   2913 
   2914     return axObjectCache()->getOrCreate(correspondingControl->renderer());
   2915 }
   2916 
   2917 AccessibilityObject* AccessibilityRenderObject::correspondingLabelForControlElement() const
   2918 {
   2919     if (!m_renderer)
   2920         return 0;
   2921 
   2922     Node* node = m_renderer->node();
   2923     if (node && node->isHTMLElement()) {
   2924         HTMLLabelElement* label = labelForElement(static_cast<Element*>(node));
   2925         if (label)
   2926             return axObjectCache()->getOrCreate(label->renderer());
   2927     }
   2928 
   2929     return 0;
   2930 }
   2931 
   2932 bool AccessibilityRenderObject::renderObjectIsObservable(RenderObject* renderer) const
   2933 {
   2934     // AX clients will listen for AXValueChange on a text control.
   2935     if (renderer->isTextControl())
   2936         return true;
   2937 
   2938     // AX clients will listen for AXSelectedChildrenChanged on listboxes.
   2939     Node* node = renderer->node();
   2940     if (nodeHasRole(node, "listbox") || (renderer->isBoxModelObject() && toRenderBoxModelObject(renderer)->isListBox()))
   2941         return true;
   2942 
   2943     // Textboxes should send out notifications.
   2944     if (nodeHasRole(node, "textbox"))
   2945         return true;
   2946 
   2947     return false;
   2948 }
   2949 
   2950 AccessibilityObject* AccessibilityRenderObject::observableObject() const
   2951 {
   2952     // Find the object going up the parent chain that is used in accessibility to monitor certain notifications.
   2953     for (RenderObject* renderer = m_renderer; renderer && renderer->node(); renderer = renderer->parent()) {
   2954         if (renderObjectIsObservable(renderer))
   2955             return axObjectCache()->getOrCreate(renderer);
   2956     }
   2957 
   2958     return 0;
   2959 }
   2960 
   2961 AccessibilityRole AccessibilityRenderObject::determineAriaRoleAttribute() const
   2962 {
   2963     const AtomicString& ariaRole = getAttribute(roleAttr);
   2964     if (ariaRole.isNull() || ariaRole.isEmpty())
   2965         return UnknownRole;
   2966 
   2967     AccessibilityRole role = ariaRoleToWebCoreRole(ariaRole);
   2968 
   2969     if (role == ButtonRole && ariaHasPopup())
   2970         role = PopUpButtonRole;
   2971 
   2972     if (role == TextAreaRole && ariaIsMultiline())
   2973         role = TextFieldRole;
   2974 
   2975     if (role)
   2976         return role;
   2977 
   2978     AccessibilityObject* parentObject = parentObjectUnignored();
   2979     if (!parentObject)
   2980         return UnknownRole;
   2981 
   2982     AccessibilityRole parentAriaRole = parentObject->ariaRoleAttribute();
   2983 
   2984     // selects and listboxes both have options as child roles, but they map to different roles within WebCore
   2985     if (equalIgnoringCase(ariaRole, "option")) {
   2986         if (parentAriaRole == MenuRole)
   2987             return MenuItemRole;
   2988         if (parentAriaRole == ListBoxRole)
   2989             return ListBoxOptionRole;
   2990     }
   2991     // an aria "menuitem" may map to MenuButton or MenuItem depending on its parent
   2992     if (equalIgnoringCase(ariaRole, "menuitem")) {
   2993         if (parentAriaRole == GroupRole)
   2994             return MenuButtonRole;
   2995         if (parentAriaRole == MenuRole || parentAriaRole == MenuBarRole)
   2996             return MenuItemRole;
   2997     }
   2998 
   2999     return UnknownRole;
   3000 }
   3001 
   3002 AccessibilityRole AccessibilityRenderObject::ariaRoleAttribute() const
   3003 {
   3004     return m_ariaRole;
   3005 }
   3006 
   3007 void AccessibilityRenderObject::updateAccessibilityRole()
   3008 {
   3009     bool ignoredStatus = accessibilityIsIgnored();
   3010     m_role = determineAccessibilityRole();
   3011 
   3012     // The AX hierarchy only needs to be updated if the ignored status of an element has changed.
   3013     if (ignoredStatus != accessibilityIsIgnored())
   3014         childrenChanged();
   3015 }
   3016 
   3017 AccessibilityRole AccessibilityRenderObject::determineAccessibilityRole()
   3018 {
   3019     if (!m_renderer)
   3020         return UnknownRole;
   3021 
   3022     m_ariaRole = determineAriaRoleAttribute();
   3023 
   3024     Node* node = m_renderer->node();
   3025     AccessibilityRole ariaRole = ariaRoleAttribute();
   3026     if (ariaRole != UnknownRole)
   3027         return ariaRole;
   3028 
   3029     RenderBoxModelObject* cssBox = renderBoxModelObject();
   3030 
   3031     if (node && node->isLink()) {
   3032         if (cssBox && cssBox->isImage())
   3033             return ImageMapRole;
   3034         return WebCoreLinkRole;
   3035     }
   3036     if (cssBox && cssBox->isListItem())
   3037         return ListItemRole;
   3038     if (m_renderer->isListMarker())
   3039         return ListMarkerRole;
   3040     if (node && node->hasTagName(buttonTag))
   3041         return ButtonRole;
   3042     if (m_renderer->isText())
   3043         return StaticTextRole;
   3044     if (cssBox && cssBox->isImage()) {
   3045         if (node && node->hasTagName(inputTag))
   3046             return ButtonRole;
   3047         return ImageRole;
   3048     }
   3049     if (node && node->hasTagName(canvasTag))
   3050         return ImageRole;
   3051 
   3052     if (cssBox && cssBox->isRenderView())
   3053         return WebAreaRole;
   3054 
   3055     if (cssBox && cssBox->isTextField())
   3056         return TextFieldRole;
   3057 
   3058     if (cssBox && cssBox->isTextArea())
   3059         return TextAreaRole;
   3060 
   3061     if (node && node->hasTagName(inputTag)) {
   3062         HTMLInputElement* input = static_cast<HTMLInputElement*>(node);
   3063         if (input->isCheckbox())
   3064             return CheckBoxRole;
   3065         if (input->isRadioButton())
   3066             return RadioButtonRole;
   3067         if (input->isTextButton())
   3068             return ButtonRole;
   3069     }
   3070 
   3071     if (node && node->hasTagName(buttonTag))
   3072         return ButtonRole;
   3073 
   3074     if (isFileUploadButton())
   3075         return ButtonRole;
   3076 
   3077     if (cssBox && cssBox->isMenuList())
   3078         return PopUpButtonRole;
   3079 
   3080     if (headingLevel())
   3081         return HeadingRole;
   3082 
   3083 #if ENABLE(MATHML)
   3084     if (node && node->hasTagName(MathMLNames::mathTag))
   3085         return DocumentMathRole;
   3086 #endif
   3087 
   3088     if (node && node->hasTagName(ddTag))
   3089         return DefinitionListDefinitionRole;
   3090 
   3091     if (node && node->hasTagName(dtTag))
   3092         return DefinitionListTermRole;
   3093 
   3094     if (node && (node->hasTagName(rpTag) || node->hasTagName(rtTag)))
   3095         return AnnotationRole;
   3096 
   3097 #if PLATFORM(GTK)
   3098     // Gtk ATs expect all tables, data and layout, to be exposed as tables.
   3099     if (node && (node->hasTagName(tdTag) || node->hasTagName(thTag)))
   3100         return CellRole;
   3101 
   3102     if (node && node->hasTagName(trTag))
   3103         return RowRole;
   3104 
   3105     if (node && node->hasTagName(tableTag))
   3106         return TableRole;
   3107 #endif
   3108 
   3109     // Table sections should be ignored.
   3110     if (m_renderer->isTableSection())
   3111         return IgnoredRole;
   3112 
   3113 #if PLATFORM(GTK)
   3114     if (m_renderer->isHR())
   3115         return SplitterRole;
   3116 
   3117     if (node && node->hasTagName(pTag))
   3118         return ParagraphRole;
   3119 
   3120     if (node && node->hasTagName(labelTag))
   3121         return LabelRole;
   3122 
   3123     if (node && node->hasTagName(divTag))
   3124         return DivRole;
   3125 
   3126     if (node && node->hasTagName(formTag))
   3127         return FormRole;
   3128 #else
   3129     if (node && node->hasTagName(labelTag))
   3130         return GroupRole;
   3131 #endif
   3132 
   3133     if (m_renderer->isBlockFlow())
   3134         return GroupRole;
   3135 
   3136     // If the element does not have role, but it has ARIA attributes, accessibility should fallback to exposing it as a group.
   3137     if (supportsARIAAttributes())
   3138         return GroupRole;
   3139 
   3140     return UnknownRole;
   3141 }
   3142 
   3143 AccessibilityOrientation AccessibilityRenderObject::orientation() const
   3144 {
   3145     const AtomicString& ariaOrientation = getAttribute(aria_orientationAttr);
   3146     if (equalIgnoringCase(ariaOrientation, "horizontal"))
   3147         return AccessibilityOrientationHorizontal;
   3148     if (equalIgnoringCase(ariaOrientation, "vertical"))
   3149         return AccessibilityOrientationVertical;
   3150 
   3151     return AccessibilityObject::orientation();
   3152 }
   3153 
   3154 bool AccessibilityRenderObject::inheritsPresentationalRole() const
   3155 {
   3156     // ARIA spec says that when a parent object is presentational, and it has required child elements,
   3157     // those child elements are also presentational. For example, <li> becomes presentational from <ul>.
   3158     // http://www.w3.org/WAI/PF/aria/complete#presentation
   3159     DEFINE_STATIC_LOCAL(HashSet<QualifiedName>, listItemParents, ());
   3160 
   3161     HashSet<QualifiedName>* possibleParentTagNames = 0;
   3162     switch (roleValue()) {
   3163     case ListItemRole:
   3164     case ListMarkerRole:
   3165         if (listItemParents.isEmpty()) {
   3166             listItemParents.add(ulTag);
   3167             listItemParents.add(olTag);
   3168             listItemParents.add(dlTag);
   3169         }
   3170         possibleParentTagNames = &listItemParents;
   3171         break;
   3172     default:
   3173         break;
   3174     }
   3175 
   3176     // Not all elements need to check for this, only ones that are required children.
   3177     if (!possibleParentTagNames)
   3178         return false;
   3179 
   3180     for (AccessibilityObject* parent = parentObject(); parent; parent = parent->parentObject()) {
   3181         if (!parent->isAccessibilityRenderObject())
   3182             continue;
   3183 
   3184         Node* elementNode = static_cast<AccessibilityRenderObject*>(parent)->node();
   3185         if (!elementNode || !elementNode->isElementNode())
   3186             continue;
   3187 
   3188         // If native tag of the parent element matches an acceptable name, then return
   3189         // based on its presentational status.
   3190         if (possibleParentTagNames->contains(static_cast<Element*>(elementNode)->tagQName()))
   3191             return parent->roleValue() == PresentationalRole;
   3192     }
   3193 
   3194     return false;
   3195 }
   3196 
   3197 bool AccessibilityRenderObject::isPresentationalChildOfAriaRole() const
   3198 {
   3199     // Walk the parent chain looking for a parent that has presentational children
   3200     AccessibilityObject* parent;
   3201     for (parent = parentObject(); parent && !parent->ariaRoleHasPresentationalChildren(); parent = parent->parentObject())
   3202     { }
   3203 
   3204     return parent;
   3205 }
   3206 
   3207 bool AccessibilityRenderObject::ariaRoleHasPresentationalChildren() const
   3208 {
   3209     switch (m_ariaRole) {
   3210     case ButtonRole:
   3211     case SliderRole:
   3212     case ImageRole:
   3213     case ProgressIndicatorRole:
   3214     // case SeparatorRole:
   3215         return true;
   3216     default:
   3217         return false;
   3218     }
   3219 }
   3220 
   3221 bool AccessibilityRenderObject::canSetFocusAttribute() const
   3222 {
   3223     ASSERT(m_renderer);
   3224     Node* node = m_renderer->node();
   3225 
   3226     // NOTE: It would be more accurate to ask the document whether setFocusedNode() would
   3227     // do anything.  For example, setFocusedNode() will do nothing if the current focused
   3228     // node will not relinquish the focus.
   3229     if (!node || !node->isElementNode())
   3230         return false;
   3231 
   3232     if (!static_cast<Element*>(node)->isEnabledFormControl())
   3233         return false;
   3234 
   3235     switch (roleValue()) {
   3236     case WebCoreLinkRole:
   3237     case ImageMapLinkRole:
   3238     case TextFieldRole:
   3239     case TextAreaRole:
   3240     case ButtonRole:
   3241     case PopUpButtonRole:
   3242     case CheckBoxRole:
   3243     case RadioButtonRole:
   3244     case SliderRole:
   3245         return true;
   3246     default:
   3247         return node->supportsFocus();
   3248     }
   3249 }
   3250 
   3251 bool AccessibilityRenderObject::canSetExpandedAttribute() const
   3252 {
   3253     // An object can be expanded if it aria-expanded is true or false.
   3254     const AtomicString& ariaExpanded = getAttribute(aria_expandedAttr);
   3255     return equalIgnoringCase(ariaExpanded, "true") || equalIgnoringCase(ariaExpanded, "false");
   3256 }
   3257 
   3258 bool AccessibilityRenderObject::canSetValueAttribute() const
   3259 {
   3260     if (equalIgnoringCase(getAttribute(aria_readonlyAttr), "true"))
   3261         return false;
   3262 
   3263     // Any node could be contenteditable, so isReadOnly should be relied upon
   3264     // for this information for all elements.
   3265     return isProgressIndicator() || isSlider() || !isReadOnly();
   3266 }
   3267 
   3268 bool AccessibilityRenderObject::canSetTextRangeAttributes() const
   3269 {
   3270     return isTextControl();
   3271 }
   3272 
   3273 void AccessibilityRenderObject::contentChanged()
   3274 {
   3275     // If this element supports ARIA live regions, then notify the AT of changes.
   3276     AXObjectCache* cache = axObjectCache();
   3277     for (RenderObject* renderParent = m_renderer; renderParent; renderParent = renderParent->parent()) {
   3278         AccessibilityObject* parent = cache->get(renderParent);
   3279         if (!parent)
   3280             continue;
   3281 
   3282         // If we find a parent that has ARIA live region on, send the notification and stop processing.
   3283         // The spec does not talk about nested live regions.
   3284         if (parent->supportsARIALiveRegion()) {
   3285             axObjectCache()->postNotification(renderParent, AXObjectCache::AXLiveRegionChanged, true);
   3286             break;
   3287         }
   3288     }
   3289 }
   3290 
   3291 void AccessibilityRenderObject::childrenChanged()
   3292 {
   3293     // This method is meant as a quick way of marking a portion of the accessibility tree dirty.
   3294     if (!m_renderer)
   3295         return;
   3296 
   3297     bool sentChildrenChanged = false;
   3298 
   3299     // Go up the accessibility parent chain, but only if the element already exists. This method is
   3300     // called during render layouts, minimal work should be done.
   3301     // If AX elements are created now, they could interrogate the render tree while it's in a funky state.
   3302     // At the same time, process ARIA live region changes.
   3303     for (AccessibilityObject* parent = this; parent; parent = parent->parentObjectIfExists()) {
   3304         if (!parent->isAccessibilityRenderObject())
   3305             continue;
   3306 
   3307         AccessibilityRenderObject* axParent = static_cast<AccessibilityRenderObject*>(parent);
   3308 
   3309         // Send the children changed notification on the first accessibility render object ancestor.
   3310         if (!sentChildrenChanged) {
   3311             axObjectCache()->postNotification(axParent->renderer(), AXObjectCache::AXChildrenChanged, true);
   3312             sentChildrenChanged = true;
   3313         }
   3314 
   3315         // Only do work if the children haven't been marked dirty. This has the effect of blocking
   3316         // future live region change notifications until the AX tree has been accessed again. This
   3317         // is a good performance win for all parties.
   3318         if (!axParent->needsToUpdateChildren()) {
   3319             axParent->setNeedsToUpdateChildren();
   3320 
   3321             // If this element supports ARIA live regions, then notify the AT of changes.
   3322             if (axParent->supportsARIALiveRegion())
   3323                 axObjectCache()->postNotification(axParent->renderer(), AXObjectCache::AXLiveRegionChanged, true);
   3324         }
   3325     }
   3326 }
   3327 
   3328 bool AccessibilityRenderObject::canHaveChildren() const
   3329 {
   3330     if (!m_renderer)
   3331         return false;
   3332 
   3333     // Elements that should not have children
   3334     switch (roleValue()) {
   3335     case ImageRole:
   3336     case ButtonRole:
   3337     case PopUpButtonRole:
   3338     case CheckBoxRole:
   3339     case RadioButtonRole:
   3340     case TabRole:
   3341     case StaticTextRole:
   3342     case ListBoxOptionRole:
   3343     case ScrollBarRole:
   3344         return false;
   3345     default:
   3346         return true;
   3347     }
   3348 }
   3349 
   3350 void AccessibilityRenderObject::clearChildren()
   3351 {
   3352     AccessibilityObject::clearChildren();
   3353     m_childrenDirty = false;
   3354 }
   3355 
   3356 void AccessibilityRenderObject::updateChildrenIfNecessary()
   3357 {
   3358     if (needsToUpdateChildren())
   3359         clearChildren();
   3360 
   3361     AccessibilityObject::updateChildrenIfNecessary();
   3362 }
   3363 
   3364 const AccessibilityObject::AccessibilityChildrenVector& AccessibilityRenderObject::children()
   3365 {
   3366     updateChildrenIfNecessary();
   3367 
   3368     return m_children;
   3369 }
   3370 
   3371 void AccessibilityRenderObject::addChildren()
   3372 {
   3373     // If the need to add more children in addition to existing children arises,
   3374     // childrenChanged should have been called, leaving the object with no children.
   3375     ASSERT(!m_haveChildren);
   3376 
   3377     // nothing to add if there is no RenderObject
   3378     if (!m_renderer)
   3379         return;
   3380 
   3381     m_haveChildren = true;
   3382 
   3383     if (!canHaveChildren())
   3384         return;
   3385 
   3386     // add all unignored acc children
   3387     for (RefPtr<AccessibilityObject> obj = firstChild(); obj; obj = obj->nextSibling()) {
   3388         if (obj->accessibilityIsIgnored()) {
   3389             obj->updateChildrenIfNecessary();
   3390             AccessibilityChildrenVector children = obj->children();
   3391             unsigned length = children.size();
   3392             for (unsigned i = 0; i < length; ++i)
   3393                 m_children.append(children[i]);
   3394         } else {
   3395             ASSERT(obj->parentObject() == this);
   3396             m_children.append(obj);
   3397         }
   3398     }
   3399 
   3400     // FrameView's need to be inserted into the AX hierarchy when encountered.
   3401     if (isAttachment()) {
   3402         Widget* widget = widgetForAttachmentView();
   3403         if (widget && widget->isFrameView())
   3404             m_children.append(axObjectCache()->getOrCreate(widget));
   3405     }
   3406 
   3407     // for a RenderImage, add the <area> elements as individual accessibility objects
   3408     RenderBoxModelObject* cssBox = renderBoxModelObject();
   3409     if (cssBox && cssBox->isRenderImage()) {
   3410         HTMLMapElement* map = toRenderImage(cssBox)->imageMap();
   3411         if (map) {
   3412             for (Node* current = map->firstChild(); current; current = current->traverseNextNode(map)) {
   3413 
   3414                 // add an <area> element for this child if it has a link
   3415                 if (current->hasTagName(areaTag) && current->isLink()) {
   3416                     AccessibilityImageMapLink* areaObject = static_cast<AccessibilityImageMapLink*>(axObjectCache()->getOrCreate(ImageMapLinkRole));
   3417                     areaObject->setHTMLAreaElement(static_cast<HTMLAreaElement*>(current));
   3418                     areaObject->setHTMLMapElement(map);
   3419                     areaObject->setParent(this);
   3420 
   3421                     m_children.append(areaObject);
   3422                 }
   3423             }
   3424         }
   3425     }
   3426 }
   3427 
   3428 const AtomicString& AccessibilityRenderObject::ariaLiveRegionStatus() const
   3429 {
   3430     DEFINE_STATIC_LOCAL(const AtomicString, liveRegionStatusAssertive, ("assertive"));
   3431     DEFINE_STATIC_LOCAL(const AtomicString, liveRegionStatusPolite, ("polite"));
   3432     DEFINE_STATIC_LOCAL(const AtomicString, liveRegionStatusOff, ("off"));
   3433 
   3434     const AtomicString& liveRegionStatus = getAttribute(aria_liveAttr);
   3435     // These roles have implicit live region status.
   3436     if (liveRegionStatus.isEmpty()) {
   3437         switch (roleValue()) {
   3438         case ApplicationAlertDialogRole:
   3439         case ApplicationAlertRole:
   3440             return liveRegionStatusAssertive;
   3441         case ApplicationLogRole:
   3442         case ApplicationStatusRole:
   3443             return liveRegionStatusPolite;
   3444         case ApplicationTimerRole:
   3445         case ApplicationMarqueeRole:
   3446             return liveRegionStatusOff;
   3447         default:
   3448             break;
   3449         }
   3450     }
   3451 
   3452     return liveRegionStatus;
   3453 }
   3454 
   3455 const AtomicString& AccessibilityRenderObject::ariaLiveRegionRelevant() const
   3456 {
   3457     DEFINE_STATIC_LOCAL(const AtomicString, defaultLiveRegionRelevant, ("additions text"));
   3458     const AtomicString& relevant = getAttribute(aria_relevantAttr);
   3459 
   3460     // Default aria-relevant = "additions text".
   3461     if (relevant.isEmpty())
   3462         return defaultLiveRegionRelevant;
   3463 
   3464     return relevant;
   3465 }
   3466 
   3467 bool AccessibilityRenderObject::ariaLiveRegionAtomic() const
   3468 {
   3469     return elementAttributeValue(aria_atomicAttr);
   3470 }
   3471 
   3472 bool AccessibilityRenderObject::ariaLiveRegionBusy() const
   3473 {
   3474     return elementAttributeValue(aria_busyAttr);
   3475 }
   3476 
   3477 void AccessibilityRenderObject::ariaSelectedRows(AccessibilityChildrenVector& result)
   3478 {
   3479     // Get all the rows.
   3480     AccessibilityChildrenVector allRows;
   3481     ariaTreeRows(allRows);
   3482 
   3483     // Determine which rows are selected.
   3484     bool isMulti = isMultiSelectable();
   3485 
   3486     // Prefer active descendant over aria-selected.
   3487     AccessibilityObject* activeDesc = activeDescendant();
   3488     if (activeDesc && (activeDesc->isTreeItem() || activeDesc->isTableRow())) {
   3489         result.append(activeDesc);
   3490         if (!isMulti)
   3491             return;
   3492     }
   3493 
   3494     unsigned count = allRows.size();
   3495     for (unsigned k = 0; k < count; ++k) {
   3496         if (allRows[k]->isSelected()) {
   3497             result.append(allRows[k]);
   3498             if (!isMulti)
   3499                 break;
   3500         }
   3501     }
   3502 }
   3503 
   3504 void AccessibilityRenderObject::ariaListboxSelectedChildren(AccessibilityChildrenVector& result)
   3505 {
   3506     bool isMulti = isMultiSelectable();
   3507 
   3508     AccessibilityChildrenVector childObjects = children();
   3509     unsigned childrenSize = childObjects.size();
   3510     for (unsigned k = 0; k < childrenSize; ++k) {
   3511         // Every child should have aria-role option, and if so, check for selected attribute/state.
   3512         AccessibilityObject* child = childObjects[k].get();
   3513         if (child->isSelected() && child->ariaRoleAttribute() == ListBoxOptionRole) {
   3514             result.append(child);
   3515             if (!isMulti)
   3516                 return;
   3517         }
   3518     }
   3519 }
   3520 
   3521 void AccessibilityRenderObject::selectedChildren(AccessibilityChildrenVector& result)
   3522 {
   3523     ASSERT(result.isEmpty());
   3524 
   3525     // only listboxes should be asked for their selected children.
   3526     AccessibilityRole role = roleValue();
   3527     if (role == ListBoxRole) // native list boxes would be AccessibilityListBoxes, so only check for aria list boxes
   3528         ariaListboxSelectedChildren(result);
   3529     else if (role == TreeRole || role == TreeGridRole || role == TableRole)
   3530         ariaSelectedRows(result);
   3531 }
   3532 
   3533 void AccessibilityRenderObject::ariaListboxVisibleChildren(AccessibilityChildrenVector& result)
   3534 {
   3535     if (!hasChildren())
   3536         addChildren();
   3537 
   3538     unsigned length = m_children.size();
   3539     for (unsigned i = 0; i < length; i++) {
   3540         if (!m_children[i]->isOffScreen())
   3541             result.append(m_children[i]);
   3542     }
   3543 }
   3544 
   3545 void AccessibilityRenderObject::visibleChildren(AccessibilityChildrenVector& result)
   3546 {
   3547     ASSERT(result.isEmpty());
   3548 
   3549     // only listboxes are asked for their visible children.
   3550     if (ariaRoleAttribute() != ListBoxRole) { // native list boxes would be AccessibilityListBoxes, so only check for aria list boxes
   3551         ASSERT_NOT_REACHED();
   3552         return;
   3553     }
   3554     return ariaListboxVisibleChildren(result);
   3555 }
   3556 
   3557 void AccessibilityRenderObject::tabChildren(AccessibilityChildrenVector& result)
   3558 {
   3559     ASSERT(roleValue() == TabListRole);
   3560 
   3561     unsigned length = m_children.size();
   3562     for (unsigned i = 0; i < length; ++i) {
   3563         if (m_children[i]->isTabItem())
   3564             result.append(m_children[i]);
   3565     }
   3566 }
   3567 
   3568 const String& AccessibilityRenderObject::actionVerb() const
   3569 {
   3570     // FIXME: Need to add verbs for select elements.
   3571     DEFINE_STATIC_LOCAL(const String, buttonAction, (AXButtonActionVerb()));
   3572     DEFINE_STATIC_LOCAL(const String, textFieldAction, (AXTextFieldActionVerb()));
   3573     DEFINE_STATIC_LOCAL(const String, radioButtonAction, (AXRadioButtonActionVerb()));
   3574     DEFINE_STATIC_LOCAL(const String, checkedCheckBoxAction, (AXCheckedCheckBoxActionVerb()));
   3575     DEFINE_STATIC_LOCAL(const String, uncheckedCheckBoxAction, (AXUncheckedCheckBoxActionVerb()));
   3576     DEFINE_STATIC_LOCAL(const String, linkAction, (AXLinkActionVerb()));
   3577     DEFINE_STATIC_LOCAL(const String, noAction, ());
   3578 
   3579     switch (roleValue()) {
   3580     case ButtonRole:
   3581         return buttonAction;
   3582     case TextFieldRole:
   3583     case TextAreaRole:
   3584         return textFieldAction;
   3585     case RadioButtonRole:
   3586         return radioButtonAction;
   3587     case CheckBoxRole:
   3588         return isChecked() ? checkedCheckBoxAction : uncheckedCheckBoxAction;
   3589     case LinkRole:
   3590     case WebCoreLinkRole:
   3591         return linkAction;
   3592     default:
   3593         return noAction;
   3594     }
   3595 }
   3596 
   3597 void AccessibilityRenderObject::setAccessibleName(String& name)
   3598 {
   3599     // Setting the accessible name can store the value in the DOM
   3600     if (!m_renderer)
   3601         return;
   3602 
   3603     Node* domNode = 0;
   3604     // For web areas, set the aria-label on the HTML element.
   3605     if (isWebArea())
   3606         domNode = m_renderer->document()->documentElement();
   3607     else
   3608         domNode = m_renderer->node();
   3609 
   3610     if (domNode && domNode->isElementNode())
   3611         static_cast<Element*>(domNode)->setAttribute(aria_labelAttr, name);
   3612 }
   3613 
   3614 void AccessibilityRenderObject::updateBackingStore()
   3615 {
   3616     if (!m_renderer)
   3617         return;
   3618 
   3619     // Updating layout may delete m_renderer and this object.
   3620     m_renderer->document()->updateLayoutIgnorePendingStylesheets();
   3621 }
   3622 
   3623 static bool isLinkable(const AccessibilityRenderObject& object)
   3624 {
   3625     if (!object.renderer())
   3626         return false;
   3627 
   3628     // See https://wiki.mozilla.org/Accessibility/AT-Windows-API for the elements
   3629     // Mozilla considers linkable.
   3630     return object.isLink() || object.isImage() || object.renderer()->isText();
   3631 }
   3632 
   3633 String AccessibilityRenderObject::stringValueForMSAA() const
   3634 {
   3635     if (isLinkable(*this)) {
   3636         Element* anchor = anchorElement();
   3637         if (anchor && anchor->hasTagName(aTag))
   3638             return static_cast<HTMLAnchorElement*>(anchor)->href();
   3639     }
   3640 
   3641     return stringValue();
   3642 }
   3643 
   3644 bool AccessibilityRenderObject::isLinked() const
   3645 {
   3646     if (!isLinkable(*this))
   3647         return false;
   3648 
   3649     Element* anchor = anchorElement();
   3650     if (!anchor || !anchor->hasTagName(aTag))
   3651         return false;
   3652 
   3653     return !static_cast<HTMLAnchorElement*>(anchor)->href().isEmpty();
   3654 }
   3655 
   3656 String AccessibilityRenderObject::nameForMSAA() const
   3657 {
   3658     if (m_renderer && m_renderer->isText())
   3659         return textUnderElement();
   3660 
   3661     return title();
   3662 }
   3663 
   3664 static bool shouldReturnTagNameAsRoleForMSAA(const Element& element)
   3665 {
   3666     // See "document structure",
   3667     // https://wiki.mozilla.org/Accessibility/AT-Windows-API
   3668     // FIXME: Add the other tag names that should be returned as the role.
   3669     return element.hasTagName(h1Tag) || element.hasTagName(h2Tag)
   3670         || element.hasTagName(h3Tag) || element.hasTagName(h4Tag)
   3671         || element.hasTagName(h5Tag) || element.hasTagName(h6Tag);
   3672 }
   3673 
   3674 String AccessibilityRenderObject::stringRoleForMSAA() const
   3675 {
   3676     if (!m_renderer)
   3677         return String();
   3678 
   3679     Node* node = m_renderer->node();
   3680     if (!node || !node->isElementNode())
   3681         return String();
   3682 
   3683     Element* element = static_cast<Element*>(node);
   3684     if (!shouldReturnTagNameAsRoleForMSAA(*element))
   3685         return String();
   3686 
   3687     return element->tagName();
   3688 }
   3689 
   3690 String AccessibilityRenderObject::positionalDescriptionForMSAA() const
   3691 {
   3692     // See "positional descriptions",
   3693     // https://wiki.mozilla.org/Accessibility/AT-Windows-API
   3694     if (isHeading())
   3695         return "L" + String::number(headingLevel());
   3696 
   3697     // FIXME: Add positional descriptions for other elements.
   3698     return String();
   3699 }
   3700 
   3701 String AccessibilityRenderObject::descriptionForMSAA() const
   3702 {
   3703     String description = positionalDescriptionForMSAA();
   3704     if (!description.isEmpty())
   3705         return description;
   3706 
   3707     description = accessibilityDescription();
   3708     if (!description.isEmpty()) {
   3709         // From the Mozilla MSAA implementation:
   3710         // "Signal to screen readers that this description is speakable and is not
   3711         // a formatted positional information description. Don't localize the
   3712         // 'Description: ' part of this string, it will be parsed out by assistive
   3713         // technologies."
   3714         return "Description: " + description;
   3715     }
   3716 
   3717     return String();
   3718 }
   3719 
   3720 static AccessibilityRole msaaRoleForRenderer(const RenderObject* renderer)
   3721 {
   3722     if (!renderer)
   3723         return UnknownRole;
   3724 
   3725     if (renderer->isText())
   3726         return EditableTextRole;
   3727 
   3728     if (renderer->isBoxModelObject() && toRenderBoxModelObject(renderer)->isListItem())
   3729         return ListItemRole;
   3730 
   3731     return UnknownRole;
   3732 }
   3733 
   3734 AccessibilityRole AccessibilityRenderObject::roleValueForMSAA() const
   3735 {
   3736     if (m_roleForMSAA != UnknownRole)
   3737         return m_roleForMSAA;
   3738 
   3739     m_roleForMSAA = msaaRoleForRenderer(m_renderer);
   3740 
   3741     if (m_roleForMSAA == UnknownRole)
   3742         m_roleForMSAA = roleValue();
   3743 
   3744     return m_roleForMSAA;
   3745 }
   3746 
   3747 } // namespace WebCore
   3748