Home | History | Annotate | Download | only in accessibility
      1 /*
      2 * Copyright (C) 2012, Google Inc. All rights reserved.
      3 *
      4 * Redistribution and use in source and binary forms, with or without
      5 * modification, are permitted provided that the following conditions
      6 * are met:
      7 *
      8 * 1.  Redistributions of source code must retain the above copyright
      9 *     notice, this list of conditions and the following disclaimer.
     10 * 2.  Redistributions in binary form must reproduce the above copyright
     11 *     notice, this list of conditions and the following disclaimer in the
     12 *     documentation and/or other materials provided with the distribution.
     13 * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
     14 *     its contributors may be used to endorse or promote products derived
     15 *     from this software without specific prior written permission.
     16 *
     17 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
     18 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     19 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
     20 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
     21 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
     22 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
     23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
     24 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     27 */
     28 
     29 #include "config.h"
     30 #include "core/accessibility/AXNodeObject.h"
     31 
     32 #include "core/InputTypeNames.h"
     33 #include "core/accessibility/AXObjectCache.h"
     34 #include "core/dom/NodeTraversal.h"
     35 #include "core/dom/Text.h"
     36 #include "core/html/HTMLFieldSetElement.h"
     37 #include "core/html/HTMLFrameElementBase.h"
     38 #include "core/html/HTMLInputElement.h"
     39 #include "core/html/HTMLLabelElement.h"
     40 #include "core/html/HTMLLegendElement.h"
     41 #include "core/html/HTMLPlugInElement.h"
     42 #include "core/html/HTMLSelectElement.h"
     43 #include "core/html/HTMLTextAreaElement.h"
     44 #include "core/rendering/RenderObject.h"
     45 #include "platform/UserGestureIndicator.h"
     46 #include "wtf/text/StringBuilder.h"
     47 
     48 
     49 namespace blink {
     50 
     51 using namespace HTMLNames;
     52 
     53 AXNodeObject::AXNodeObject(Node* node)
     54     : AXObject()
     55     , m_ariaRole(UnknownRole)
     56     , m_childrenDirty(false)
     57 #if ENABLE(ASSERT)
     58     , m_initialized(false)
     59 #endif
     60     , m_node(node)
     61 {
     62 }
     63 
     64 PassRefPtr<AXNodeObject> AXNodeObject::create(Node* node)
     65 {
     66     return adoptRef(new AXNodeObject(node));
     67 }
     68 
     69 AXNodeObject::~AXNodeObject()
     70 {
     71     ASSERT(isDetached());
     72 }
     73 
     74 // This function implements the ARIA accessible name as described by the Mozilla
     75 // ARIA Implementer's Guide.
     76 static String accessibleNameForNode(Node* node)
     77 {
     78     if (!node)
     79         return String();
     80 
     81     if (node->isTextNode())
     82         return toText(node)->data();
     83 
     84     if (isHTMLInputElement(*node))
     85         return toHTMLInputElement(*node).value();
     86 
     87     if (node->isHTMLElement()) {
     88         const AtomicString& alt = toHTMLElement(node)->getAttribute(altAttr);
     89         if (!alt.isEmpty())
     90             return alt;
     91     }
     92 
     93     return String();
     94 }
     95 
     96 String AXNodeObject::accessibilityDescriptionForElements(WillBeHeapVector<RawPtrWillBeMember<Element> > &elements) const
     97 {
     98     StringBuilder builder;
     99     unsigned size = elements.size();
    100     for (unsigned i = 0; i < size; ++i) {
    101         Element* idElement = elements[i];
    102 
    103         builder.append(accessibleNameForNode(idElement));
    104         for (Node* n = idElement->firstChild(); n; n = NodeTraversal::next(*n, idElement))
    105             builder.append(accessibleNameForNode(n));
    106 
    107         if (i != size - 1)
    108             builder.append(' ');
    109     }
    110     return builder.toString();
    111 }
    112 
    113 void AXNodeObject::alterSliderValue(bool increase)
    114 {
    115     if (roleValue() != SliderRole)
    116         return;
    117 
    118     if (!getAttribute(stepAttr).isEmpty())
    119         changeValueByStep(increase);
    120     else
    121         changeValueByPercent(increase ? 5 : -5);
    122 }
    123 
    124 String AXNodeObject::ariaAccessibilityDescription() const
    125 {
    126     String ariaLabeledBy = ariaLabeledByAttribute();
    127     if (!ariaLabeledBy.isEmpty())
    128         return ariaLabeledBy;
    129 
    130     const AtomicString& ariaLabel = getAttribute(aria_labelAttr);
    131     if (!ariaLabel.isEmpty())
    132         return ariaLabel;
    133 
    134     return String();
    135 }
    136 
    137 
    138 void AXNodeObject::ariaLabeledByElements(WillBeHeapVector<RawPtrWillBeMember<Element> >& elements) const
    139 {
    140     elementsFromAttribute(elements, aria_labeledbyAttr);
    141     if (!elements.size())
    142         elementsFromAttribute(elements, aria_labelledbyAttr);
    143 }
    144 
    145 void AXNodeObject::changeValueByStep(bool increase)
    146 {
    147     float step = stepValueForRange();
    148     float value = valueForRange();
    149 
    150     value += increase ? step : -step;
    151 
    152     setValue(String::number(value));
    153 
    154     axObjectCache()->postNotification(node(), AXObjectCache::AXValueChanged, true);
    155 }
    156 
    157 bool AXNodeObject::computeAccessibilityIsIgnored() const
    158 {
    159 #if ENABLE(ASSERT)
    160     // Double-check that an AXObject is never accessed before
    161     // it's been initialized.
    162     ASSERT(m_initialized);
    163 #endif
    164 
    165     // If this element is within a parent that cannot have children, it should not be exposed.
    166     if (isDescendantOfBarrenParent())
    167         return true;
    168 
    169     // Ignore labels that are already referenced by a control's title UI element.
    170     AXObject* controlObject = correspondingControlForLabelElement();
    171     if (controlObject && !controlObject->exposesTitleUIElement() && controlObject->isCheckboxOrRadio())
    172         return true;
    173 
    174     return m_role == UnknownRole;
    175 }
    176 
    177 AccessibilityRole AXNodeObject::determineAccessibilityRole()
    178 {
    179     if (!node())
    180         return UnknownRole;
    181 
    182     m_ariaRole = determineAriaRoleAttribute();
    183 
    184     AccessibilityRole ariaRole = ariaRoleAttribute();
    185     if (ariaRole != UnknownRole)
    186         return ariaRole;
    187 
    188     if (node()->isLink())
    189         return LinkRole;
    190     if (node()->isTextNode())
    191         return StaticTextRole;
    192     if (isHTMLButtonElement(*node()))
    193         return buttonRoleType();
    194     if (isHTMLDetailsElement(*node()))
    195         return DetailsRole;
    196     if (isHTMLSummaryElement(*node())) {
    197         if (node()->parentNode() && isHTMLDetailsElement(node()->parentNode()))
    198             return DisclosureTriangleRole;
    199         return UnknownRole;
    200     }
    201 
    202     if (isHTMLInputElement(*node())) {
    203         HTMLInputElement& input = toHTMLInputElement(*node());
    204         const AtomicString& type = input.type();
    205         if (type == InputTypeNames::checkbox)
    206             return CheckBoxRole;
    207         if (type == InputTypeNames::radio)
    208             return RadioButtonRole;
    209         if (input.isTextButton())
    210             return buttonRoleType();
    211         if (type == InputTypeNames::range)
    212             return SliderRole;
    213         if (type == InputTypeNames::color)
    214             return ColorWellRole;
    215         return TextFieldRole;
    216     }
    217     if (isHTMLSelectElement(*node())) {
    218         HTMLSelectElement& selectElement = toHTMLSelectElement(*node());
    219         return selectElement.multiple() ? ListBoxRole : PopUpButtonRole;
    220     }
    221     if (isHTMLTextAreaElement(*node()))
    222         return TextAreaRole;
    223     if (headingLevel())
    224         return HeadingRole;
    225     if (isHTMLDivElement(*node()))
    226         return DivRole;
    227     if (isHTMLParagraphElement(*node()))
    228         return ParagraphRole;
    229     if (isHTMLLabelElement(*node()))
    230         return LabelRole;
    231     if (node()->isElementNode() && node()->hasTagName(figcaptionTag))
    232         return FigcaptionRole;
    233     if (node()->isElementNode() && node()->hasTagName(figureTag))
    234         return FigureRole;
    235     if (node()->isElementNode() && toElement(node())->isFocusable())
    236         return GroupRole;
    237     if (isHTMLAnchorElement(*node()) && isClickable())
    238         return LinkRole;
    239     if (isHTMLIFrameElement(*node()))
    240         return IframeRole;
    241     if (isEmbeddedObject())
    242         return EmbeddedObjectRole;
    243 
    244     return UnknownRole;
    245 }
    246 
    247 AccessibilityRole AXNodeObject::determineAriaRoleAttribute() const
    248 {
    249     const AtomicString& ariaRole = getAttribute(roleAttr);
    250     if (ariaRole.isNull() || ariaRole.isEmpty())
    251         return UnknownRole;
    252 
    253     AccessibilityRole role = ariaRoleToWebCoreRole(ariaRole);
    254 
    255     // ARIA states if an item can get focus, it should not be presentational.
    256     if ((role == NoneRole || role == PresentationalRole) && canSetFocusAttribute())
    257         return UnknownRole;
    258 
    259     if (role == ButtonRole)
    260         role = buttonRoleType();
    261 
    262     if (role == TextAreaRole && !ariaIsMultiline())
    263         role = TextFieldRole;
    264 
    265     role = remapAriaRoleDueToParent(role);
    266 
    267     if (role)
    268         return role;
    269 
    270     return UnknownRole;
    271 }
    272 
    273 void AXNodeObject::elementsFromAttribute(WillBeHeapVector<RawPtrWillBeMember<Element> >& elements, const QualifiedName& attribute) const
    274 {
    275     Node* node = this->node();
    276     if (!node || !node->isElementNode())
    277         return;
    278 
    279     TreeScope& scope = node->treeScope();
    280 
    281     String idList = getAttribute(attribute).string();
    282     if (idList.isEmpty())
    283         return;
    284 
    285     idList.replace('\n', ' ');
    286     Vector<String> idVector;
    287     idList.split(' ', idVector);
    288 
    289     unsigned size = idVector.size();
    290     for (unsigned i = 0; i < size; ++i) {
    291         AtomicString idName(idVector[i]);
    292         Element* idElement = scope.getElementById(idName);
    293         if (idElement)
    294             elements.append(idElement);
    295     }
    296 }
    297 
    298 // If you call node->hasEditableStyle() since that will return true if an ancestor is editable.
    299 // This only returns true if this is the element that actually has the contentEditable attribute set.
    300 bool AXNodeObject::hasContentEditableAttributeSet() const
    301 {
    302     if (!hasAttribute(contenteditableAttr))
    303         return false;
    304     const AtomicString& contentEditableValue = getAttribute(contenteditableAttr);
    305     // Both "true" (case-insensitive) and the empty string count as true.
    306     return contentEditableValue.isEmpty() || equalIgnoringCase(contentEditableValue, "true");
    307 }
    308 
    309 bool AXNodeObject::isDescendantOfBarrenParent() const
    310 {
    311     for (AXObject* object = parentObject(); object; object = object->parentObject()) {
    312         if (!object->canHaveChildren())
    313             return true;
    314     }
    315 
    316     return false;
    317 }
    318 
    319 bool AXNodeObject::isGenericFocusableElement() const
    320 {
    321     if (!canSetFocusAttribute())
    322         return false;
    323 
    324     // If it's a control, it's not generic.
    325     if (isControl())
    326         return false;
    327 
    328     // If it has an aria role, it's not generic.
    329     if (m_ariaRole != UnknownRole)
    330         return false;
    331 
    332     // If the content editable attribute is set on this element, that's the reason
    333     // it's focusable, and existing logic should handle this case already - so it's not a
    334     // generic focusable element.
    335 
    336     if (hasContentEditableAttributeSet())
    337         return false;
    338 
    339     // The web area and body element are both focusable, but existing logic handles these
    340     // cases already, so we don't need to include them here.
    341     if (roleValue() == WebAreaRole)
    342         return false;
    343     if (isHTMLBodyElement(node()))
    344         return false;
    345 
    346     // An SVG root is focusable by default, but it's probably not interactive, so don't
    347     // include it. It can still be made accessible by giving it an ARIA role.
    348     if (roleValue() == SVGRootRole)
    349         return false;
    350 
    351     return true;
    352 }
    353 
    354 HTMLLabelElement* AXNodeObject::labelForElement(Element* element) const
    355 {
    356     if (!element->isHTMLElement() || !toHTMLElement(element)->isLabelable())
    357         return 0;
    358 
    359     const AtomicString& id = element->getIdAttribute();
    360     if (!id.isEmpty()) {
    361         if (HTMLLabelElement* label = element->treeScope().labelElementForId(id))
    362             return label;
    363     }
    364 
    365     return Traversal<HTMLLabelElement>::firstAncestor(*element);
    366 }
    367 
    368 AXObject* AXNodeObject::menuButtonForMenu() const
    369 {
    370     Element* menuItem = menuItemElementForMenu();
    371 
    372     if (menuItem) {
    373         // ARIA just has generic menu items. AppKit needs to know if this is a top level items like MenuBarButton or MenuBarItem
    374         AXObject* menuItemAX = axObjectCache()->getOrCreate(menuItem);
    375         if (menuItemAX && menuItemAX->isMenuButton())
    376             return menuItemAX;
    377     }
    378     return 0;
    379 }
    380 
    381 static Element* siblingWithAriaRole(String role, Node* node)
    382 {
    383     Node* parent = node->parentNode();
    384     if (!parent)
    385         return 0;
    386 
    387     for (Element* sibling = ElementTraversal::firstChild(*parent); sibling; sibling = ElementTraversal::nextSibling(*sibling)) {
    388         const AtomicString& siblingAriaRole = sibling->getAttribute(roleAttr);
    389         if (equalIgnoringCase(siblingAriaRole, role))
    390             return sibling;
    391     }
    392 
    393     return 0;
    394 }
    395 
    396 Element* AXNodeObject::menuItemElementForMenu() const
    397 {
    398     if (ariaRoleAttribute() != MenuRole)
    399         return 0;
    400 
    401     return siblingWithAriaRole("menuitem", node());
    402 }
    403 
    404 Element* AXNodeObject::mouseButtonListener() const
    405 {
    406     Node* node = this->node();
    407     if (!node)
    408         return 0;
    409 
    410     // check if our parent is a mouse button listener
    411     if (!node->isElementNode())
    412         node = node->parentElement();
    413 
    414     if (!node)
    415         return 0;
    416 
    417     // FIXME: Do the continuation search like anchorElement does
    418     for (Element* element = toElement(node); element; element = element->parentElement()) {
    419         if (element->getAttributeEventListener(EventTypeNames::click) || element->getAttributeEventListener(EventTypeNames::mousedown) || element->getAttributeEventListener(EventTypeNames::mouseup))
    420             return element;
    421     }
    422 
    423     return 0;
    424 }
    425 
    426 AccessibilityRole AXNodeObject::remapAriaRoleDueToParent(AccessibilityRole role) const
    427 {
    428     // Some objects change their role based on their parent.
    429     // However, asking for the unignoredParent calls accessibilityIsIgnored(), which can trigger a loop.
    430     // While inside the call stack of creating an element, we need to avoid accessibilityIsIgnored().
    431     // https://bugs.webkit.org/show_bug.cgi?id=65174
    432 
    433     if (role != ListBoxOptionRole && role != MenuItemRole)
    434         return role;
    435 
    436     for (AXObject* parent = parentObject(); parent && !parent->accessibilityIsIgnored(); parent = parent->parentObject()) {
    437         AccessibilityRole parentAriaRole = parent->ariaRoleAttribute();
    438 
    439         // Selects and listboxes both have options as child roles, but they map to different roles within WebCore.
    440         if (role == ListBoxOptionRole && parentAriaRole == MenuRole)
    441             return MenuItemRole;
    442         // An aria "menuitem" may map to MenuButton or MenuItem depending on its parent.
    443         if (role == MenuItemRole && parentAriaRole == GroupRole)
    444             return MenuButtonRole;
    445 
    446         // If the parent had a different role, then we don't need to continue searching up the chain.
    447         if (parentAriaRole)
    448             break;
    449     }
    450 
    451     return role;
    452 }
    453 
    454 void AXNodeObject::init()
    455 {
    456 #if ENABLE(ASSERT)
    457     ASSERT(!m_initialized);
    458     m_initialized = true;
    459 #endif
    460     m_role = determineAccessibilityRole();
    461 }
    462 
    463 void AXNodeObject::detach()
    464 {
    465     clearChildren();
    466     AXObject::detach();
    467     m_node = 0;
    468 }
    469 
    470 bool AXNodeObject::isAnchor() const
    471 {
    472     return !isNativeImage() && isLink();
    473 }
    474 
    475 bool AXNodeObject::isControl() const
    476 {
    477     Node* node = this->node();
    478     if (!node)
    479         return false;
    480 
    481     return ((node->isElementNode() && toElement(node)->isFormControlElement())
    482         || AXObject::isARIAControl(ariaRoleAttribute()));
    483 }
    484 
    485 bool AXNodeObject::isEmbeddedObject() const
    486 {
    487     return isHTMLPlugInElement(node());
    488 }
    489 
    490 bool AXNodeObject::isFieldset() const
    491 {
    492     return isHTMLFieldSetElement(node());
    493 }
    494 
    495 bool AXNodeObject::isHeading() const
    496 {
    497     return roleValue() == HeadingRole;
    498 }
    499 
    500 bool AXNodeObject::isHovered() const
    501 {
    502     Node* node = this->node();
    503     if (!node)
    504         return false;
    505 
    506     return node->hovered();
    507 }
    508 
    509 bool AXNodeObject::isImage() const
    510 {
    511     return roleValue() == ImageRole;
    512 }
    513 
    514 bool AXNodeObject::isImageButton() const
    515 {
    516     return isNativeImage() && isButton();
    517 }
    518 
    519 bool AXNodeObject::isInputImage() const
    520 {
    521     Node* node = this->node();
    522     if (roleValue() == ButtonRole && isHTMLInputElement(node))
    523         return toHTMLInputElement(*node).type() == InputTypeNames::image;
    524 
    525     return false;
    526 }
    527 
    528 bool AXNodeObject::isLink() const
    529 {
    530     return roleValue() == LinkRole;
    531 }
    532 
    533 bool AXNodeObject::isMenu() const
    534 {
    535     return roleValue() == MenuRole;
    536 }
    537 
    538 bool AXNodeObject::isMenuButton() const
    539 {
    540     return roleValue() == MenuButtonRole;
    541 }
    542 
    543 bool AXNodeObject::isMultiSelectable() const
    544 {
    545     const AtomicString& ariaMultiSelectable = getAttribute(aria_multiselectableAttr);
    546     if (equalIgnoringCase(ariaMultiSelectable, "true"))
    547         return true;
    548     if (equalIgnoringCase(ariaMultiSelectable, "false"))
    549         return false;
    550 
    551     return isHTMLSelectElement(node()) && toHTMLSelectElement(*node()).multiple();
    552 }
    553 
    554 bool AXNodeObject::isNativeCheckboxOrRadio() const
    555 {
    556     Node* node = this->node();
    557     if (!isHTMLInputElement(node))
    558         return false;
    559 
    560     HTMLInputElement* input = toHTMLInputElement(node);
    561     return input->type() == InputTypeNames::checkbox || input->type() == InputTypeNames::radio;
    562 }
    563 
    564 bool AXNodeObject::isNativeImage() const
    565 {
    566     Node* node = this->node();
    567     if (!node)
    568         return false;
    569 
    570     if (isHTMLImageElement(*node))
    571         return true;
    572 
    573     if (isHTMLPlugInElement(*node))
    574         return true;
    575 
    576     if (isHTMLInputElement(*node))
    577         return toHTMLInputElement(*node).type() == InputTypeNames::image;
    578 
    579     return false;
    580 }
    581 
    582 bool AXNodeObject::isNativeTextControl() const
    583 {
    584     Node* node = this->node();
    585     if (!node)
    586         return false;
    587 
    588     if (isHTMLTextAreaElement(*node))
    589         return true;
    590 
    591     if (isHTMLInputElement(*node))
    592         return toHTMLInputElement(node)->isTextField();
    593 
    594     return false;
    595 }
    596 
    597 bool AXNodeObject::isNonNativeTextControl() const
    598 {
    599     if (isNativeTextControl())
    600         return false;
    601 
    602     if (hasContentEditableAttributeSet())
    603         return true;
    604 
    605     if (isARIATextControl())
    606         return true;
    607 
    608     return false;
    609 }
    610 
    611 bool AXNodeObject::isPasswordField() const
    612 {
    613     Node* node = this->node();
    614     if (!isHTMLInputElement(node))
    615         return false;
    616 
    617     if (ariaRoleAttribute() != UnknownRole)
    618         return false;
    619 
    620     return toHTMLInputElement(node)->type() == InputTypeNames::password;
    621 }
    622 
    623 bool AXNodeObject::isProgressIndicator() const
    624 {
    625     return roleValue() == ProgressIndicatorRole;
    626 }
    627 
    628 bool AXNodeObject::isSlider() const
    629 {
    630     return roleValue() == SliderRole;
    631 }
    632 
    633 bool AXNodeObject::isChecked() const
    634 {
    635     Node* node = this->node();
    636     if (!node)
    637         return false;
    638 
    639     // First test for native checkedness semantics
    640     if (isHTMLInputElement(*node))
    641         return toHTMLInputElement(*node).shouldAppearChecked();
    642 
    643     // Else, if this is an ARIA checkbox or radio, respect the aria-checked attribute
    644     AccessibilityRole ariaRole = ariaRoleAttribute();
    645     if (ariaRole == RadioButtonRole || ariaRole == CheckBoxRole) {
    646         if (equalIgnoringCase(getAttribute(aria_checkedAttr), "true"))
    647             return true;
    648         return false;
    649     }
    650 
    651     // Otherwise it's not checked
    652     return false;
    653 }
    654 
    655 bool AXNodeObject::isClickable() const
    656 {
    657     if (node()) {
    658         if (node()->isElementNode() && toElement(node())->isDisabledFormControl())
    659             return false;
    660 
    661         // Note: we can't call node()->willRespondToMouseClickEvents() because that triggers a style recalc and can delete this.
    662         if (node()->hasEventListeners(EventTypeNames::mouseup) || node()->hasEventListeners(EventTypeNames::mousedown) || node()->hasEventListeners(EventTypeNames::click) || node()->hasEventListeners(EventTypeNames::DOMActivate))
    663             return true;
    664     }
    665 
    666     return AXObject::isClickable();
    667 }
    668 
    669 bool AXNodeObject::isEnabled() const
    670 {
    671     if (equalIgnoringCase(getAttribute(aria_disabledAttr), "true"))
    672         return false;
    673 
    674     Node* node = this->node();
    675     if (!node || !node->isElementNode())
    676         return true;
    677 
    678     return !toElement(node)->isDisabledFormControl();
    679 }
    680 
    681 bool AXNodeObject::isIndeterminate() const
    682 {
    683     Node* node = this->node();
    684     if (!isHTMLInputElement(node))
    685         return false;
    686 
    687     return toHTMLInputElement(node)->shouldAppearIndeterminate();
    688 }
    689 
    690 bool AXNodeObject::isPressed() const
    691 {
    692     if (!isButton())
    693         return false;
    694 
    695     Node* node = this->node();
    696     if (!node)
    697         return false;
    698 
    699     // If this is an ARIA button, check the aria-pressed attribute rather than node()->active()
    700     if (ariaRoleAttribute() == ButtonRole) {
    701         if (equalIgnoringCase(getAttribute(aria_pressedAttr), "true"))
    702             return true;
    703         return false;
    704     }
    705 
    706     return node->active();
    707 }
    708 
    709 bool AXNodeObject::isReadOnly() const
    710 {
    711     Node* node = this->node();
    712     if (!node)
    713         return true;
    714 
    715     if (isHTMLTextAreaElement(*node))
    716         return toHTMLTextAreaElement(*node).isReadOnly();
    717 
    718     if (isHTMLInputElement(*node)) {
    719         HTMLInputElement& input = toHTMLInputElement(*node);
    720         if (input.isTextField())
    721             return input.isReadOnly();
    722     }
    723 
    724     return !node->hasEditableStyle();
    725 }
    726 
    727 bool AXNodeObject::isRequired() const
    728 {
    729     if (equalIgnoringCase(getAttribute(aria_requiredAttr), "true"))
    730         return true;
    731 
    732     Node* n = this->node();
    733     if (n && (n->isElementNode() && toElement(n)->isFormControlElement()))
    734         return toHTMLFormControlElement(n)->isRequired();
    735 
    736     return false;
    737 }
    738 
    739 bool AXNodeObject::canSetFocusAttribute() const
    740 {
    741     Node* node = this->node();
    742     if (!node)
    743         return false;
    744 
    745     if (isWebArea())
    746         return true;
    747 
    748     // NOTE: It would be more accurate to ask the document whether setFocusedNode() would
    749     // do anything. For example, setFocusedNode() will do nothing if the current focused
    750     // node will not relinquish the focus.
    751     if (!node)
    752         return false;
    753 
    754     if (isDisabledFormControl(node))
    755         return false;
    756 
    757     return node->isElementNode() && toElement(node)->supportsFocus();
    758 }
    759 
    760 bool AXNodeObject::canSetValueAttribute() const
    761 {
    762     if (equalIgnoringCase(getAttribute(aria_readonlyAttr), "true"))
    763         return false;
    764 
    765     if (isProgressIndicator() || isSlider())
    766         return true;
    767 
    768     if (isTextControl() && !isNativeTextControl())
    769         return true;
    770 
    771     // Any node could be contenteditable, so isReadOnly should be relied upon
    772     // for this information for all elements.
    773     return !isReadOnly();
    774 }
    775 
    776 bool AXNodeObject::canvasHasFallbackContent() const
    777 {
    778     Node* node = this->node();
    779     if (!isHTMLCanvasElement(node))
    780         return false;
    781 
    782     // If it has any children that are elements, we'll assume it might be fallback
    783     // content. If it has no children or its only children are not elements
    784     // (e.g. just text nodes), it doesn't have fallback content.
    785     return ElementTraversal::firstChild(*node);
    786 }
    787 
    788 bool AXNodeObject::exposesTitleUIElement() const
    789 {
    790     if (!isControl())
    791         return false;
    792 
    793     // If this control is ignored (because it's invisible),
    794     // then the label needs to be exposed so it can be visible to accessibility.
    795     if (accessibilityIsIgnored())
    796         return true;
    797 
    798     // ARIA: section 2A, bullet #3 says if aria-labeledby or aria-label appears, it should
    799     // override the "label" element association.
    800     bool hasTextAlternative = (!ariaLabeledByAttribute().isEmpty() || !getAttribute(aria_labelAttr).isEmpty());
    801 
    802     // Checkboxes and radio buttons use the text of their title ui element as their own AXTitle.
    803     // This code controls whether the title ui element should appear in the AX tree (usually, no).
    804     // It should appear if the control already has a label (which will be used as the AXTitle instead).
    805     if (isCheckboxOrRadio())
    806         return hasTextAlternative;
    807 
    808     // When controls have their own descriptions, the title element should be ignored.
    809     if (hasTextAlternative)
    810         return false;
    811 
    812     return true;
    813 }
    814 
    815 int AXNodeObject::headingLevel() const
    816 {
    817     // headings can be in block flow and non-block flow
    818     Node* node = this->node();
    819     if (!node)
    820         return 0;
    821 
    822     if (ariaRoleAttribute() == HeadingRole)
    823         return getAttribute(aria_levelAttr).toInt();
    824 
    825     if (!node->isHTMLElement())
    826         return 0;
    827 
    828     HTMLElement& element = toHTMLElement(*node);
    829     if (element.hasTagName(h1Tag))
    830         return 1;
    831 
    832     if (element.hasTagName(h2Tag))
    833         return 2;
    834 
    835     if (element.hasTagName(h3Tag))
    836         return 3;
    837 
    838     if (element.hasTagName(h4Tag))
    839         return 4;
    840 
    841     if (element.hasTagName(h5Tag))
    842         return 5;
    843 
    844     if (element.hasTagName(h6Tag))
    845         return 6;
    846 
    847     return 0;
    848 }
    849 
    850 unsigned AXNodeObject::hierarchicalLevel() const
    851 {
    852     Node* node = this->node();
    853     if (!node || !node->isElementNode())
    854         return 0;
    855     Element* element = toElement(node);
    856     String ariaLevel = element->getAttribute(aria_levelAttr);
    857     if (!ariaLevel.isEmpty())
    858         return ariaLevel.toInt();
    859 
    860     // Only tree item will calculate its level through the DOM currently.
    861     if (roleValue() != TreeItemRole)
    862         return 0;
    863 
    864     // Hierarchy leveling starts at 1, to match the aria-level spec.
    865     // We measure tree hierarchy by the number of groups that the item is within.
    866     unsigned level = 1;
    867     for (AXObject* parent = parentObject(); parent; parent = parent->parentObject()) {
    868         AccessibilityRole parentRole = parent->roleValue();
    869         if (parentRole == GroupRole)
    870             level++;
    871         else if (parentRole == TreeRole)
    872             break;
    873     }
    874 
    875     return level;
    876 }
    877 
    878 String AXNodeObject::text() const
    879 {
    880     // If this is a user defined static text, use the accessible name computation.
    881     if (ariaRoleAttribute() == StaticTextRole)
    882         return ariaAccessibilityDescription();
    883 
    884     if (!isTextControl())
    885         return String();
    886 
    887     Node* node = this->node();
    888     if (!node)
    889         return String();
    890 
    891     if (isNativeTextControl() && (isHTMLTextAreaElement(*node) || isHTMLInputElement(*node)))
    892         return toHTMLTextFormControlElement(*node).value();
    893 
    894     if (!node->isElementNode())
    895         return String();
    896 
    897     return toElement(node)->innerText();
    898 }
    899 
    900 AXObject* AXNodeObject::titleUIElement() const
    901 {
    902     if (!node() || !node()->isElementNode())
    903         return 0;
    904 
    905     if (isFieldset())
    906         return axObjectCache()->getOrCreate(toHTMLFieldSetElement(node())->legend());
    907 
    908     HTMLLabelElement* label = labelForElement(toElement(node()));
    909     if (label)
    910         return axObjectCache()->getOrCreate(label);
    911 
    912     return 0;
    913 }
    914 
    915 AccessibilityButtonState AXNodeObject::checkboxOrRadioValue() const
    916 {
    917     if (isNativeCheckboxOrRadio())
    918         return isChecked() ? ButtonStateOn : ButtonStateOff;
    919 
    920     return AXObject::checkboxOrRadioValue();
    921 }
    922 
    923 void AXNodeObject::colorValue(int& r, int& g, int& b) const
    924 {
    925     r = 0;
    926     g = 0;
    927     b = 0;
    928 
    929     if (!isColorWell())
    930         return;
    931 
    932     if (!isHTMLInputElement(node()))
    933         return;
    934 
    935     HTMLInputElement* input = toHTMLInputElement(node());
    936     const AtomicString& type = input->getAttribute(typeAttr);
    937     if (!equalIgnoringCase(type, "color"))
    938         return;
    939 
    940     // HTMLInputElement::value always returns a string parseable by Color.
    941     Color color;
    942     bool success = color.setFromString(input->value());
    943     ASSERT_UNUSED(success, success);
    944     r = color.red();
    945     g = color.green();
    946     b = color.blue();
    947 }
    948 
    949 String AXNodeObject::valueDescription() const
    950 {
    951     if (!supportsRangeValue())
    952         return String();
    953 
    954     return getAttribute(aria_valuetextAttr).string();
    955 }
    956 
    957 float AXNodeObject::valueForRange() const
    958 {
    959     if (hasAttribute(aria_valuenowAttr))
    960         return getAttribute(aria_valuenowAttr).toFloat();
    961 
    962     if (isHTMLInputElement(node())) {
    963         HTMLInputElement& input = toHTMLInputElement(*node());
    964         if (input.type() == InputTypeNames::range)
    965             return input.valueAsNumber();
    966     }
    967 
    968     return 0.0;
    969 }
    970 
    971 float AXNodeObject::maxValueForRange() const
    972 {
    973     if (hasAttribute(aria_valuemaxAttr))
    974         return getAttribute(aria_valuemaxAttr).toFloat();
    975 
    976     if (isHTMLInputElement(node())) {
    977         HTMLInputElement& input = toHTMLInputElement(*node());
    978         if (input.type() == InputTypeNames::range)
    979             return input.maximum();
    980     }
    981 
    982     return 0.0;
    983 }
    984 
    985 float AXNodeObject::minValueForRange() const
    986 {
    987     if (hasAttribute(aria_valueminAttr))
    988         return getAttribute(aria_valueminAttr).toFloat();
    989 
    990     if (isHTMLInputElement(node())) {
    991         HTMLInputElement& input = toHTMLInputElement(*node());
    992         if (input.type() == InputTypeNames::range)
    993             return input.minimum();
    994     }
    995 
    996     return 0.0;
    997 }
    998 
    999 float AXNodeObject::stepValueForRange() const
   1000 {
   1001     return getAttribute(stepAttr).toFloat();
   1002 }
   1003 
   1004 String AXNodeObject::stringValue() const
   1005 {
   1006     Node* node = this->node();
   1007     if (!node)
   1008         return String();
   1009 
   1010     if (ariaRoleAttribute() == StaticTextRole) {
   1011         String staticText = text();
   1012         if (!staticText.length())
   1013             staticText = textUnderElement();
   1014         return staticText;
   1015     }
   1016 
   1017     if (node->isTextNode())
   1018         return textUnderElement();
   1019 
   1020     if (isHTMLSelectElement(*node)) {
   1021         HTMLSelectElement& selectElement = toHTMLSelectElement(*node);
   1022         int selectedIndex = selectElement.selectedIndex();
   1023         const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& listItems = selectElement.listItems();
   1024         if (selectedIndex >= 0 && static_cast<size_t>(selectedIndex) < listItems.size()) {
   1025             const AtomicString& overriddenDescription = listItems[selectedIndex]->fastGetAttribute(aria_labelAttr);
   1026             if (!overriddenDescription.isNull())
   1027                 return overriddenDescription;
   1028         }
   1029         if (!selectElement.multiple())
   1030             return selectElement.value();
   1031         return String();
   1032     }
   1033 
   1034     if (isTextControl())
   1035         return text();
   1036 
   1037     // FIXME: We might need to implement a value here for more types
   1038     // FIXME: It would be better not to advertise a value at all for the types for which we don't implement one;
   1039     // this would require subclassing or making accessibilityAttributeNames do something other than return a
   1040     // single static array.
   1041     return String();
   1042 }
   1043 
   1044 String AXNodeObject::ariaDescribedByAttribute() const
   1045 {
   1046     WillBeHeapVector<RawPtrWillBeMember<Element> > elements;
   1047     elementsFromAttribute(elements, aria_describedbyAttr);
   1048 
   1049     return accessibilityDescriptionForElements(elements);
   1050 }
   1051 
   1052 
   1053 String AXNodeObject::ariaLabeledByAttribute() const
   1054 {
   1055     WillBeHeapVector<RawPtrWillBeMember<Element> > elements;
   1056     ariaLabeledByElements(elements);
   1057 
   1058     return accessibilityDescriptionForElements(elements);
   1059 }
   1060 
   1061 AccessibilityRole AXNodeObject::ariaRoleAttribute() const
   1062 {
   1063     return m_ariaRole;
   1064 }
   1065 
   1066 // When building the textUnderElement for an object, determine whether or not
   1067 // we should include the inner text of this given descendant object or skip it.
   1068 static bool shouldUseAccessiblityObjectInnerText(AXObject* obj)
   1069 {
   1070     // Consider this hypothetical example:
   1071     // <div tabindex=0>
   1072     //   <h2>
   1073     //     Table of contents
   1074     //   </h2>
   1075     //   <a href="#start">Jump to start of book</a>
   1076     //   <ul>
   1077     //     <li><a href="#1">Chapter 1</a></li>
   1078     //     <li><a href="#1">Chapter 2</a></li>
   1079     //   </ul>
   1080     // </div>
   1081     //
   1082     // The goal is to return a reasonable title for the outer container div, because
   1083     // it's focusable - but without making its title be the full inner text, which is
   1084     // quite long. As a heuristic, skip links, controls, and elements that are usually
   1085     // containers with lots of children.
   1086 
   1087     // Skip hidden children
   1088     if (obj->isInertOrAriaHidden())
   1089         return false;
   1090 
   1091     // Skip focusable children, so we don't include the text of links and controls.
   1092     if (obj->canSetFocusAttribute())
   1093         return false;
   1094 
   1095     // Skip big container elements like lists, tables, etc.
   1096     if (obj->isList() || obj->isAXTable() || obj->isTree() || obj->isCanvas())
   1097         return false;
   1098 
   1099     return true;
   1100 }
   1101 
   1102 String AXNodeObject::textUnderElement() const
   1103 {
   1104     Node* node = this->node();
   1105     if (node && node->isTextNode())
   1106         return toText(node)->wholeText();
   1107 
   1108     StringBuilder builder;
   1109     for (AXObject* child = firstChild(); child; child = child->nextSibling()) {
   1110         if (!shouldUseAccessiblityObjectInnerText(child))
   1111             continue;
   1112 
   1113         if (child->isAXNodeObject()) {
   1114             Vector<AccessibilityText> textOrder;
   1115             toAXNodeObject(child)->alternativeText(textOrder);
   1116             if (textOrder.size() > 0) {
   1117                 builder.append(textOrder[0].text);
   1118                 continue;
   1119             }
   1120         }
   1121 
   1122         builder.append(child->textUnderElement());
   1123     }
   1124 
   1125     return builder.toString();
   1126 }
   1127 
   1128 String AXNodeObject::accessibilityDescription() const
   1129 {
   1130     // Static text should not have a description, it should only have a stringValue.
   1131     if (roleValue() == StaticTextRole)
   1132         return String();
   1133 
   1134     String ariaDescription = ariaAccessibilityDescription();
   1135     if (!ariaDescription.isEmpty())
   1136         return ariaDescription;
   1137 
   1138     if (isImage() || isInputImage() || isNativeImage() || isCanvas()) {
   1139         // Images should use alt as long as the attribute is present, even if empty.
   1140         // Otherwise, it should fallback to other methods, like the title attribute.
   1141         const AtomicString& alt = getAttribute(altAttr);
   1142         if (!alt.isNull())
   1143             return alt;
   1144     }
   1145 
   1146     // An element's descriptive text is comprised of title() (what's visible on the screen) and accessibilityDescription() (other descriptive text).
   1147     // Both are used to generate what a screen reader speaks.
   1148     // If this point is reached (i.e. there's no accessibilityDescription) and there's no title(), we should fallback to using the title attribute.
   1149     // The title attribute is normally used as help text (because it is a tooltip), but if there is nothing else available, this should be used (according to ARIA).
   1150     if (title().isEmpty())
   1151         return getAttribute(titleAttr);
   1152 
   1153     return String();
   1154 }
   1155 
   1156 String AXNodeObject::title() const
   1157 {
   1158     Node* node = this->node();
   1159     if (!node)
   1160         return String();
   1161 
   1162     bool isInputElement = isHTMLInputElement(*node);
   1163     if (isInputElement) {
   1164         HTMLInputElement& input = toHTMLInputElement(*node);
   1165         if (input.isTextButton())
   1166             return input.valueWithDefault();
   1167     }
   1168 
   1169     if (isInputElement || AXObject::isARIAInput(ariaRoleAttribute()) || isControl()) {
   1170         HTMLLabelElement* label = labelForElement(toElement(node));
   1171         if (label && !exposesTitleUIElement())
   1172             return label->innerText();
   1173     }
   1174 
   1175     // If this node isn't rendered, there's no inner text we can extract from a select element.
   1176     if (!isAXRenderObject() && isHTMLSelectElement(*node))
   1177         return String();
   1178 
   1179     switch (roleValue()) {
   1180     case PopUpButtonRole:
   1181         // Native popup buttons should not use their button children's text as a title. That value is retrieved through stringValue().
   1182         if (isHTMLSelectElement(*node))
   1183             return String();
   1184     case ButtonRole:
   1185     case ToggleButtonRole:
   1186     case CheckBoxRole:
   1187     case ListBoxOptionRole:
   1188     case MenuButtonRole:
   1189     case MenuItemRole:
   1190     case RadioButtonRole:
   1191     case TabRole:
   1192         return textUnderElement();
   1193     // SVGRoots should not use the text under itself as a title. That could include the text of objects like <text>.
   1194     case SVGRootRole:
   1195         return String();
   1196     default:
   1197         break;
   1198     }
   1199 
   1200     if (isHeading() || isLink())
   1201         return textUnderElement();
   1202 
   1203     // If it's focusable but it's not content editable or a known control type, then it will appear to
   1204     // the user as a single atomic object, so we should use its text as the default title.
   1205     if (isGenericFocusableElement())
   1206         return textUnderElement();
   1207 
   1208     return String();
   1209 }
   1210 
   1211 String AXNodeObject::helpText() const
   1212 {
   1213     Node* node = this->node();
   1214     if (!node)
   1215         return String();
   1216 
   1217     const AtomicString& ariaHelp = getAttribute(aria_helpAttr);
   1218     if (!ariaHelp.isEmpty())
   1219         return ariaHelp;
   1220 
   1221     String describedBy = ariaDescribedByAttribute();
   1222     if (!describedBy.isEmpty())
   1223         return describedBy;
   1224 
   1225     String description = accessibilityDescription();
   1226     for (Node* curr = node; curr; curr = curr->parentNode()) {
   1227         if (curr->isHTMLElement()) {
   1228             const AtomicString& summary = toElement(curr)->getAttribute(summaryAttr);
   1229             if (!summary.isEmpty())
   1230                 return summary;
   1231 
   1232             // The title attribute should be used as help text unless it is already being used as descriptive text.
   1233             const AtomicString& title = toElement(curr)->getAttribute(titleAttr);
   1234             if (!title.isEmpty() && description != title)
   1235                 return title;
   1236         }
   1237 
   1238         // Only take help text from an ancestor element if its a group or an unknown role. If help was
   1239         // added to those kinds of elements, it is likely it was meant for a child element.
   1240         AXObject* axObj = axObjectCache()->getOrCreate(curr);
   1241         if (axObj) {
   1242             AccessibilityRole role = axObj->roleValue();
   1243             if (role != GroupRole && role != UnknownRole)
   1244                 break;
   1245         }
   1246     }
   1247 
   1248     return String();
   1249 }
   1250 
   1251 LayoutRect AXNodeObject::elementRect() const
   1252 {
   1253     // First check if it has a custom rect, for example if this element is tied to a canvas path.
   1254     if (!m_explicitElementRect.isEmpty())
   1255         return m_explicitElementRect;
   1256 
   1257     // FIXME: If there are a lot of elements in the canvas, it will be inefficient.
   1258     // We can avoid the inefficient calculations by using AXComputedObjectAttributeCache.
   1259     if (node()->parentElement()->isInCanvasSubtree()) {
   1260         LayoutRect rect;
   1261 
   1262         for (Node* child = node()->firstChild(); child; child = child->nextSibling()) {
   1263             if (child->isHTMLElement()) {
   1264                 if (AXObject* obj = axObjectCache()->get(child)) {
   1265                     if (rect.isEmpty())
   1266                         rect = obj->elementRect();
   1267                     else
   1268                         rect.unite(obj->elementRect());
   1269                 }
   1270             }
   1271         }
   1272 
   1273         if (!rect.isEmpty())
   1274             return rect;
   1275     }
   1276 
   1277     // If this object doesn't have an explicit element rect or computable from its children,
   1278     // for now, let's return the position of the ancestor that does have a position,
   1279     // and make it the width of that parent, and about the height of a line of text, so that it's clear the object is a child of the parent.
   1280 
   1281     LayoutRect boundingBox;
   1282 
   1283     for (AXObject* positionProvider = parentObject(); positionProvider; positionProvider = positionProvider->parentObject()) {
   1284         if (positionProvider->isAXRenderObject()) {
   1285             LayoutRect parentRect = positionProvider->elementRect();
   1286             boundingBox.setSize(LayoutSize(parentRect.width(), LayoutUnit(std::min(10.0f, parentRect.height().toFloat()))));
   1287             boundingBox.setLocation(parentRect.location());
   1288             break;
   1289         }
   1290     }
   1291 
   1292     return boundingBox;
   1293 }
   1294 
   1295 AXObject* AXNodeObject::parentObject() const
   1296 {
   1297     if (!node())
   1298         return 0;
   1299 
   1300     Node* parentObj = node()->parentNode();
   1301     if (parentObj)
   1302         return axObjectCache()->getOrCreate(parentObj);
   1303 
   1304     return 0;
   1305 }
   1306 
   1307 AXObject* AXNodeObject::parentObjectIfExists() const
   1308 {
   1309     return parentObject();
   1310 }
   1311 
   1312 AXObject* AXNodeObject::firstChild() const
   1313 {
   1314     if (!node())
   1315         return 0;
   1316 
   1317     Node* firstChild = node()->firstChild();
   1318 
   1319     if (!firstChild)
   1320         return 0;
   1321 
   1322     return axObjectCache()->getOrCreate(firstChild);
   1323 }
   1324 
   1325 AXObject* AXNodeObject::nextSibling() const
   1326 {
   1327     if (!node())
   1328         return 0;
   1329 
   1330     Node* nextSibling = node()->nextSibling();
   1331     if (!nextSibling)
   1332         return 0;
   1333 
   1334     return axObjectCache()->getOrCreate(nextSibling);
   1335 }
   1336 
   1337 void AXNodeObject::addChildren()
   1338 {
   1339     // If the need to add more children in addition to existing children arises,
   1340     // childrenChanged should have been called, leaving the object with no children.
   1341     ASSERT(!m_haveChildren);
   1342 
   1343     if (!m_node)
   1344         return;
   1345 
   1346     m_haveChildren = true;
   1347 
   1348     // The only time we add children from the DOM tree to a node with a renderer is when it's a canvas.
   1349     if (renderer() && !isHTMLCanvasElement(*m_node))
   1350         return;
   1351 
   1352     for (Node* child = m_node->firstChild(); child; child = child->nextSibling())
   1353         addChild(axObjectCache()->getOrCreate(child));
   1354 }
   1355 
   1356 void AXNodeObject::addChild(AXObject* child)
   1357 {
   1358     insertChild(child, m_children.size());
   1359 }
   1360 
   1361 void AXNodeObject::insertChild(AXObject* child, unsigned index)
   1362 {
   1363     if (!child)
   1364         return;
   1365 
   1366     // If the parent is asking for this child's children, then either it's the first time (and clearing is a no-op),
   1367     // or its visibility has changed. In the latter case, this child may have a stale child cached.
   1368     // This can prevent aria-hidden changes from working correctly. Hence, whenever a parent is getting children, ensure data is not stale.
   1369     child->clearChildren();
   1370 
   1371     if (child->accessibilityIsIgnored()) {
   1372         AccessibilityChildrenVector children = child->children();
   1373         size_t length = children.size();
   1374         for (size_t i = 0; i < length; ++i)
   1375             m_children.insert(index + i, children[i]);
   1376     } else {
   1377         ASSERT(child->parentObject() == this);
   1378         m_children.insert(index, child);
   1379     }
   1380 }
   1381 
   1382 bool AXNodeObject::canHaveChildren() const
   1383 {
   1384     // If this is an AXRenderObject, then it's okay if this object
   1385     // doesn't have a node - there are some renderers that don't have associated
   1386     // nodes, like scroll areas and css-generated text.
   1387     if (!node() && !isAXRenderObject())
   1388         return false;
   1389 
   1390     // Elements that should not have children
   1391     switch (roleValue()) {
   1392     case ImageRole:
   1393     case ButtonRole:
   1394     case PopUpButtonRole:
   1395     case CheckBoxRole:
   1396     case RadioButtonRole:
   1397     case TabRole:
   1398     case ToggleButtonRole:
   1399     case ListBoxOptionRole:
   1400     case ScrollBarRole:
   1401         return false;
   1402     case StaticTextRole:
   1403         if (!axObjectCache()->inlineTextBoxAccessibilityEnabled())
   1404             return false;
   1405     default:
   1406         return true;
   1407     }
   1408 }
   1409 
   1410 Element* AXNodeObject::actionElement() const
   1411 {
   1412     Node* node = this->node();
   1413     if (!node)
   1414         return 0;
   1415 
   1416     if (isHTMLInputElement(*node)) {
   1417         HTMLInputElement& input = toHTMLInputElement(*node);
   1418         if (!input.isDisabledFormControl() && (isCheckboxOrRadio() || input.isTextButton()))
   1419             return &input;
   1420     } else if (isHTMLButtonElement(*node)) {
   1421         return toElement(node);
   1422     }
   1423 
   1424     if (isFileUploadButton())
   1425         return toElement(node);
   1426 
   1427     if (AXObject::isARIAInput(ariaRoleAttribute()))
   1428         return toElement(node);
   1429 
   1430     if (isImageButton())
   1431         return toElement(node);
   1432 
   1433     if (isHTMLSelectElement(*node))
   1434         return toElement(node);
   1435 
   1436     switch (roleValue()) {
   1437     case ButtonRole:
   1438     case PopUpButtonRole:
   1439     case ToggleButtonRole:
   1440     case TabRole:
   1441     case MenuItemRole:
   1442     case ListItemRole:
   1443         return toElement(node);
   1444     default:
   1445         break;
   1446     }
   1447 
   1448     Element* elt = anchorElement();
   1449     if (!elt)
   1450         elt = mouseButtonListener();
   1451     return elt;
   1452 }
   1453 
   1454 Element* AXNodeObject::anchorElement() const
   1455 {
   1456     Node* node = this->node();
   1457     if (!node)
   1458         return 0;
   1459 
   1460     AXObjectCache* cache = axObjectCache();
   1461 
   1462     // search up the DOM tree for an anchor element
   1463     // NOTE: this assumes that any non-image with an anchor is an HTMLAnchorElement
   1464     for ( ; node; node = node->parentNode()) {
   1465         if (isHTMLAnchorElement(*node) || (node->renderer() && cache->getOrCreate(node->renderer())->isAnchor()))
   1466             return toElement(node);
   1467     }
   1468 
   1469     return 0;
   1470 }
   1471 
   1472 Document* AXNodeObject::document() const
   1473 {
   1474     if (!node())
   1475         return 0;
   1476     return &node()->document();
   1477 }
   1478 
   1479 void AXNodeObject::setNode(Node* node)
   1480 {
   1481     m_node = node;
   1482 }
   1483 
   1484 AXObject* AXNodeObject::correspondingControlForLabelElement() const
   1485 {
   1486     HTMLLabelElement* labelElement = labelElementContainer();
   1487     if (!labelElement)
   1488         return 0;
   1489 
   1490     HTMLElement* correspondingControl = labelElement->control();
   1491     if (!correspondingControl)
   1492         return 0;
   1493 
   1494     // Make sure the corresponding control isn't a descendant of this label
   1495     // that's in the middle of being destroyed.
   1496     if (correspondingControl->renderer() && !correspondingControl->renderer()->parent())
   1497         return 0;
   1498 
   1499     return axObjectCache()->getOrCreate(correspondingControl);
   1500 }
   1501 
   1502 HTMLLabelElement* AXNodeObject::labelElementContainer() const
   1503 {
   1504     if (!node())
   1505         return 0;
   1506 
   1507     // the control element should not be considered part of the label
   1508     if (isControl())
   1509         return 0;
   1510 
   1511     // find if this has a ancestor that is a label
   1512     return Traversal<HTMLLabelElement>::firstAncestorOrSelf(*node());
   1513 }
   1514 
   1515 void AXNodeObject::setFocused(bool on)
   1516 {
   1517     if (!canSetFocusAttribute())
   1518         return;
   1519 
   1520     Document* document = this->document();
   1521     if (!on) {
   1522         document->setFocusedElement(nullptr);
   1523     } else {
   1524         Node* node = this->node();
   1525         if (node && node->isElementNode()) {
   1526             // If this node is already the currently focused node, then calling focus() won't do anything.
   1527             // That is a problem when focus is removed from the webpage to chrome, and then returns.
   1528             // In these cases, we need to do what keyboard and mouse focus do, which is reset focus first.
   1529             if (document->focusedElement() == node)
   1530                 document->setFocusedElement(nullptr);
   1531 
   1532             toElement(node)->focus();
   1533         } else {
   1534             document->setFocusedElement(nullptr);
   1535         }
   1536     }
   1537 }
   1538 
   1539 void AXNodeObject::increment()
   1540 {
   1541     UserGestureIndicator gestureIndicator(DefinitelyProcessingNewUserGesture);
   1542     alterSliderValue(true);
   1543 }
   1544 
   1545 void AXNodeObject::decrement()
   1546 {
   1547     UserGestureIndicator gestureIndicator(DefinitelyProcessingNewUserGesture);
   1548     alterSliderValue(false);
   1549 }
   1550 
   1551 void AXNodeObject::childrenChanged()
   1552 {
   1553     // This method is meant as a quick way of marking a portion of the accessibility tree dirty.
   1554     if (!node() && !renderer())
   1555         return;
   1556 
   1557     axObjectCache()->postNotification(this, document(), AXObjectCache::AXChildrenChanged, true);
   1558 
   1559     // Go up the accessibility parent chain, but only if the element already exists. This method is
   1560     // called during render layouts, minimal work should be done.
   1561     // If AX elements are created now, they could interrogate the render tree while it's in a funky state.
   1562     // At the same time, process ARIA live region changes.
   1563     for (AXObject* parent = this; parent; parent = parent->parentObjectIfExists()) {
   1564         parent->setNeedsToUpdateChildren();
   1565 
   1566         // These notifications always need to be sent because screenreaders are reliant on them to perform.
   1567         // In other words, they need to be sent even when the screen reader has not accessed this live region since the last update.
   1568 
   1569         // If this element supports ARIA live regions, then notify the AT of changes.
   1570         if (parent->supportsARIALiveRegion())
   1571             axObjectCache()->postNotification(parent, parent->document(), AXObjectCache::AXLiveRegionChanged, true);
   1572 
   1573         // If this element is an ARIA text box or content editable, post a "value changed" notification on it
   1574         // so that it behaves just like a native input element or textarea.
   1575         if (isNonNativeTextControl())
   1576             axObjectCache()->postNotification(parent, parent->document(), AXObjectCache::AXValueChanged, true);
   1577     }
   1578 }
   1579 
   1580 void AXNodeObject::selectionChanged()
   1581 {
   1582     // Post the selected text changed event on the first ancestor that's
   1583     // focused (to handle form controls, ARIA text boxes and contentEditable),
   1584     // or the web area if the selection is just in the document somewhere.
   1585     if (isFocused() || isWebArea())
   1586         axObjectCache()->postNotification(this, document(), AXObjectCache::AXSelectedTextChanged, true);
   1587     else
   1588         AXObject::selectionChanged(); // Calls selectionChanged on parent.
   1589 }
   1590 
   1591 void AXNodeObject::textChanged()
   1592 {
   1593     // If this element supports ARIA live regions, or is part of a region with an ARIA editable role,
   1594     // then notify the AT of changes.
   1595     AXObjectCache* cache = axObjectCache();
   1596     for (Node* parentNode = node(); parentNode; parentNode = parentNode->parentNode()) {
   1597         AXObject* parent = cache->get(parentNode);
   1598         if (!parent)
   1599             continue;
   1600 
   1601         if (parent->supportsARIALiveRegion())
   1602             cache->postNotification(parentNode, AXObjectCache::AXLiveRegionChanged, true);
   1603 
   1604         // If this element is an ARIA text box or content editable, post a "value changed" notification on it
   1605         // so that it behaves just like a native input element or textarea.
   1606         if (parent->isNonNativeTextControl())
   1607             cache->postNotification(parentNode, AXObjectCache::AXValueChanged, true);
   1608     }
   1609 }
   1610 
   1611 void AXNodeObject::updateAccessibilityRole()
   1612 {
   1613     bool ignoredStatus = accessibilityIsIgnored();
   1614     m_role = determineAccessibilityRole();
   1615 
   1616     // The AX hierarchy only needs to be updated if the ignored status of an element has changed.
   1617     if (ignoredStatus != accessibilityIsIgnored())
   1618         childrenChanged();
   1619 }
   1620 
   1621 String AXNodeObject::alternativeTextForWebArea() const
   1622 {
   1623     // The WebArea description should follow this order:
   1624     //     aria-label on the <html>
   1625     //     title on the <html>
   1626     //     <title> inside the <head> (of it was set through JS)
   1627     //     name on the <html>
   1628     // For iframes:
   1629     //     aria-label on the <iframe>
   1630     //     title on the <iframe>
   1631     //     name on the <iframe>
   1632 
   1633     Document* document = this->document();
   1634     if (!document)
   1635         return String();
   1636 
   1637     // Check if the HTML element has an aria-label for the webpage.
   1638     if (Element* documentElement = document->documentElement()) {
   1639         const AtomicString& ariaLabel = documentElement->getAttribute(aria_labelAttr);
   1640         if (!ariaLabel.isEmpty())
   1641             return ariaLabel;
   1642     }
   1643 
   1644     if (HTMLFrameOwnerElement* owner = document->ownerElement()) {
   1645         if (isHTMLFrameElementBase(*owner)) {
   1646             const AtomicString& title = owner->getAttribute(titleAttr);
   1647             if (!title.isEmpty())
   1648                 return title;
   1649         }
   1650         return owner->getNameAttribute();
   1651     }
   1652 
   1653     String documentTitle = document->title();
   1654     if (!documentTitle.isEmpty())
   1655         return documentTitle;
   1656 
   1657     if (HTMLElement* body = document->body())
   1658         return body->getNameAttribute();
   1659 
   1660     return String();
   1661 }
   1662 
   1663 void AXNodeObject::alternativeText(Vector<AccessibilityText>& textOrder) const
   1664 {
   1665     if (isWebArea()) {
   1666         String webAreaText = alternativeTextForWebArea();
   1667         if (!webAreaText.isEmpty())
   1668             textOrder.append(AccessibilityText(webAreaText, AlternativeText));
   1669         return;
   1670     }
   1671 
   1672     ariaLabeledByText(textOrder);
   1673 
   1674     const AtomicString& ariaLabel = getAttribute(aria_labelAttr);
   1675     if (!ariaLabel.isEmpty())
   1676         textOrder.append(AccessibilityText(ariaLabel, AlternativeText));
   1677 
   1678     if (isImage() || isInputImage() || isNativeImage() || isCanvas()) {
   1679         // Images should use alt as long as the attribute is present, even if empty.
   1680         // Otherwise, it should fallback to other methods, like the title attribute.
   1681         const AtomicString& alt = getAttribute(altAttr);
   1682         if (!alt.isNull())
   1683             textOrder.append(AccessibilityText(alt, AlternativeText));
   1684     }
   1685 }
   1686 
   1687 void AXNodeObject::ariaLabeledByText(Vector<AccessibilityText>& textOrder) const
   1688 {
   1689     String ariaLabeledBy = ariaLabeledByAttribute();
   1690     if (!ariaLabeledBy.isEmpty()) {
   1691         WillBeHeapVector<RawPtrWillBeMember<Element> > elements;
   1692         ariaLabeledByElements(elements);
   1693 
   1694         unsigned length = elements.size();
   1695         for (unsigned k = 0; k < length; k++) {
   1696             RefPtr<AXObject> axElement = axObjectCache()->getOrCreate(elements[k]);
   1697             textOrder.append(AccessibilityText(ariaLabeledBy, AlternativeText, axElement));
   1698         }
   1699     }
   1700 }
   1701 
   1702 void AXNodeObject::changeValueByPercent(float percentChange)
   1703 {
   1704     float range = maxValueForRange() - minValueForRange();
   1705     float value = valueForRange();
   1706 
   1707     value += range * (percentChange / 100);
   1708     setValue(String::number(value));
   1709 
   1710     axObjectCache()->postNotification(node(), AXObjectCache::AXValueChanged, true);
   1711 }
   1712 
   1713 } // namespace blink
   1714