/*
 * Copyright (C) 2012, Google Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1.  Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 * 2.  Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
 *     its contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "modules/accessibility/AXNodeObject.h"

#include "core/InputTypeNames.h"
#include "core/dom/DocumentUserGestureToken.h"
#include "core/dom/Element.h"
#include "core/dom/NodeTraversal.h"
#include "core/dom/QualifiedName.h"
#include "core/dom/Text.h"
#include "core/dom/shadow/FlatTreeTraversal.h"
#include "core/editing/EditingUtilities.h"
#include "core/editing/markers/DocumentMarkerController.h"
#include "core/frame/FrameView.h"
#include "core/html/HTMLDListElement.h"
#include "core/html/HTMLFieldSetElement.h"
#include "core/html/HTMLFrameElementBase.h"
#include "core/html/HTMLImageElement.h"
#include "core/html/HTMLInputElement.h"
#include "core/html/HTMLLabelElement.h"
#include "core/html/HTMLLegendElement.h"
#include "core/html/HTMLMediaElement.h"
#include "core/html/HTMLMeterElement.h"
#include "core/html/HTMLPlugInElement.h"
#include "core/html/HTMLSelectElement.h"
#include "core/html/HTMLTableCaptionElement.h"
#include "core/html/HTMLTableCellElement.h"
#include "core/html/HTMLTableElement.h"
#include "core/html/HTMLTableRowElement.h"
#include "core/html/HTMLTableSectionElement.h"
#include "core/html/HTMLTextAreaElement.h"
#include "core/html/LabelsNodeList.h"
#include "core/html/TextControlElement.h"
#include "core/html/parser/HTMLParserIdioms.h"
#include "core/html/shadow/MediaControlElements.h"
#include "core/layout/LayoutBlockFlow.h"
#include "core/layout/LayoutObject.h"
#include "core/svg/SVGElement.h"
#include "modules/accessibility/AXObjectCacheImpl.h"
#include "platform/UserGestureIndicator.h"
#include "platform/text/PlatformLocale.h"
#include "wtf/text/StringBuilder.h"

namespace blink {

using namespace HTMLNames;

class SparseAttributeSetter {
  USING_FAST_MALLOC(SparseAttributeSetter);

 public:
  virtual void run(const AXObject&,
                   AXSparseAttributeClient&,
                   const AtomicString& value) = 0;
};

class BoolAttributeSetter : public SparseAttributeSetter {
 public:
  BoolAttributeSetter(AXBoolAttribute attribute) : m_attribute(attribute) {}

 private:
  AXBoolAttribute m_attribute;

  void run(const AXObject& obj,
           AXSparseAttributeClient& attributeMap,
           const AtomicString& value) override {
    attributeMap.addBoolAttribute(m_attribute,
                                  equalIgnoringCase(value, "true"));
  }
};

class StringAttributeSetter : public SparseAttributeSetter {
 public:
  StringAttributeSetter(AXStringAttribute attribute) : m_attribute(attribute) {}

 private:
  AXStringAttribute m_attribute;

  void run(const AXObject& obj,
           AXSparseAttributeClient& attributeMap,
           const AtomicString& value) override {
    attributeMap.addStringAttribute(m_attribute, value);
  }
};

class ObjectAttributeSetter : public SparseAttributeSetter {
 public:
  ObjectAttributeSetter(AXObjectAttribute attribute) : m_attribute(attribute) {}

 private:
  AXObjectAttribute m_attribute;

  void run(const AXObject& obj,
           AXSparseAttributeClient& attributeMap,
           const AtomicString& value) override {
    if (value.isNull() || value.isEmpty())
      return;

    Node* node = obj.getNode();
    if (!node || !node->isElementNode())
      return;
    Element* target = toElement(node)->treeScope().getElementById(value);
    if (!target)
      return;
    AXObject* axTarget = obj.axObjectCache().getOrCreate(target);
    if (axTarget)
      attributeMap.addObjectAttribute(m_attribute, *axTarget);
  }
};

class ObjectVectorAttributeSetter : public SparseAttributeSetter {
 public:
  ObjectVectorAttributeSetter(AXObjectVectorAttribute attribute)
      : m_attribute(attribute) {}

 private:
  AXObjectVectorAttribute m_attribute;

  void run(const AXObject& obj,
           AXSparseAttributeClient& attributeMap,
           const AtomicString& value) override {
    Node* node = obj.getNode();
    if (!node || !node->isElementNode())
      return;

    String attributeValue = value.getString();
    if (attributeValue.isEmpty())
      return;

    attributeValue.simplifyWhiteSpace();
    Vector<String> ids;
    attributeValue.split(' ', ids);
    if (ids.isEmpty())
      return;

    HeapVector<Member<AXObject>> objects;
    TreeScope& scope = node->treeScope();
    for (const auto& id : ids) {
      if (Element* idElement = scope.getElementById(AtomicString(id))) {
        AXObject* axIdElement = obj.axObjectCache().getOrCreate(idElement);
        if (axIdElement && !axIdElement->accessibilityIsIgnored())
          objects.push_back(axIdElement);
      }
    }

    attributeMap.addObjectVectorAttribute(m_attribute, objects);
  }
};

using AXSparseAttributeSetterMap =
    HashMap<QualifiedName, SparseAttributeSetter*>;

static AXSparseAttributeSetterMap& getSparseAttributeSetterMap() {
  // Use a map from attribute name to properties of that attribute.
  // That way we only need to iterate over the list of attributes once,
  // rather than calling getAttribute() once for each possible obscure
  // accessibility attribute.
  DEFINE_STATIC_LOCAL(AXSparseAttributeSetterMap, axSparseAttributeSetterMap,
                      ());
  if (axSparseAttributeSetterMap.isEmpty()) {
    axSparseAttributeSetterMap.set(
        aria_activedescendantAttr,
        new ObjectAttributeSetter(AXObjectAttribute::AriaActiveDescendant));
    axSparseAttributeSetterMap.set(
        aria_controlsAttr,
        new ObjectVectorAttributeSetter(AXObjectVectorAttribute::AriaControls));
    axSparseAttributeSetterMap.set(
        aria_flowtoAttr,
        new ObjectVectorAttributeSetter(AXObjectVectorAttribute::AriaFlowTo));
    axSparseAttributeSetterMap.set(
        aria_detailsAttr,
        new ObjectVectorAttributeSetter(AXObjectVectorAttribute::AriaDetails));
    axSparseAttributeSetterMap.set(
        aria_errormessageAttr,
        new ObjectAttributeSetter(AXObjectAttribute::AriaErrorMessage));
    axSparseAttributeSetterMap.set(
        aria_keyshortcutsAttr,
        new StringAttributeSetter(AXStringAttribute::AriaKeyShortcuts));
    axSparseAttributeSetterMap.set(
        aria_roledescriptionAttr,
        new StringAttributeSetter(AXStringAttribute::AriaRoleDescription));
  }
  return axSparseAttributeSetterMap;
}

AXNodeObject::AXNodeObject(Node* node, AXObjectCacheImpl& axObjectCache)
    : AXObject(axObjectCache),
      m_ariaRole(UnknownRole),
      m_childrenDirty(false),
      m_node(node) {
}

AXNodeObject* AXNodeObject::create(Node* node,
                                   AXObjectCacheImpl& axObjectCache) {
  return new AXNodeObject(node, axObjectCache);
}

AXNodeObject::~AXNodeObject() {
  ASSERT(!m_node);
}

void AXNodeObject::alterSliderValue(bool increase) {
  if (roleValue() != SliderRole)
    return;

  float value = valueForRange();
  float step = stepValueForRange();

  value += increase ? step : -step;

  setValue(String::number(value));
  axObjectCache().postNotification(getNode(),
                                   AXObjectCacheImpl::AXValueChanged);
}

AXObject* AXNodeObject::activeDescendant() {
  if (!getNode() || !getNode()->isElementNode())
    return nullptr;

  const AtomicString& activeDescendantAttr =
      getAttribute(aria_activedescendantAttr);
  if (activeDescendantAttr.isNull() || activeDescendantAttr.isEmpty())
    return nullptr;

  Element* element = toElement(getNode());
  Element* descendant =
      element->treeScope().getElementById(activeDescendantAttr);
  if (!descendant)
    return nullptr;

  AXObject* axDescendant = axObjectCache().getOrCreate(descendant);
  return axDescendant;
}

bool AXNodeObject::computeAccessibilityIsIgnored(
    IgnoredReasons* ignoredReasons) const {
#if DCHECK_IS_ON()
  // Double-check that an AXObject is never accessed before
  // it's been initialized.
  ASSERT(m_initialized);
#endif

  // If this element is within a parent that cannot have children, it should not
  // be exposed.
  if (isDescendantOfLeafNode()) {
    if (ignoredReasons)
      ignoredReasons->push_back(
          IgnoredReason(AXAncestorIsLeafNode, leafNodeAncestor()));
    return true;
  }

  // Ignore labels that are already referenced by a control.
  AXObject* controlObject = correspondingControlForLabelElement();
  if (controlObject && controlObject->isCheckboxOrRadio() &&
      controlObject->nameFromLabelElement()) {
    if (ignoredReasons) {
      HTMLLabelElement* label = labelElementContainer();
      if (label && label != getNode()) {
        AXObject* labelAXObject = axObjectCache().getOrCreate(label);
        ignoredReasons->push_back(
            IgnoredReason(AXLabelContainer, labelAXObject));
      }

      ignoredReasons->push_back(IgnoredReason(AXLabelFor, controlObject));
    }
    return true;
  }

  Element* element = getNode()->isElementNode() ? toElement(getNode())
                                                : getNode()->parentElement();
  if (!getLayoutObject() && (!element || !element->isInCanvasSubtree()) &&
      !equalIgnoringCase(getAttribute(aria_hiddenAttr), "false")) {
    if (ignoredReasons)
      ignoredReasons->push_back(IgnoredReason(AXNotRendered));
    return true;
  }

  if (m_role == UnknownRole) {
    if (ignoredReasons)
      ignoredReasons->push_back(IgnoredReason(AXUninteresting));
    return true;
  }
  return false;
}

static bool isListElement(Node* node) {
  return isHTMLUListElement(*node) || isHTMLOListElement(*node) ||
         isHTMLDListElement(*node);
}

static bool isPresentationalInTable(AXObject* parent,
                                    HTMLElement* currentElement) {
  if (!currentElement)
    return false;

  Node* parentNode = parent->getNode();
  if (!parentNode || !parentNode->isHTMLElement())
    return false;

  // AXTable determines the role as checking isTableXXX.
  // If Table has explicit role including presentation, AXTable doesn't assign
  // implicit Role to a whole Table. That's why we should check it based on
  // node.
  // Normal Table Tree is that
  // cell(its role)-> tr(tr role)-> tfoot, tbody, thead(ignored role) ->
  //     table(table role).
  // If table has presentation role, it will be like
  // cell(group)-> tr(unknown) -> tfoot, tbody, thead(ignored) ->
  //     table(presentation).
  if (isHTMLTableCellElement(*currentElement) &&
      isHTMLTableRowElement(*parentNode))
    return parent->hasInheritedPresentationalRole();

  if (isHTMLTableRowElement(*currentElement) &&
      isHTMLTableSectionElement(toHTMLElement(*parentNode))) {
    // Because TableSections have ignored role, presentation should be checked
    // with its parent node.
    AXObject* tableObject = parent->parentObject();
    Node* tableNode = tableObject ? tableObject->getNode() : 0;
    return isHTMLTableElement(tableNode) &&
           tableObject->hasInheritedPresentationalRole();
  }
  return false;
}

static bool isRequiredOwnedElement(AXObject* parent,
                                   AccessibilityRole currentRole,
                                   HTMLElement* currentElement) {
  Node* parentNode = parent->getNode();
  if (!parentNode || !parentNode->isHTMLElement())
    return false;

  if (currentRole == ListItemRole)
    return isListElement(parentNode);
  if (currentRole == ListMarkerRole)
    return isHTMLLIElement(*parentNode);
  if (currentRole == MenuItemCheckBoxRole || currentRole == MenuItemRole ||
      currentRole == MenuItemRadioRole)
    return isHTMLMenuElement(*parentNode);

  if (!currentElement)
    return false;
  if (isHTMLTableCellElement(*currentElement))
    return isHTMLTableRowElement(*parentNode);
  if (isHTMLTableRowElement(*currentElement))
    return isHTMLTableSectionElement(toHTMLElement(*parentNode));

  // In case of ListboxRole and its child, ListBoxOptionRole, inheritance of
  // presentation role is handled in AXListBoxOption because ListBoxOption Role
  // doesn't have any child.
  // If it's just ignored because of presentation, we can't see any AX tree
  // related to ListBoxOption.
  return false;
}

const AXObject* AXNodeObject::inheritsPresentationalRoleFrom() const {
  // ARIA states if an item can get focus, it should not be presentational.
  if (canSetFocusAttribute())
    return 0;

  if (isPresentational())
    return this;

  // http://www.w3.org/TR/wai-aria/complete#presentation
  // ARIA spec says that the user agent MUST apply an inherited role of
  // presentation
  // to any owned elements that do not have an explicit role defined.
  if (ariaRoleAttribute() != UnknownRole)
    return 0;

  AXObject* parent = parentObject();
  if (!parent)
    return 0;

  HTMLElement* element = nullptr;
  if (getNode() && getNode()->isHTMLElement())
    element = toHTMLElement(getNode());
  if (!parent->hasInheritedPresentationalRole()) {
    if (!getLayoutObject() || !getLayoutObject()->isBoxModelObject())
      return 0;

    LayoutBoxModelObject* cssBox = toLayoutBoxModelObject(getLayoutObject());
    if (!cssBox->isTableCell() && !cssBox->isTableRow())
      return 0;

    if (!isPresentationalInTable(parent, element))
      return 0;
  }
  // ARIA spec says that when a parent object is presentational and this object
  // is a required owned element of that parent, then this object is also
  // presentational.
  if (isRequiredOwnedElement(parent, roleValue(), element))
    return parent;
  return 0;
}

bool AXNodeObject::isDescendantOfElementType(
    const HTMLQualifiedName& tagName) const {
  if (!getNode())
    return false;

  for (Element* parent = getNode()->parentElement(); parent;
       parent = parent->parentElement()) {
    if (parent->hasTagName(tagName))
      return true;
  }
  return false;
}

AccessibilityRole AXNodeObject::nativeAccessibilityRoleIgnoringAria() const {
  if (!getNode())
    return UnknownRole;

  // HTMLAnchorElement sets isLink only when it has hrefAttr.
  // We assume that it is also LinkRole if it has event listners even though it
  // doesn't have hrefAttr.
  if (getNode()->isLink() || (isHTMLAnchorElement(*getNode()) && isClickable()))
    return LinkRole;

  if (isHTMLButtonElement(*getNode()))
    return buttonRoleType();

  if (isHTMLDetailsElement(*getNode()))
    return DetailsRole;

  if (isHTMLSummaryElement(*getNode())) {
    ContainerNode* parent = FlatTreeTraversal::parent(*getNode());
    if (parent && isHTMLDetailsElement(parent))
      return DisclosureTriangleRole;
    return UnknownRole;
  }

  if (isHTMLInputElement(*getNode())) {
    HTMLInputElement& input = toHTMLInputElement(*getNode());
    const AtomicString& type = input.type();
    if (input.dataList())
      return ComboBoxRole;
    if (type == InputTypeNames::button) {
      if ((getNode()->parentNode() &&
           isHTMLMenuElement(getNode()->parentNode())) ||
          (parentObject() && parentObject()->roleValue() == MenuRole))
        return MenuItemRole;
      return buttonRoleType();
    }
    if (type == InputTypeNames::checkbox) {
      if ((getNode()->parentNode() &&
           isHTMLMenuElement(getNode()->parentNode())) ||
          (parentObject() && parentObject()->roleValue() == MenuRole))
        return MenuItemCheckBoxRole;
      return CheckBoxRole;
    }
    if (type == InputTypeNames::date)
      return DateRole;
    if (type == InputTypeNames::datetime ||
        type == InputTypeNames::datetime_local ||
        type == InputTypeNames::month || type == InputTypeNames::week)
      return DateTimeRole;
    if (type == InputTypeNames::file)
      return ButtonRole;
    if (type == InputTypeNames::radio) {
      if ((getNode()->parentNode() &&
           isHTMLMenuElement(getNode()->parentNode())) ||
          (parentObject() && parentObject()->roleValue() == MenuRole))
        return MenuItemRadioRole;
      return RadioButtonRole;
    }
    if (type == InputTypeNames::number)
      return SpinButtonRole;
    if (input.isTextButton())
      return buttonRoleType();
    if (type == InputTypeNames::range)
      return SliderRole;
    if (type == InputTypeNames::color)
      return ColorWellRole;
    if (type == InputTypeNames::time)
      return InputTimeRole;
    return TextFieldRole;
  }

  if (isHTMLSelectElement(*getNode())) {
    HTMLSelectElement& selectElement = toHTMLSelectElement(*getNode());
    return selectElement.isMultiple() ? ListBoxRole : PopUpButtonRole;
  }

  if (isHTMLTextAreaElement(*getNode()))
    return TextFieldRole;

  if (headingLevel())
    return HeadingRole;

  if (isHTMLDivElement(*getNode()))
    return DivRole;

  if (isHTMLMeterElement(*getNode()))
    return MeterRole;

  if (isHTMLOutputElement(*getNode()))
    return StatusRole;

  if (isHTMLParagraphElement(*getNode()))
    return ParagraphRole;

  if (isHTMLLabelElement(*getNode()))
    return LabelRole;

  if (isHTMLLegendElement(*getNode()))
    return LegendRole;

  if (isHTMLRubyElement(*getNode()))
    return RubyRole;

  if (isHTMLDListElement(*getNode()))
    return DescriptionListRole;

  if (isHTMLAudioElement(*getNode()))
    return AudioRole;
  if (isHTMLVideoElement(*getNode()))
    return VideoRole;

  if (getNode()->hasTagName(ddTag))
    return DescriptionListDetailRole;

  if (getNode()->hasTagName(dtTag))
    return DescriptionListTermRole;

  if (getNode()->nodeName() == "math")
    return MathRole;

  if (getNode()->hasTagName(rpTag) || getNode()->hasTagName(rtTag))
    return AnnotationRole;

  if (isHTMLFormElement(*getNode()))
    return FormRole;

  if (getNode()->hasTagName(abbrTag))
    return AbbrRole;

  if (getNode()->hasTagName(articleTag))
    return ArticleRole;

  if (getNode()->hasTagName(mainTag))
    return MainRole;

  if (getNode()->hasTagName(markTag))
    return MarkRole;

  if (getNode()->hasTagName(navTag))
    return NavigationRole;

  if (getNode()->hasTagName(asideTag))
    return ComplementaryRole;

  if (getNode()->hasTagName(preTag))
    return PreRole;

  if (getNode()->hasTagName(sectionTag))
    return RegionRole;

  if (getNode()->hasTagName(addressTag))
    return ContentInfoRole;

  if (isHTMLDialogElement(*getNode()))
    return DialogRole;

  // The HTML element should not be exposed as an element. That's what the
  // LayoutView element does.
  if (isHTMLHtmlElement(*getNode()))
    return IgnoredRole;

  if (isHTMLIFrameElement(*getNode())) {
    const AtomicString& ariaRole = getAttribute(roleAttr);
    if (ariaRole == "none" || ariaRole == "presentation")
      return IframePresentationalRole;
    return IframeRole;
  }

  // There should only be one banner/contentInfo per page. If header/footer are
  // being used within an article or section then it should not be exposed as
  // whole page's banner/contentInfo but as a group role.
  if (getNode()->hasTagName(headerTag)) {
    if (isDescendantOfElementType(articleTag) ||
        isDescendantOfElementType(sectionTag) ||
        (getNode()->parentElement() &&
         getNode()->parentElement()->hasTagName(mainTag))) {
      return GroupRole;
    }
    return BannerRole;
  }

  if (getNode()->hasTagName(footerTag)) {
    if (isDescendantOfElementType(articleTag) ||
        isDescendantOfElementType(sectionTag) ||
        (getNode()->parentElement() &&
         getNode()->parentElement()->hasTagName(mainTag))) {
      return GroupRole;
    }
    return FooterRole;
  }

  if (getNode()->hasTagName(blockquoteTag))
    return BlockquoteRole;

  if (getNode()->hasTagName(captionTag))
    return CaptionRole;

  if (getNode()->hasTagName(figcaptionTag))
    return FigcaptionRole;

  if (getNode()->hasTagName(figureTag))
    return FigureRole;

  if (getNode()->nodeName() == "TIME")
    return TimeRole;

  if (isEmbeddedObject())
    return EmbeddedObjectRole;

  if (isHTMLHRElement(*getNode()))
    return SplitterRole;

  if (isFieldset()) {
    return GroupRole;
  }

  return UnknownRole;
}

AccessibilityRole AXNodeObject::determineAccessibilityRole() {
  if (!getNode())
    return UnknownRole;

  if ((m_ariaRole = determineAriaRoleAttribute()) != UnknownRole)
    return m_ariaRole;
  if (getNode()->isTextNode())
    return StaticTextRole;

  AccessibilityRole role = nativeAccessibilityRoleIgnoringAria();
  if (role != UnknownRole)
    return role;
  if (getNode()->isElementNode()) {
    Element* element = toElement(getNode());
    // A generic element with tabIndex explicitly set gets GroupRole.
    // The layout checks for focusability aren't critical here; a false
    // positive would be harmless.
    if (element->isInCanvasSubtree() && element->supportsFocus())
      return GroupRole;
  }
  return UnknownRole;
}

AccessibilityRole AXNodeObject::determineAriaRoleAttribute() const {
  const AtomicString& ariaRole = getAttribute(roleAttr);
  if (ariaRole.isNull() || ariaRole.isEmpty())
    return UnknownRole;

  AccessibilityRole role = ariaRoleToWebCoreRole(ariaRole);

  // ARIA states if an item can get focus, it should not be presentational.
  if ((role == NoneRole || role == PresentationalRole) &&
      canSetFocusAttribute())
    return UnknownRole;

  if (role == ButtonRole)
    role = buttonRoleType();

  role = remapAriaRoleDueToParent(role);

  if (role)
    return role;

  return UnknownRole;
}

void AXNodeObject::accessibilityChildrenFromAttribute(
    QualifiedName attr,
    AXObject::AXObjectVector& children) const {
  HeapVector<Member<Element>> elements;
  elementsFromAttribute(elements, attr);

  AXObjectCacheImpl& cache = axObjectCache();
  for (const auto& element : elements) {
    if (AXObject* child = cache.getOrCreate(element)) {
      // Only aria-labelledby and aria-describedby can target hidden elements.
      if (child->accessibilityIsIgnored() && attr != aria_labelledbyAttr &&
          attr != aria_labeledbyAttr && attr != aria_describedbyAttr) {
        continue;
      }
      children.push_back(child);
    }
  }
}

// This only returns true if this is the element that actually has the
// contentEditable attribute set, unlike node->hasEditableStyle() which will
// also return true if an ancestor is editable.
bool AXNodeObject::hasContentEditableAttributeSet() const {
  const AtomicString& contentEditableValue = getAttribute(contenteditableAttr);
  if (contentEditableValue.isNull())
    return false;
  // Both "true" (case-insensitive) and the empty string count as true.
  return contentEditableValue.isEmpty() ||
         equalIgnoringCase(contentEditableValue, "true");
}

bool AXNodeObject::isTextControl() const {
  if (hasContentEditableAttributeSet())
    return true;

  switch (roleValue()) {
    case TextFieldRole:
    case ComboBoxRole:
    case SearchBoxRole:
    case SpinButtonRole:
      return true;
    default:
      return false;
  }
}

bool AXNodeObject::isGenericFocusableElement() const {
  if (!canSetFocusAttribute())
    return false;

  // If it's a control, it's not generic.
  if (isControl())
    return false;

  // If it has an aria role, it's not generic.
  if (m_ariaRole != UnknownRole)
    return false;

  // If the content editable attribute is set on this element, that's the reason
  // it's focusable, and existing logic should handle this case already - so
  // it's not a generic focusable element.

  if (hasContentEditableAttributeSet())
    return false;

  // The web area and body element are both focusable, but existing logic
  // handles these cases already, so we don't need to include them here.
  if (roleValue() == WebAreaRole)
    return false;
  if (isHTMLBodyElement(getNode()))
    return false;

  // An SVG root is focusable by default, but it's probably not interactive, so
  // don't include it. It can still be made accessible by giving it an ARIA
  // role.
  if (roleValue() == SVGRootRole)
    return false;

  return true;
}

AXObject* AXNodeObject::menuButtonForMenu() const {
  Element* menuItem = menuItemElementForMenu();

  if (menuItem) {
    // ARIA just has generic menu items. AppKit needs to know if this is a top
    // level items like MenuBarButton or MenuBarItem
    AXObject* menuItemAX = axObjectCache().getOrCreate(menuItem);
    if (menuItemAX && menuItemAX->isMenuButton())
      return menuItemAX;
  }
  return 0;
}

static Element* siblingWithAriaRole(String role, Node* node) {
  Node* parent = node->parentNode();
  if (!parent)
    return 0;

  for (Element* sibling = ElementTraversal::firstChild(*parent); sibling;
       sibling = ElementTraversal::nextSibling(*sibling)) {
    const AtomicString& siblingAriaRole = sibling->getAttribute(roleAttr);
    if (equalIgnoringCase(siblingAriaRole, role))
      return sibling;
  }

  return 0;
}

Element* AXNodeObject::menuItemElementForMenu() const {
  if (ariaRoleAttribute() != MenuRole)
    return 0;

  return siblingWithAriaRole("menuitem", getNode());
}

Element* AXNodeObject::mouseButtonListener() const {
  Node* node = this->getNode();
  if (!node)
    return 0;

  if (!node->isElementNode())
    node = node->parentElement();

  if (!node)
    return 0;

  for (Element* element = toElement(node); element;
       element = element->parentElement()) {
    // It's a pretty common practice to put click listeners on the body or
    // document, but that's almost never what the user wants when clicking on an
    // accessible element.
    if (isHTMLBodyElement(element))
      break;

    if (element->hasEventListeners(EventTypeNames::click) ||
        element->hasEventListeners(EventTypeNames::mousedown) ||
        element->hasEventListeners(EventTypeNames::mouseup) ||
        element->hasEventListeners(EventTypeNames::DOMActivate))
      return element;
  }

  return 0;
}

AccessibilityRole AXNodeObject::remapAriaRoleDueToParent(
    AccessibilityRole role) const {
  // Some objects change their role based on their parent.
  // However, asking for the unignoredParent calls accessibilityIsIgnored(),
  // which can trigger a loop.  While inside the call stack of creating an
  // element, we need to avoid accessibilityIsIgnored().
  // https://bugs.webkit.org/show_bug.cgi?id=65174

  if (role != ListBoxOptionRole && role != MenuItemRole)
    return role;

  for (AXObject* parent = parentObject();
       parent && !parent->accessibilityIsIgnored();
       parent = parent->parentObject()) {
    AccessibilityRole parentAriaRole = parent->ariaRoleAttribute();

    // Selects and listboxes both have options as child roles, but they map to
    // different roles within WebCore.
    if (role == ListBoxOptionRole && parentAriaRole == MenuRole)
      return MenuItemRole;
    // An aria "menuitem" may map to MenuButton or MenuItem depending on its
    // parent.
    if (role == MenuItemRole && parentAriaRole == GroupRole)
      return MenuButtonRole;

    // If the parent had a different role, then we don't need to continue
    // searching up the chain.
    if (parentAriaRole)
      break;
  }

  return role;
}

void AXNodeObject::init() {
#if DCHECK_IS_ON()
  ASSERT(!m_initialized);
  m_initialized = true;
#endif
  m_role = determineAccessibilityRole();
}

void AXNodeObject::detach() {
  AXObject::detach();
  m_node = nullptr;
}

void AXNodeObject::getSparseAXAttributes(
    AXSparseAttributeClient& sparseAttributeClient) const {
  Node* node = this->getNode();
  if (!node || !node->isElementNode())
    return;

  AXSparseAttributeSetterMap& axSparseAttributeSetterMap =
      getSparseAttributeSetterMap();
  AttributeCollection attributes = toElement(node)->attributesWithoutUpdate();
  for (const Attribute& attr : attributes) {
    SparseAttributeSetter* setter = axSparseAttributeSetterMap.get(attr.name());
    if (setter)
      setter->run(*this, sparseAttributeClient, attr.value());
  }
}

bool AXNodeObject::isAnchor() const {
  return !isNativeImage() && isLink();
}

bool AXNodeObject::isControl() const {
  Node* node = this->getNode();
  if (!node)
    return false;

  return ((node->isElementNode() && toElement(node)->isFormControlElement()) ||
          AXObject::isARIAControl(ariaRoleAttribute()));
}

bool AXNodeObject::isControllingVideoElement() const {
  Node* node = this->getNode();
  if (!node)
    return true;

  return isHTMLVideoElement(toParentMediaElement(node));
}

bool AXNodeObject::isEmbeddedObject() const {
  return isHTMLPlugInElement(getNode());
}

bool AXNodeObject::isFieldset() const {
  return isHTMLFieldSetElement(getNode());
}

bool AXNodeObject::isHeading() const {
  return roleValue() == HeadingRole;
}

bool AXNodeObject::isHovered() const {
  if (Node* node = this->getNode())
    return node->isHovered();
  return false;
}

bool AXNodeObject::isImage() const {
  return roleValue() == ImageRole;
}

bool AXNodeObject::isImageButton() const {
  return isNativeImage() && isButton();
}

bool AXNodeObject::isInputImage() const {
  Node* node = this->getNode();
  if (roleValue() == ButtonRole && isHTMLInputElement(node))
    return toHTMLInputElement(*node).type() == InputTypeNames::image;

  return false;
}

bool AXNodeObject::isLink() const {
  return roleValue() == LinkRole;
}

bool AXNodeObject::isMenu() const {
  return roleValue() == MenuRole;
}

bool AXNodeObject::isMenuButton() const {
  return roleValue() == MenuButtonRole;
}

bool AXNodeObject::isMeter() const {
  return roleValue() == MeterRole;
}

bool AXNodeObject::isMultiSelectable() const {
  const AtomicString& ariaMultiSelectable =
      getAttribute(aria_multiselectableAttr);
  if (equalIgnoringCase(ariaMultiSelectable, "true"))
    return true;
  if (equalIgnoringCase(ariaMultiSelectable, "false"))
    return false;

  return isHTMLSelectElement(getNode()) &&
         toHTMLSelectElement(*getNode()).isMultiple();
}

bool AXNodeObject::isNativeCheckboxOrRadio() const {
  Node* node = this->getNode();
  if (!isHTMLInputElement(node))
    return false;

  HTMLInputElement* input = toHTMLInputElement(node);
  return input->type() == InputTypeNames::checkbox ||
         input->type() == InputTypeNames::radio;
}

bool AXNodeObject::isNativeImage() const {
  Node* node = this->getNode();
  if (!node)
    return false;

  if (isHTMLImageElement(*node))
    return true;

  if (isHTMLPlugInElement(*node))
    return true;

  if (isHTMLInputElement(*node))
    return toHTMLInputElement(*node).type() == InputTypeNames::image;

  return false;
}

bool AXNodeObject::isNativeTextControl() const {
  Node* node = this->getNode();
  if (!node)
    return false;

  if (isHTMLTextAreaElement(*node))
    return true;

  if (isHTMLInputElement(*node))
    return toHTMLInputElement(node)->isTextField();

  return false;
}

bool AXNodeObject::isNonNativeTextControl() const {
  if (isNativeTextControl())
    return false;

  if (hasContentEditableAttributeSet())
    return true;

  if (isARIATextControl())
    return true;

  return false;
}

bool AXNodeObject::isPasswordField() const {
  Node* node = this->getNode();
  if (!isHTMLInputElement(node))
    return false;

  AccessibilityRole ariaRole = ariaRoleAttribute();
  if (ariaRole != TextFieldRole && ariaRole != UnknownRole)
    return false;

  return toHTMLInputElement(node)->type() == InputTypeNames::password;
}

bool AXNodeObject::isProgressIndicator() const {
  return roleValue() == ProgressIndicatorRole;
}

bool AXNodeObject::isRichlyEditable() const {
  return hasContentEditableAttributeSet();
}

bool AXNodeObject::isSlider() const {
  return roleValue() == SliderRole;
}

bool AXNodeObject::isNativeSlider() const {
  Node* node = this->getNode();
  if (!node)
    return false;

  if (!isHTMLInputElement(node))
    return false;

  return toHTMLInputElement(node)->type() == InputTypeNames::range;
}

bool AXNodeObject::isChecked() const {
  Node* node = this->getNode();
  if (!node)
    return false;

  // First test for native checkedness semantics
  if (isHTMLInputElement(*node))
    return toHTMLInputElement(*node).shouldAppearChecked();

  // Else, if this is an ARIA role checkbox or radio or menuitemcheckbox
  // or menuitemradio or switch, respect the aria-checked attribute
  switch (ariaRoleAttribute()) {
    case CheckBoxRole:
    case MenuItemCheckBoxRole:
    case MenuItemRadioRole:
    case RadioButtonRole:
    case SwitchRole:
      if (equalIgnoringCase(getAttribute(aria_checkedAttr), "true"))
        return true;
      return false;
    default:
      break;
  }

  // Otherwise it's not checked
  return false;
}

bool AXNodeObject::isClickable() const {
  if (getNode()) {
    if (getNode()->isElementNode() &&
        toElement(getNode())->isDisabledFormControl())
      return false;

    // Note: we can't call getNode()->willRespondToMouseClickEvents() because
    // that triggers a style recalc and can delete this.
    if (getNode()->hasEventListeners(EventTypeNames::mouseup) ||
        getNode()->hasEventListeners(EventTypeNames::mousedown) ||
        getNode()->hasEventListeners(EventTypeNames::click) ||
        getNode()->hasEventListeners(EventTypeNames::DOMActivate))
      return true;
  }

  return AXObject::isClickable();
}

bool AXNodeObject::isEnabled() const {
  if (isDescendantOfDisabledNode())
    return false;

  Node* node = this->getNode();
  if (!node || !node->isElementNode())
    return true;

  return !toElement(node)->isDisabledFormControl();
}

AccessibilityExpanded AXNodeObject::isExpanded() const {
  if (getNode() && isHTMLSummaryElement(*getNode())) {
    if (getNode()->parentNode() &&
        isHTMLDetailsElement(getNode()->parentNode()))
      return toElement(getNode()->parentNode())->hasAttribute(openAttr)
                 ? ExpandedExpanded
                 : ExpandedCollapsed;
  }

  const AtomicString& expanded = getAttribute(aria_expandedAttr);
  if (equalIgnoringCase(expanded, "true"))
    return ExpandedExpanded;
  if (equalIgnoringCase(expanded, "false"))
    return ExpandedCollapsed;

  return ExpandedUndefined;
}

bool AXNodeObject::isModal() const {
  if (roleValue() != DialogRole && roleValue() != AlertDialogRole)
    return false;

  if (hasAttribute(aria_modalAttr)) {
    const AtomicString& modal = getAttribute(aria_modalAttr);
    if (equalIgnoringCase(modal, "true"))
      return true;
    if (equalIgnoringCase(modal, "false"))
      return false;
  }

  if (getNode() && isHTMLDialogElement(*getNode()))
    return toElement(getNode())->isInTopLayer();

  return false;
}

bool AXNodeObject::isPressed() const {
  if (!isButton())
    return false;

  Node* node = this->getNode();
  if (!node)
    return false;

  // ARIA button with aria-pressed not undefined, then check for aria-pressed
  // attribute rather than getNode()->active()
  if (ariaRoleAttribute() == ToggleButtonRole) {
    if (equalIgnoringCase(getAttribute(aria_pressedAttr), "true") ||
        equalIgnoringCase(getAttribute(aria_pressedAttr), "mixed"))
      return true;
    return false;
  }

  return node->isActive();
}

bool AXNodeObject::isReadOnly() const {
  Node* node = this->getNode();
  if (!node)
    return true;

  if (isHTMLTextAreaElement(*node))
    return toHTMLTextAreaElement(*node).isReadOnly();

  if (isHTMLInputElement(*node)) {
    HTMLInputElement& input = toHTMLInputElement(*node);
    if (input.isTextField())
      return input.isReadOnly();
  }

  return !hasEditableStyle(*node);
}

bool AXNodeObject::isRequired() const {
  Node* n = this->getNode();
  if (n && (n->isElementNode() && toElement(n)->isFormControlElement()) &&
      hasAttribute(requiredAttr))
    return toHTMLFormControlElement(n)->isRequired();

  if (equalIgnoringCase(getAttribute(aria_requiredAttr), "true"))
    return true;

  return false;
}

bool AXNodeObject::canSetFocusAttribute() const {
  Node* node = getNode();
  if (!node)
    return false;

  if (isWebArea())
    return true;

  // Children of elements with an aria-activedescendant attribute should be
  // focusable if they have a (non-presentational) ARIA role.
  if (!isPresentational() && ariaRoleAttribute() != UnknownRole &&
      ancestorExposesActiveDescendant())
    return true;

  // NOTE: It would be more accurate to ask the document whether
  // setFocusedNode() would do anything. For example, setFocusedNode() will do
  // nothing if the current focused node will not relinquish the focus.
  if (isDisabledFormControl(node))
    return false;

  return node->isElementNode() && toElement(node)->supportsFocus();
}

bool AXNodeObject::canSetValueAttribute() const {
  if (equalIgnoringCase(getAttribute(aria_readonlyAttr), "true"))
    return false;

  if (isProgressIndicator() || isSlider())
    return true;

  if (isTextControl() && !isNativeTextControl())
    return true;

  // Any node could be contenteditable, so isReadOnly should be relied upon
  // for this information for all elements.
  return !isReadOnly();
}

bool AXNodeObject::canSetSelectedAttribute() const {
  // ARIA list box options can be selected if they are children of an element
  // with an aria-activedescendant attribute.
  if (ariaRoleAttribute() == ListBoxOptionRole &&
      ancestorExposesActiveDescendant())
    return true;
  return AXObject::canSetSelectedAttribute();
}

bool AXNodeObject::canvasHasFallbackContent() const {
  Node* node = this->getNode();
  if (!isHTMLCanvasElement(node))
    return false;

  // If it has any children that are elements, we'll assume it might be fallback
  // content. If it has no children or its only children are not elements
  // (e.g. just text nodes), it doesn't have fallback content.
  return ElementTraversal::firstChild(*node);
}

int AXNodeObject::headingLevel() const {
  // headings can be in block flow and non-block flow
  Node* node = this->getNode();
  if (!node)
    return 0;

  if (roleValue() == HeadingRole) {
    String levelStr = getAttribute(aria_levelAttr);
    if (!levelStr.isEmpty()) {
      int level = levelStr.toInt();
      if (level >= 1 && level <= 9)
        return level;
      return 1;
    }
  }

  if (!node->isHTMLElement())
    return 0;

  HTMLElement& element = toHTMLElement(*node);
  if (element.hasTagName(h1Tag))
    return 1;

  if (element.hasTagName(h2Tag))
    return 2;

  if (element.hasTagName(h3Tag))
    return 3;

  if (element.hasTagName(h4Tag))
    return 4;

  if (element.hasTagName(h5Tag))
    return 5;

  if (element.hasTagName(h6Tag))
    return 6;

  return 0;
}

unsigned AXNodeObject::hierarchicalLevel() const {
  Node* node = this->getNode();
  if (!node || !node->isElementNode())
    return 0;

  Element* element = toElement(node);
  String levelStr = element->getAttribute(aria_levelAttr);
  if (!levelStr.isEmpty()) {
    int level = levelStr.toInt();
    if (level > 0)
      return level;
    return 1;
  }

  // Only tree item will calculate its level through the DOM currently.
  if (roleValue() != TreeItemRole)
    return 0;

  // Hierarchy leveling starts at 1, to match the aria-level spec.
  // We measure tree hierarchy by the number of groups that the item is within.
  unsigned level = 1;
  for (AXObject* parent = parentObject(); parent;
       parent = parent->parentObject()) {
    AccessibilityRole parentRole = parent->roleValue();
    if (parentRole == GroupRole)
      level++;
    else if (parentRole == TreeRole)
      break;
  }

  return level;
}

String AXNodeObject::ariaAutoComplete() const {
  if (roleValue() != ComboBoxRole)
    return String();

  const AtomicString& ariaAutoComplete =
      getAttribute(aria_autocompleteAttr).lower();

  if (ariaAutoComplete == "inline" || ariaAutoComplete == "list" ||
      ariaAutoComplete == "both")
    return ariaAutoComplete;

  return String();
}

void AXNodeObject::markers(Vector<DocumentMarker::MarkerType>& markerTypes,
                           Vector<AXRange>& markerRanges) const {
  if (!getNode() || !getDocument() || !getDocument()->view())
    return;

  DocumentMarkerController& markerController = getDocument()->markers();
  DocumentMarkerVector markers = markerController.markersFor(getNode());
  for (size_t i = 0; i < markers.size(); ++i) {
    DocumentMarker* marker = markers[i];
    switch (marker->type()) {
      case DocumentMarker::Spelling:
      case DocumentMarker::Grammar:
      case DocumentMarker::TextMatch:
        markerTypes.push_back(marker->type());
        markerRanges.push_back(
            AXRange(marker->startOffset(), marker->endOffset()));
        break;
      case DocumentMarker::InvisibleSpellcheck:
      case DocumentMarker::Composition:
        // No need for accessibility to know about these marker types.
        break;
    }
  }
}

AccessibilityOrientation AXNodeObject::orientation() const {
  const AtomicString& ariaOrientation = getAttribute(aria_orientationAttr);
  AccessibilityOrientation orientation = AccessibilityOrientationUndefined;
  if (equalIgnoringCase(ariaOrientation, "horizontal"))
    orientation = AccessibilityOrientationHorizontal;
  else if (equalIgnoringCase(ariaOrientation, "vertical"))
    orientation = AccessibilityOrientationVertical;

  switch (roleValue()) {
    case ComboBoxRole:
    case ListBoxRole:
    case MenuRole:
    case ScrollBarRole:
    case TreeRole:
      if (orientation == AccessibilityOrientationUndefined)
        orientation = AccessibilityOrientationVertical;

      return orientation;
    case MenuBarRole:
    case SliderRole:
    case SplitterRole:
    case TabListRole:
    case ToolbarRole:
      if (orientation == AccessibilityOrientationUndefined)
        orientation = AccessibilityOrientationHorizontal;

      return orientation;
    case RadioGroupRole:
    case TreeGridRole:
    // TODO(nektar): Fix bug 532670 and remove table role.
    case TableRole:
      return orientation;
    default:
      return AXObject::orientation();
  }
}

String AXNodeObject::text() const {
  // If this is a user defined static text, use the accessible name computation.
  if (ariaRoleAttribute() == StaticTextRole)
    return computedName();

  if (!isTextControl())
    return String();

  Node* node = this->getNode();
  if (!node)
    return String();

  if (isNativeTextControl() &&
      (isHTMLTextAreaElement(*node) || isHTMLInputElement(*node)))
    return toTextControlElement(*node).value();

  if (!node->isElementNode())
    return String();

  return toElement(node)->innerText();
}

AccessibilityButtonState AXNodeObject::checkboxOrRadioValue() const {
  if (isNativeCheckboxInMixedState())
    return ButtonStateMixed;

  if (isNativeCheckboxOrRadio())
    return isChecked() ? ButtonStateOn : ButtonStateOff;

  return AXObject::checkboxOrRadioValue();
}

RGBA32 AXNodeObject::colorValue() const {
  if (!isHTMLInputElement(getNode()) || !isColorWell())
    return AXObject::colorValue();

  HTMLInputElement* input = toHTMLInputElement(getNode());
  const AtomicString& type = input->getAttribute(typeAttr);
  if (!equalIgnoringCase(type, "color"))
    return AXObject::colorValue();

  // HTMLInputElement::value always returns a string parseable by Color.
  Color color;
  bool success = color.setFromString(input->value());
  DCHECK(success);
  return color.rgb();
}

AriaCurrentState AXNodeObject::ariaCurrentState() const {
  if (!hasAttribute(aria_currentAttr))
    return AXObject::ariaCurrentState();

  const AtomicString& attributeValue = getAttribute(aria_currentAttr);
  if (attributeValue.isEmpty() || equalIgnoringCase(attributeValue, "false"))
    return AriaCurrentStateFalse;
  if (equalIgnoringCase(attributeValue, "true"))
    return AriaCurrentStateTrue;
  if (equalIgnoringCase(attributeValue, "page"))
    return AriaCurrentStatePage;
  if (equalIgnoringCase(attributeValue, "step"))
    return AriaCurrentStateStep;
  if (equalIgnoringCase(attributeValue, "location"))
    return AriaCurrentStateLocation;
  if (equalIgnoringCase(attributeValue, "date"))
    return AriaCurrentStateDate;
  if (equalIgnoringCase(attributeValue, "time"))
    return AriaCurrentStateTime;
  // An unknown value should return true.
  if (!attributeValue.isEmpty())
    return AriaCurrentStateTrue;

  return AXObject::ariaCurrentState();
}

InvalidState AXNodeObject::getInvalidState() const {
  if (hasAttribute(aria_invalidAttr)) {
    const AtomicString& attributeValue = getAttribute(aria_invalidAttr);
    if (equalIgnoringCase(attributeValue, "false"))
      return InvalidStateFalse;
    if (equalIgnoringCase(attributeValue, "true"))
      return InvalidStateTrue;
    if (equalIgnoringCase(attributeValue, "spelling"))
      return InvalidStateSpelling;
    if (equalIgnoringCase(attributeValue, "grammar"))
      return InvalidStateGrammar;
    // A yet unknown value.
    if (!attributeValue.isEmpty())
      return InvalidStateOther;
  }

  if (getNode() && getNode()->isElementNode() &&
      toElement(getNode())->isFormControlElement()) {
    HTMLFormControlElement* element = toHTMLFormControlElement(getNode());
    HeapVector<Member<HTMLFormControlElement>> invalidControls;
    bool isInvalid =
        !element->checkValidity(&invalidControls, CheckValidityDispatchNoEvent);
    return isInvalid ? InvalidStateTrue : InvalidStateFalse;
  }

  return AXObject::getInvalidState();
}

int AXNodeObject::posInSet() const {
  if (supportsSetSizeAndPosInSet()) {
    String posInSetStr = getAttribute(aria_posinsetAttr);
    if (!posInSetStr.isEmpty()) {
      int posInSet = posInSetStr.toInt();
      if (posInSet > 0)
        return posInSet;
      return 1;
    }

    return AXObject::indexInParent() + 1;
  }

  return 0;
}

int AXNodeObject::setSize() const {
  if (supportsSetSizeAndPosInSet()) {
    String setSizeStr = getAttribute(aria_setsizeAttr);
    if (!setSizeStr.isEmpty()) {
      int setSize = setSizeStr.toInt();
      if (setSize > 0)
        return setSize;
      return 1;
    }

    if (parentObject()) {
      const auto& siblings = parentObject()->children();
      return siblings.size();
    }
  }

  return 0;
}

String AXNodeObject::ariaInvalidValue() const {
  if (getInvalidState() == InvalidStateOther)
    return getAttribute(aria_invalidAttr);

  return String();
}

String AXNodeObject::valueDescription() const {
  if (!supportsRangeValue())
    return String();

  return getAttribute(aria_valuetextAttr).getString();
}

float AXNodeObject::valueForRange() const {
  if (hasAttribute(aria_valuenowAttr))
    return getAttribute(aria_valuenowAttr).toFloat();

  if (isNativeSlider())
    return toHTMLInputElement(*getNode()).valueAsNumber();

  if (isHTMLMeterElement(getNode()))
    return toHTMLMeterElement(*getNode()).value();

  return 0.0;
}

float AXNodeObject::maxValueForRange() const {
  if (hasAttribute(aria_valuemaxAttr))
    return getAttribute(aria_valuemaxAttr).toFloat();

  if (isNativeSlider())
    return toHTMLInputElement(*getNode()).maximum();

  if (isHTMLMeterElement(getNode()))
    return toHTMLMeterElement(*getNode()).max();

  return 0.0;
}

float AXNodeObject::minValueForRange() const {
  if (hasAttribute(aria_valueminAttr))
    return getAttribute(aria_valueminAttr).toFloat();

  if (isNativeSlider())
    return toHTMLInputElement(*getNode()).minimum();

  if (isHTMLMeterElement(getNode()))
    return toHTMLMeterElement(*getNode()).min();

  return 0.0;
}

float AXNodeObject::stepValueForRange() const {
  if (!isNativeSlider())
    return 0.0;

  Decimal step =
      toHTMLInputElement(*getNode()).createStepRange(RejectAny).step();
  return step.toString().toFloat();
}

String AXNodeObject::stringValue() const {
  Node* node = this->getNode();
  if (!node)
    return String();

  if (isHTMLSelectElement(*node)) {
    HTMLSelectElement& selectElement = toHTMLSelectElement(*node);
    int selectedIndex = selectElement.selectedIndex();
    const HeapVector<Member<HTMLElement>>& listItems =
        selectElement.listItems();
    if (selectedIndex >= 0 &&
        static_cast<size_t>(selectedIndex) < listItems.size()) {
      const AtomicString& overriddenDescription =
          listItems[selectedIndex]->fastGetAttribute(aria_labelAttr);
      if (!overriddenDescription.isNull())
        return overriddenDescription;
    }
    if (!selectElement.isMultiple())
      return selectElement.value();
    return String();
  }

  if (isNativeTextControl())
    return text();

  // Handle other HTML input elements that aren't text controls, like date and
  // time controls, by returning the string value, with the exception of
  // checkboxes and radio buttons (which would return "on").
  if (isHTMLInputElement(node)) {
    HTMLInputElement* input = toHTMLInputElement(node);
    if (input->type() != InputTypeNames::checkbox &&
        input->type() != InputTypeNames::radio)
      return input->value();
  }

  return String();
}

AccessibilityRole AXNodeObject::ariaRoleAttribute() const {
  return m_ariaRole;
}

// Returns the nearest LayoutBlockFlow ancestor which does not have an
// inlineBoxWrapper - i.e. is not itself an inline object.
static LayoutBlockFlow* nonInlineBlockFlow(LayoutObject* object) {
  LayoutObject* current = object;
  while (current) {
    if (current->isLayoutBlockFlow()) {
      LayoutBlockFlow* blockFlow = toLayoutBlockFlow(current);
      if (!blockFlow->inlineBoxWrapper())
        return blockFlow;
    }
    current = current->parent();
  }

  ASSERT_NOT_REACHED();
  return nullptr;
}

// Returns true if |r1| and |r2| are both non-null, both inline, and are
// contained within the same non-inline LayoutBlockFlow.
static bool isInSameNonInlineBlockFlow(LayoutObject* r1, LayoutObject* r2) {
  if (!r1 || !r2)
    return false;
  if (!r1->isInline() || !r2->isInline())
    return false;
  LayoutBlockFlow* b1 = nonInlineBlockFlow(r1);
  LayoutBlockFlow* b2 = nonInlineBlockFlow(r2);
  return b1 && b2 && b1 == b2;
}

bool AXNodeObject::isNativeCheckboxInMixedState() const {
  if (!isHTMLInputElement(m_node))
    return false;

  HTMLInputElement* input = toHTMLInputElement(m_node);
  return input->type() == InputTypeNames::checkbox &&
         input->shouldAppearIndeterminate();
}

//
// New AX name calculation.
//

String AXNodeObject::textAlternative(bool recursive,
                                     bool inAriaLabelledByTraversal,
                                     AXObjectSet& visited,
                                     AXNameFrom& nameFrom,
                                     AXRelatedObjectVector* relatedObjects,
                                     NameSources* nameSources) const {
  // If nameSources is non-null, relatedObjects is used in filling it in, so it
  // must be non-null as well.
  if (nameSources)
    ASSERT(relatedObjects);

  bool foundTextAlternative = false;

  if (!getNode() && !getLayoutObject())
    return String();

  String textAlternative = ariaTextAlternative(
      recursive, inAriaLabelledByTraversal, visited, nameFrom, relatedObjects,
      nameSources, &foundTextAlternative);
  if (foundTextAlternative && !nameSources)
    return textAlternative;

  // Step 2E from: http://www.w3.org/TR/accname-aam-1.1
  if (recursive && !inAriaLabelledByTraversal && isControl() && !isButton()) {
    // No need to set any name source info in a recursive call.
    if (isTextControl())
      return text();

    if (isRange()) {
      const AtomicString& ariaValuetext = getAttribute(aria_valuetextAttr);
      if (!ariaValuetext.isNull())
        return ariaValuetext.getString();
      return String::number(valueForRange());
    }

    return stringValue();
  }

  // Step 2D from: http://www.w3.org/TR/accname-aam-1.1
  textAlternative = nativeTextAlternative(visited, nameFrom, relatedObjects,
                                          nameSources, &foundTextAlternative);
  if (!textAlternative.isEmpty() && !nameSources)
    return textAlternative;

  // Step 2F / 2G from: http://www.w3.org/TR/accname-aam-1.1
  if (recursive || nameFromContents()) {
    nameFrom = AXNameFromContents;
    if (nameSources) {
      nameSources->push_back(NameSource(foundTextAlternative));
      nameSources->back().type = nameFrom;
    }

    Node* node = this->getNode();
    if (node && node->isTextNode())
      textAlternative = toText(node)->wholeText();
    else if (isHTMLBRElement(node))
      textAlternative = String("\n");
    else
      textAlternative = textFromDescendants(visited, false);

    if (!textAlternative.isEmpty()) {
      if (nameSources) {
        foundTextAlternative = true;
        nameSources->back().text = textAlternative;
      } else {
        return textAlternative;
      }
    }
  }

  // Step 2H from: http://www.w3.org/TR/accname-aam-1.1
  nameFrom = AXNameFromTitle;
  if (nameSources) {
    nameSources->push_back(NameSource(foundTextAlternative, titleAttr));
    nameSources->back().type = nameFrom;
  }
  const AtomicString& title = getAttribute(titleAttr);
  if (!title.isEmpty()) {
    textAlternative = title;
    if (nameSources) {
      foundTextAlternative = true;
      nameSources->back().text = textAlternative;
    } else {
      return textAlternative;
    }
  }

  nameFrom = AXNameFromUninitialized;

  if (nameSources && foundTextAlternative) {
    for (size_t i = 0; i < nameSources->size(); ++i) {
      if (!(*nameSources)[i].text.isNull() && !(*nameSources)[i].superseded) {
        NameSource& nameSource = (*nameSources)[i];
        nameFrom = nameSource.type;
        if (!nameSource.relatedObjects.isEmpty())
          *relatedObjects = nameSource.relatedObjects;
        return nameSource.text;
      }
    }
  }

  return String();
}

String AXNodeObject::textFromDescendants(AXObjectSet& visited,
                                         bool recursive) const {
  if (!canHaveChildren() && recursive)
    return String();

  StringBuilder accumulatedText;
  AXObject* previous = nullptr;

  AXObjectVector children;

  HeapVector<Member<AXObject>> ownedChildren;
  computeAriaOwnsChildren(ownedChildren);
  for (AXObject* obj = rawFirstChild(); obj; obj = obj->rawNextSibling()) {
    if (!axObjectCache().isAriaOwned(obj))
      children.push_back(obj);
  }
  for (const auto& ownedChild : ownedChildren)
    children.push_back(ownedChild);

  for (AXObject* child : children) {
    // Don't recurse into children that are explicitly marked as aria-hidden.
    // Note that we don't call isInertOrAriaHidden because that would return
    // true if any ancestor is hidden, but we need to be able to compute the
    // accessible name of object inside hidden subtrees (for example, if
    // aria-labelledby points to an object that's hidden).
    if (equalIgnoringCase(child->getAttribute(aria_hiddenAttr), "true"))
      continue;

    // If we're going between two layoutObjects that are in separate
    // LayoutBoxes, add whitespace if it wasn't there already. Intuitively if
    // you have <span>Hello</span><span>World</span>, those are part of the same
    // LayoutBox so we should return "HelloWorld", but given
    // <div>Hello</div><div>World</div> the strings are in separate boxes so we
    // should return "Hello World".
    if (previous && accumulatedText.length() &&
        !isHTMLSpace(accumulatedText[accumulatedText.length() - 1])) {
      if (!isInSameNonInlineBlockFlow(child->getLayoutObject(),
                                      previous->getLayoutObject()))
        accumulatedText.append(' ');
    }

    String result;
    if (child->isPresentational())
      result = child->textFromDescendants(visited, true);
    else
      result = recursiveTextAlternative(*child, false, visited);
    accumulatedText.append(result);
    previous = child;
  }

  return accumulatedText.toString();
}

bool AXNodeObject::nameFromLabelElement() const {
  // This unfortunately duplicates a bit of logic from textAlternative and
  // nativeTextAlternative, but it's necessary because nameFromLabelElement
  // needs to be called from computeAccessibilityIsIgnored, which isn't allowed
  // to call axObjectCache->getOrCreate.

  if (!getNode() && !getLayoutObject())
    return false;

  // Step 2A from: http://www.w3.org/TR/accname-aam-1.1
  if (isHiddenForTextAlternativeCalculation())
    return false;

  // Step 2B from: http://www.w3.org/TR/accname-aam-1.1
  HeapVector<Member<Element>> elements;
  ariaLabelledbyElementVector(elements);
  if (elements.size() > 0)
    return false;

  // Step 2C from: http://www.w3.org/TR/accname-aam-1.1
  const AtomicString& ariaLabel = getAttribute(aria_labelAttr);
  if (!ariaLabel.isEmpty())
    return false;

  // Based on
  // http://rawgit.com/w3c/aria/master/html-aam/html-aam.html#accessible-name-and-description-calculation
  // 5.1/5.5 Text inputs, Other labelable Elements
  HTMLElement* htmlElement = nullptr;
  if (getNode()->isHTMLElement())
    htmlElement = toHTMLElement(getNode());
  if (htmlElement && isLabelableElement(htmlElement)) {
    if (toLabelableElement(htmlElement)->labels() &&
        toLabelableElement(htmlElement)->labels()->length() > 0)
      return true;
  }

  return false;
}

bool AXNodeObject::nameFromContents() const {
  Node* node = getNode();
  if (!node || !node->isElementNode())
    return AXObject::nameFromContents();
  // AXObject::nameFromContents determines whether an element should take its
  // name from its descendant contents based on role. However, <select> is a
  // special case, as unlike a typical pop-up button it contains its own pop-up
  // menu's contents, which should not be used as the name.
  if (isHTMLSelectElement(node))
    return false;
  return AXObject::nameFromContents();
}

void AXNodeObject::getRelativeBounds(AXObject** outContainer,
                                     FloatRect& outBoundsInContainer,
                                     SkMatrix44& outContainerTransform) const {
  if (layoutObjectForRelativeBounds()) {
    AXObject::getRelativeBounds(outContainer, outBoundsInContainer,
                                outContainerTransform);
    return;
  }

  *outContainer = nullptr;
  outBoundsInContainer = FloatRect();
  outContainerTransform.setIdentity();

  // First check if it has explicit bounds, for example if this element is tied
  // to a canvas path. When explicit coordinates are provided, the ID of the
  // explicit container element that the coordinates are relative to must be
  // provided too.
  if (!m_explicitElementRect.isEmpty()) {
    *outContainer = axObjectCache().objectFromAXID(m_explicitContainerID);
    if (*outContainer) {
      outBoundsInContainer = FloatRect(m_explicitElementRect);
      return;
    }
  }

  // If it's in a canvas but doesn't have an explicit rect, get the bounding
  // rect of its children.
  if (getNode()->parentElement()->isInCanvasSubtree()) {
    Vector<FloatRect> rects;
    for (Node& child : NodeTraversal::childrenOf(*getNode())) {
      if (child.isHTMLElement()) {
        if (AXObject* obj = axObjectCache().get(&child)) {
          AXObject* container;
          FloatRect bounds;
          obj->getRelativeBounds(&container, bounds, outContainerTransform);
          if (container) {
            *outContainer = container;
            rects.push_back(bounds);
          }
        }
      }
    }

    if (*outContainer) {
      outBoundsInContainer = unionRect(rects);
      return;
    }
  }

  // If this object doesn't have an explicit element rect or computable from its
  // children, for now, let's return the position of the ancestor that does have
  // a position, 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.
  for (AXObject* positionProvider = parentObject(); positionProvider;
       positionProvider = positionProvider->parentObject()) {
    if (positionProvider->isAXLayoutObject()) {
      positionProvider->getRelativeBounds(outContainer, outBoundsInContainer,
                                          outContainerTransform);
      if (*outContainer)
        outBoundsInContainer.setSize(
            FloatSize(outBoundsInContainer.width(),
                      std::min(10.0f, outBoundsInContainer.height())));
      break;
    }
  }
}

static Node* getParentNodeForComputeParent(Node* node) {
  if (!node)
    return nullptr;

  Node* parentNode = nullptr;

  // Skip over <optgroup> and consider the <select> the immediate parent of an
  // <option>.
  if (isHTMLOptionElement(node))
    parentNode = toHTMLOptionElement(node)->ownerSelectElement();

  if (!parentNode)
    parentNode = node->parentNode();

  return parentNode;
}

AXObject* AXNodeObject::computeParent() const {
  ASSERT(!isDetached());
  if (Node* parentNode = getParentNodeForComputeParent(getNode()))
    return axObjectCache().getOrCreate(parentNode);

  return nullptr;
}

AXObject* AXNodeObject::computeParentIfExists() const {
  if (Node* parentNode = getParentNodeForComputeParent(getNode()))
    return axObjectCache().get(parentNode);

  return nullptr;
}

AXObject* AXNodeObject::rawFirstChild() const {
  if (!getNode())
    return 0;

  Node* firstChild = getNode()->firstChild();

  if (!firstChild)
    return 0;

  return axObjectCache().getOrCreate(firstChild);
}

AXObject* AXNodeObject::rawNextSibling() const {
  if (!getNode())
    return 0;

  Node* nextSibling = getNode()->nextSibling();
  if (!nextSibling)
    return 0;

  return axObjectCache().getOrCreate(nextSibling);
}

void AXNodeObject::addChildren() {
  ASSERT(!isDetached());
  // If the need to add more children in addition to existing children arises,
  // childrenChanged should have been called, leaving the object with no
  // children.
  ASSERT(!m_haveChildren);

  if (!m_node)
    return;

  m_haveChildren = true;

  // The only time we add children from the DOM tree to a node with a
  // layoutObject is when it's a canvas.
  if (getLayoutObject() && !isHTMLCanvasElement(*m_node))
    return;

  HeapVector<Member<AXObject>> ownedChildren;
  computeAriaOwnsChildren(ownedChildren);

  for (Node& child : NodeTraversal::childrenOf(*m_node)) {
    AXObject* childObj = axObjectCache().getOrCreate(&child);
    if (childObj && !axObjectCache().isAriaOwned(childObj))
      addChild(childObj);
  }

  for (const auto& ownedChild : ownedChildren)
    addChild(ownedChild);

  for (const auto& child : m_children)
    child->setParent(this);
}

void AXNodeObject::addChild(AXObject* child) {
  insertChild(child, m_children.size());
}

void AXNodeObject::insertChild(AXObject* child, unsigned index) {
  if (!child)
    return;

  // If the parent is asking for this child's children, then either it's the
  // first time (and clearing is a no-op), or its visibility has changed. In the
  // latter case, this child may have a stale child cached.  This can prevent
  // aria-hidden changes from working correctly. Hence, whenever a parent is
  // getting children, ensure data is not stale.
  child->clearChildren();

  if (child->accessibilityIsIgnored()) {
    const auto& children = child->children();
    size_t length = children.size();
    for (size_t i = 0; i < length; ++i)
      m_children.insert(index + i, children[i]);
  } else {
    ASSERT(child->parentObject() == this);
    m_children.insert(index, child);
  }
}

bool AXNodeObject::canHaveChildren() const {
  // If this is an AXLayoutObject, then it's okay if this object
  // doesn't have a node - there are some layoutObjects that don't have
  // associated nodes, like scroll areas and css-generated text.
  if (!getNode() && !isAXLayoutObject())
    return false;

  if (getNode() && isHTMLMapElement(getNode()))
    return false;

  AccessibilityRole role = roleValue();

  // If an element has an ARIA role of presentation, we need to consider the
  // native role when deciding whether it can have children or not - otherwise
  // giving something a role of presentation could expose inner implementation
  // details.
  if (isPresentational())
    role = nativeAccessibilityRoleIgnoringAria();

  switch (role) {
    case ImageRole:
    case ButtonRole:
    case PopUpButtonRole:
    case CheckBoxRole:
    case RadioButtonRole:
    case SwitchRole:
    case TabRole:
    case ToggleButtonRole:
    case ListBoxOptionRole:
    case ScrollBarRole:
      return false;
    case StaticTextRole:
      if (!axObjectCache().inlineTextBoxAccessibilityEnabled())
        return false;
    default:
      return true;
  }
}

Element* AXNodeObject::actionElement() const {
  Node* node = this->getNode();
  if (!node)
    return 0;

  if (isHTMLInputElement(*node)) {
    HTMLInputElement& input = toHTMLInputElement(*node);
    if (!input.isDisabledFormControl() &&
        (isCheckboxOrRadio() || input.isTextButton() ||
         input.type() == InputTypeNames::file))
      return &input;
  } else if (isHTMLButtonElement(*node)) {
    return toElement(node);
  }

  if (AXObject::isARIAInput(ariaRoleAttribute()))
    return toElement(node);

  if (isImageButton())
    return toElement(node);

  if (isHTMLSelectElement(*node))
    return toElement(node);

  switch (roleValue()) {
    case ButtonRole:
    case PopUpButtonRole:
    case ToggleButtonRole:
    case TabRole:
    case MenuItemRole:
    case MenuItemCheckBoxRole:
    case MenuItemRadioRole:
      return toElement(node);
    default:
      break;
  }

  Element* anchor = anchorElement();
  Element* clickElement = mouseButtonListener();
  if (!anchor || (clickElement && clickElement->isDescendantOf(anchor)))
    return clickElement;
  return anchor;
}

Element* AXNodeObject::anchorElement() const {
  Node* node = this->getNode();
  if (!node)
    return 0;

  AXObjectCacheImpl& cache = axObjectCache();

  // search up the DOM tree for an anchor element
  // NOTE: this assumes that any non-image with an anchor is an
  // HTMLAnchorElement
  for (; node; node = node->parentNode()) {
    if (isHTMLAnchorElement(*node) ||
        (node->layoutObject() &&
         cache.getOrCreate(node->layoutObject())->isAnchor()))
      return toElement(node);
  }

  return 0;
}

Document* AXNodeObject::getDocument() const {
  if (!getNode())
    return 0;
  return &getNode()->document();
}

void AXNodeObject::setNode(Node* node) {
  m_node = node;
}

AXObject* AXNodeObject::correspondingControlForLabelElement() const {
  HTMLLabelElement* labelElement = labelElementContainer();
  if (!labelElement)
    return 0;

  HTMLElement* correspondingControl = labelElement->control();
  if (!correspondingControl)
    return 0;

  // Make sure the corresponding control isn't a descendant of this label
  // that's in the middle of being destroyed.
  if (correspondingControl->layoutObject() &&
      !correspondingControl->layoutObject()->parent())
    return 0;

  return axObjectCache().getOrCreate(correspondingControl);
}

HTMLLabelElement* AXNodeObject::labelElementContainer() const {
  if (!getNode())
    return 0;

  // the control element should not be considered part of the label
  if (isControl())
    return 0;

  // the link element should not be considered part of the label
  if (isLink())
    return 0;

  // find if this has a ancestor that is a label
  return Traversal<HTMLLabelElement>::firstAncestorOrSelf(*getNode());
}

void AXNodeObject::setFocused(bool on) {
  if (!canSetFocusAttribute())
    return;

  Document* document = this->getDocument();
  if (!on) {
    document->clearFocusedElement();
  } else {
    Node* node = this->getNode();
    if (node && node->isElementNode()) {
      // If this node is already the currently focused node, then calling
      // focus() won't do anything.  That is a problem when focus is removed
      // from the webpage to chrome, and then returns.  In these cases, we need
      // to do what keyboard and mouse focus do, which is reset focus first.
      if (document->focusedElement() == node)
        document->clearFocusedElement();

      toElement(node)->focus();
    } else {
      document->clearFocusedElement();
    }
  }
}

void AXNodeObject::increment() {
  UserGestureIndicator gestureIndicator(DocumentUserGestureToken::create(
      getDocument(), UserGestureToken::NewGesture));
  alterSliderValue(true);
}

void AXNodeObject::decrement() {
  UserGestureIndicator gestureIndicator(DocumentUserGestureToken::create(
      getDocument(), UserGestureToken::NewGesture));
  alterSliderValue(false);
}

void AXNodeObject::setSequentialFocusNavigationStartingPoint() {
  if (!getNode())
    return;

  getNode()->document().clearFocusedElement();
  getNode()->document().setSequentialFocusNavigationStartingPoint(getNode());
}

void AXNodeObject::childrenChanged() {
  // This method is meant as a quick way of marking a portion of the
  // accessibility tree dirty.
  if (!getNode() && !getLayoutObject())
    return;

  // If this is not part of the accessibility tree because an ancestor
  // has only presentational children, invalidate this object's children but
  // skip sending a notification and skip walking up the ancestors.
  if (ancestorForWhichThisIsAPresentationalChild()) {
    setNeedsToUpdateChildren();
    return;
  }

  axObjectCache().postNotification(this, AXObjectCacheImpl::AXChildrenChanged);

  // Go up the accessibility parent chain, but only if the element already
  // exists. This method is called during layout, minimal work should be done.
  // If AX elements are created now, they could interrogate the layout tree
  // while it's in a funky state.  At the same time, process ARIA live region
  // changes.
  for (AXObject* parent = this; parent;
       parent = parent->parentObjectIfExists()) {
    parent->setNeedsToUpdateChildren();

    // These notifications always need to be sent because screenreaders are
    // reliant on them to perform.  In other words, they need to be sent even
    // when the screen reader has not accessed this live region since the last
    // update.

    // If this element supports ARIA live regions, then notify the AT of
    // changes.
    if (parent->isLiveRegion())
      axObjectCache().postNotification(parent,
                                       AXObjectCacheImpl::AXLiveRegionChanged);

    // If this element is an ARIA text box or content editable, post a "value
    // changed" notification on it so that it behaves just like a native input
    // element or textarea.
    if (isNonNativeTextControl())
      axObjectCache().postNotification(parent,
                                       AXObjectCacheImpl::AXValueChanged);
  }
}

void AXNodeObject::selectionChanged() {
  // Post the selected text changed event on the first ancestor that's
  // focused (to handle form controls, ARIA text boxes and contentEditable),
  // or the web area if the selection is just in the document somewhere.
  if (isFocused() || isWebArea()) {
    axObjectCache().postNotification(this,
                                     AXObjectCacheImpl::AXSelectedTextChanged);
    if (getDocument()) {
      AXObject* documentObject = axObjectCache().getOrCreate(getDocument());
      axObjectCache().postNotification(
          documentObject, AXObjectCacheImpl::AXDocumentSelectionChanged);
    }
  } else {
    AXObject::selectionChanged();  // Calls selectionChanged on parent.
  }
}

void AXNodeObject::textChanged() {
  // If this element supports ARIA live regions, or is part of a region with an
  // ARIA editable role, then notify the AT of changes.
  AXObjectCacheImpl& cache = axObjectCache();
  for (Node* parentNode = getNode(); parentNode;
       parentNode = parentNode->parentNode()) {
    AXObject* parent = cache.get(parentNode);
    if (!parent)
      continue;

    if (parent->isLiveRegion())
      cache.postNotification(parentNode,
                             AXObjectCacheImpl::AXLiveRegionChanged);

    // If this element is an ARIA text box or content editable, post a "value
    // changed" notification on it so that it behaves just like a native input
    // element or textarea.
    if (parent->isNonNativeTextControl())
      cache.postNotification(parentNode, AXObjectCacheImpl::AXValueChanged);
  }
}

void AXNodeObject::updateAccessibilityRole() {
  bool ignoredStatus = accessibilityIsIgnored();
  m_role = determineAccessibilityRole();

  // The AX hierarchy only needs to be updated if the ignored status of an
  // element has changed.
  if (ignoredStatus != accessibilityIsIgnored())
    childrenChanged();
}

void AXNodeObject::computeAriaOwnsChildren(
    HeapVector<Member<AXObject>>& ownedChildren) const {
  if (!hasAttribute(aria_ownsAttr))
    return;

  Vector<String> idVector;
  if (canHaveChildren() && !isNativeTextControl() &&
      !hasContentEditableAttributeSet())
    tokenVectorFromAttribute(idVector, aria_ownsAttr);

  axObjectCache().updateAriaOwns(this, idVector, ownedChildren);
}

// Based on
// http://rawgit.com/w3c/aria/master/html-aam/html-aam.html#accessible-name-and-description-calculation
String AXNodeObject::nativeTextAlternative(
    AXObjectSet& visited,
    AXNameFrom& nameFrom,
    AXRelatedObjectVector* relatedObjects,
    NameSources* nameSources,
    bool* foundTextAlternative) const {
  if (!getNode())
    return String();

  // If nameSources is non-null, relatedObjects is used in filling it in, so it
  // must be non-null as well.
  if (nameSources)
    ASSERT(relatedObjects);

  String textAlternative;
  AXRelatedObjectVector localRelatedObjects;

  const HTMLInputElement* inputElement = nullptr;
  if (isHTMLInputElement(getNode()))
    inputElement = toHTMLInputElement(getNode());

  // 5.1/5.5 Text inputs, Other labelable Elements
  // If you change this logic, update AXNodeObject::nameFromLabelElement, too.
  HTMLElement* htmlElement = nullptr;
  if (getNode()->isHTMLElement())
    htmlElement = toHTMLElement(getNode());

  if (htmlElement && htmlElement->isLabelable()) {
    nameFrom = AXNameFromRelatedElement;
    if (nameSources) {
      nameSources->push_back(NameSource(*foundTextAlternative));
      nameSources->back().type = nameFrom;
      nameSources->back().nativeSource = AXTextFromNativeHTMLLabel;
    }

    LabelsNodeList* labels = toLabelableElement(htmlElement)->labels();
    if (labels && labels->length() > 0) {
      HeapVector<Member<Element>> labelElements;
      for (unsigned labelIndex = 0; labelIndex < labels->length();
           ++labelIndex) {
        Element* label = labels->item(labelIndex);
        if (nameSources) {
          if (!label->getAttribute(forAttr).isEmpty() &&
              label->getAttribute(forAttr) == htmlElement->getIdAttribute()) {
            nameSources->back().nativeSource = AXTextFromNativeHTMLLabelFor;
          } else {
            nameSources->back().nativeSource = AXTextFromNativeHTMLLabelWrapped;
          }
        }
        labelElements.push_back(label);
      }

      textAlternative =
          textFromElements(false, visited, labelElements, relatedObjects);
      if (!textAlternative.isNull()) {
        *foundTextAlternative = true;
        if (nameSources) {
          NameSource& source = nameSources->back();
          source.relatedObjects = *relatedObjects;
          source.text = textAlternative;
        } else {
          return textAlternative;
        }
      } else if (nameSources) {
        nameSources->back().invalid = true;
      }
    }
  }

  // 5.2 input type="button", input type="submit" and input type="reset"
  if (inputElement && inputElement->isTextButton()) {
    // value attribue
    nameFrom = AXNameFromValue;
    if (nameSources) {
      nameSources->push_back(NameSource(*foundTextAlternative, valueAttr));
      nameSources->back().type = nameFrom;
    }
    String value = inputElement->value();
    if (!value.isNull()) {
      textAlternative = value;
      if (nameSources) {
        NameSource& source = nameSources->back();
        source.text = textAlternative;
        *foundTextAlternative = true;
      } else {
        return textAlternative;
      }
    }

    // Get default value if object is not laid out.
    // If object is laid out, it will have a layout object for the label.
    if (!getLayoutObject()) {
      String defaultLabel = inputElement->valueOrDefaultLabel();
      if (value.isNull() && !defaultLabel.isNull()) {
        // default label
        nameFrom = AXNameFromContents;
        if (nameSources) {
          nameSources->push_back(NameSource(*foundTextAlternative));
          nameSources->back().type = nameFrom;
        }
        textAlternative = defaultLabel;
        if (nameSources) {
          NameSource& source = nameSources->back();
          source.text = textAlternative;
          *foundTextAlternative = true;
        } else {
          return textAlternative;
        }
      }
    }
    return textAlternative;
  }

  // 5.3 input type="image"
  if (inputElement &&
      inputElement->getAttribute(typeAttr) == InputTypeNames::image) {
    // alt attr
    nameFrom = AXNameFromAttribute;
    if (nameSources) {
      nameSources->push_back(NameSource(*foundTextAlternative, altAttr));
      nameSources->back().type = nameFrom;
    }
    const AtomicString& alt = inputElement->getAttribute(altAttr);
    if (!alt.isNull()) {
      textAlternative = alt;
      if (nameSources) {
        NameSource& source = nameSources->back();
        source.attributeValue = alt;
        source.text = textAlternative;
        *foundTextAlternative = true;
      } else {
        return textAlternative;
      }
    }

    // value attr
    if (nameSources) {
      nameSources->push_back(NameSource(*foundTextAlternative, valueAttr));
      nameSources->back().type = nameFrom;
    }
    nameFrom = AXNameFromAttribute;
    String value = inputElement->value();
    if (!value.isNull()) {
      textAlternative = value;
      if (nameSources) {
        NameSource& source = nameSources->back();
        source.text = textAlternative;
        *foundTextAlternative = true;
      } else {
        return textAlternative;
      }
    }

    // localised default value ("Submit")
    nameFrom = AXNameFromValue;
    textAlternative = inputElement->locale().queryString(
        WebLocalizedString::SubmitButtonDefaultLabel);
    if (nameSources) {
      nameSources->push_back(NameSource(*foundTextAlternative, typeAttr));
      NameSource& source = nameSources->back();
      source.attributeValue = inputElement->getAttribute(typeAttr);
      source.type = nameFrom;
      source.text = textAlternative;
      *foundTextAlternative = true;
    } else {
      return textAlternative;
    }
    return textAlternative;
  }

  // 5.1 Text inputs - step 3 (placeholder attribute)
  if (htmlElement && htmlElement->isTextControl()) {
    nameFrom = AXNameFromPlaceholder;
    if (nameSources) {
      nameSources->push_back(
          NameSource(*foundTextAlternative, placeholderAttr));
      NameSource& source = nameSources->back();
      source.type = nameFrom;
    }
    const String placeholder = placeholderFromNativeAttribute();
    if (!placeholder.isEmpty()) {
      textAlternative = placeholder;
      if (nameSources) {
        NameSource& source = nameSources->back();
        source.text = textAlternative;
        source.attributeValue = htmlElement->fastGetAttribute(placeholderAttr);
        *foundTextAlternative = true;
      } else {
        return textAlternative;
      }
    }

    // Also check for aria-placeholder.
    nameFrom = AXNameFromPlaceholder;
    if (nameSources) {
      nameSources->push_back(
          NameSource(*foundTextAlternative, aria_placeholderAttr));
      NameSource& source = nameSources->back();
      source.type = nameFrom;
    }
    const AtomicString& ariaPlaceholder =
        htmlElement->fastGetAttribute(aria_placeholderAttr);
    if (!ariaPlaceholder.isEmpty()) {
      textAlternative = ariaPlaceholder;
      if (nameSources) {
        NameSource& source = nameSources->back();
        source.text = textAlternative;
        source.attributeValue = ariaPlaceholder;
        *foundTextAlternative = true;
      } else {
        return textAlternative;
      }
    }

    return textAlternative;
  }

  // 5.7 figure and figcaption Elements
  if (getNode()->hasTagName(figureTag)) {
    // figcaption
    nameFrom = AXNameFromRelatedElement;
    if (nameSources) {
      nameSources->push_back(NameSource(*foundTextAlternative));
      nameSources->back().type = nameFrom;
      nameSources->back().nativeSource = AXTextFromNativeHTMLFigcaption;
    }
    Element* figcaption = nullptr;
    for (Element& element : ElementTraversal::descendantsOf(*(getNode()))) {
      if (element.hasTagName(figcaptionTag)) {
        figcaption = &element;
        break;
      }
    }
    if (figcaption) {
      AXObject* figcaptionAXObject = axObjectCache().getOrCreate(figcaption);
      if (figcaptionAXObject) {
        textAlternative =
            recursiveTextAlternative(*figcaptionAXObject, false, visited);

        if (relatedObjects) {
          localRelatedObjects.push_back(
              new NameSourceRelatedObject(figcaptionAXObject, textAlternative));
          *relatedObjects = localRelatedObjects;
          localRelatedObjects.clear();
        }

        if (nameSources) {
          NameSource& source = nameSources->back();
          source.relatedObjects = *relatedObjects;
          source.text = textAlternative;
          *foundTextAlternative = true;
        } else {
          return textAlternative;
        }
      }
    }
    return textAlternative;
  }

  // 5.8 img or area Element
  if (isHTMLImageElement(getNode()) || isHTMLAreaElement(getNode()) ||
      (getLayoutObject() && getLayoutObject()->isSVGImage())) {
    // alt
    nameFrom = AXNameFromAttribute;
    if (nameSources) {
      nameSources->push_back(NameSource(*foundTextAlternative, altAttr));
      nameSources->back().type = nameFrom;
    }
    const AtomicString& alt = getAttribute(altAttr);
    if (!alt.isNull()) {
      textAlternative = alt;
      if (nameSources) {
        NameSource& source = nameSources->back();
        source.attributeValue = alt;
        source.text = textAlternative;
        *foundTextAlternative = true;
      } else {
        return textAlternative;
      }
    }
    return textAlternative;
  }

  // 5.9 table Element
  if (isHTMLTableElement(getNode())) {
    HTMLTableElement* tableElement = toHTMLTableElement(getNode());

    // caption
    nameFrom = AXNameFromCaption;
    if (nameSources) {
      nameSources->push_back(NameSource(*foundTextAlternative));
      nameSources->back().type = nameFrom;
      nameSources->back().nativeSource = AXTextFromNativeHTMLTableCaption;
    }
    HTMLTableCaptionElement* caption = tableElement->caption();
    if (caption) {
      AXObject* captionAXObject = axObjectCache().getOrCreate(caption);
      if (captionAXObject) {
        textAlternative =
            recursiveTextAlternative(*captionAXObject, false, visited);
        if (relatedObjects) {
          localRelatedObjects.push_back(
              new NameSourceRelatedObject(captionAXObject, textAlternative));
          *relatedObjects = localRelatedObjects;
          localRelatedObjects.clear();
        }

        if (nameSources) {
          NameSource& source = nameSources->back();
          source.relatedObjects = *relatedObjects;
          source.text = textAlternative;
          *foundTextAlternative = true;
        } else {
          return textAlternative;
        }
      }
    }

    // summary
    nameFrom = AXNameFromAttribute;
    if (nameSources) {
      nameSources->push_back(NameSource(*foundTextAlternative, summaryAttr));
      nameSources->back().type = nameFrom;
    }
    const AtomicString& summary = getAttribute(summaryAttr);
    if (!summary.isNull()) {
      textAlternative = summary;
      if (nameSources) {
        NameSource& source = nameSources->back();
        source.attributeValue = summary;
        source.text = textAlternative;
        *foundTextAlternative = true;
      } else {
        return textAlternative;
      }
    }

    return textAlternative;
  }

  // Per SVG AAM 1.0's modifications to 2D of this algorithm.
  if (getNode()->isSVGElement()) {
    nameFrom = AXNameFromRelatedElement;
    if (nameSources) {
      nameSources->push_back(NameSource(*foundTextAlternative));
      nameSources->back().type = nameFrom;
      nameSources->back().nativeSource = AXTextFromNativeHTMLTitleElement;
    }
    ASSERT(getNode()->isContainerNode());
    Element* title = ElementTraversal::firstChild(
        toContainerNode(*(getNode())), HasTagName(SVGNames::titleTag));

    if (title) {
      AXObject* titleAXObject = axObjectCache().getOrCreate(title);
      if (titleAXObject && !visited.contains(titleAXObject)) {
        textAlternative =
            recursiveTextAlternative(*titleAXObject, false, visited);
        if (relatedObjects) {
          localRelatedObjects.push_back(
              new NameSourceRelatedObject(titleAXObject, textAlternative));
          *relatedObjects = localRelatedObjects;
          localRelatedObjects.clear();
        }
      }
      if (nameSources) {
        NameSource& source = nameSources->back();
        source.text = textAlternative;
        source.relatedObjects = *relatedObjects;
        *foundTextAlternative = true;
      } else {
        return textAlternative;
      }
    }
  }

  // Fieldset / legend.
  if (isHTMLFieldSetElement(getNode())) {
    nameFrom = AXNameFromRelatedElement;
    if (nameSources) {
      nameSources->push_back(NameSource(*foundTextAlternative));
      nameSources->back().type = nameFrom;
      nameSources->back().nativeSource = AXTextFromNativeHTMLLegend;
    }
    HTMLElement* legend = toHTMLFieldSetElement(getNode())->legend();
    if (legend) {
      AXObject* legendAXObject = axObjectCache().getOrCreate(legend);
      // Avoid an infinite loop
      if (legendAXObject && !visited.contains(legendAXObject)) {
        textAlternative =
            recursiveTextAlternative(*legendAXObject, false, visited);

        if (relatedObjects) {
          localRelatedObjects.push_back(
              new NameSourceRelatedObject(legendAXObject, textAlternative));
          *relatedObjects = localRelatedObjects;
          localRelatedObjects.clear();
        }

        if (nameSources) {
          NameSource& source = nameSources->back();
          source.relatedObjects = *relatedObjects;
          source.text = textAlternative;
          *foundTextAlternative = true;
        } else {
          return textAlternative;
        }
      }
    }
  }

  // Document.
  if (isWebArea()) {
    Document* document = this->getDocument();
    if (document) {
      nameFrom = AXNameFromAttribute;
      if (nameSources) {
        nameSources->push_back(
            NameSource(foundTextAlternative, aria_labelAttr));
        nameSources->back().type = nameFrom;
      }
      if (Element* documentElement = document->documentElement()) {
        const AtomicString& ariaLabel =
            documentElement->getAttribute(aria_labelAttr);
        if (!ariaLabel.isEmpty()) {
          textAlternative = ariaLabel;

          if (nameSources) {
            NameSource& source = nameSources->back();
            source.text = textAlternative;
            source.attributeValue = ariaLabel;
            *foundTextAlternative = true;
          } else {
            return textAlternative;
          }
        }
      }

      nameFrom = AXNameFromRelatedElement;
      if (nameSources) {
        nameSources->push_back(NameSource(*foundTextAlternative));
        nameSources->back().type = nameFrom;
        nameSources->back().nativeSource = AXTextFromNativeHTMLTitleElement;
      }

      textAlternative = document->title();

      Element* titleElement = document->titleElement();
      AXObject* titleAXObject = axObjectCache().getOrCreate(titleElement);
      if (titleAXObject) {
        if (relatedObjects) {
          localRelatedObjects.push_back(
              new NameSourceRelatedObject(titleAXObject, textAlternative));
          *relatedObjects = localRelatedObjects;
          localRelatedObjects.clear();
        }

        if (nameSources) {
          NameSource& source = nameSources->back();
          source.relatedObjects = *relatedObjects;
          source.text = textAlternative;
          *foundTextAlternative = true;
        } else {
          return textAlternative;
        }
      }
    }
  }

  return textAlternative;
}

String AXNodeObject::description(AXNameFrom nameFrom,
                                 AXDescriptionFrom& descriptionFrom,
                                 AXObjectVector* descriptionObjects) const {
  AXRelatedObjectVector relatedObjects;
  String result =
      description(nameFrom, descriptionFrom, nullptr, &relatedObjects);
  if (descriptionObjects) {
    descriptionObjects->clear();
    for (size_t i = 0; i < relatedObjects.size(); i++)
      descriptionObjects->push_back(relatedObjects[i]->object);
  }

  return collapseWhitespace(result);
}

// Based on
// http://rawgit.com/w3c/aria/master/html-aam/html-aam.html#accessible-name-and-description-calculation
String AXNodeObject::description(AXNameFrom nameFrom,
                                 AXDescriptionFrom& descriptionFrom,
                                 DescriptionSources* descriptionSources,
                                 AXRelatedObjectVector* relatedObjects) const {
  // If descriptionSources is non-null, relatedObjects is used in filling it in,
  // so it must be non-null as well.
  if (descriptionSources)
    ASSERT(relatedObjects);

  if (!getNode())
    return String();

  String description;
  bool foundDescription = false;

  descriptionFrom = AXDescriptionFromRelatedElement;
  if (descriptionSources) {
    descriptionSources->push_back(
        DescriptionSource(foundDescription, aria_describedbyAttr));
    descriptionSources->back().type = descriptionFrom;
  }

  // aria-describedby overrides any other accessible description, from:
  // http://rawgit.com/w3c/aria/master/html-aam/html-aam.html
  const AtomicString& ariaDescribedby = getAttribute(aria_describedbyAttr);
  if (!ariaDescribedby.isNull()) {
    if (descriptionSources)
      descriptionSources->back().attributeValue = ariaDescribedby;

    description = textFromAriaDescribedby(relatedObjects);

    if (!description.isNull()) {
      if (descriptionSources) {
        DescriptionSource& source = descriptionSources->back();
        source.type = descriptionFrom;
        source.relatedObjects = *relatedObjects;
        source.text = description;
        foundDescription = true;
      } else {
        return description;
      }
    } else if (descriptionSources) {
      descriptionSources->back().invalid = true;
    }
  }

  const HTMLInputElement* inputElement = nullptr;
  if (isHTMLInputElement(getNode()))
    inputElement = toHTMLInputElement(getNode());

  // value, 5.2.2 from: http://rawgit.com/w3c/aria/master/html-aam/html-aam.html
  if (nameFrom != AXNameFromValue && inputElement &&
      inputElement->isTextButton()) {
    descriptionFrom = AXDescriptionFromAttribute;
    if (descriptionSources) {
      descriptionSources->push_back(
          DescriptionSource(foundDescription, valueAttr));
      descriptionSources->back().type = descriptionFrom;
    }
    String value = inputElement->value();
    if (!value.isNull()) {
      description = value;
      if (descriptionSources) {
        DescriptionSource& source = descriptionSources->back();
        source.text = description;
        foundDescription = true;
      } else {
        return description;
      }
    }
  }

  // table caption, 5.9.2 from:
  // http://rawgit.com/w3c/aria/master/html-aam/html-aam.html
  if (nameFrom != AXNameFromCaption && isHTMLTableElement(getNode())) {
    HTMLTableElement* tableElement = toHTMLTableElement(getNode());

    descriptionFrom = AXDescriptionFromRelatedElement;
    if (descriptionSources) {
      descriptionSources->push_back(DescriptionSource(foundDescription));
      descriptionSources->back().type = descriptionFrom;
      descriptionSources->back().nativeSource =
          AXTextFromNativeHTMLTableCaption;
    }
    HTMLTableCaptionElement* caption = tableElement->caption();
    if (caption) {
      AXObject* captionAXObject = axObjectCache().getOrCreate(caption);
      if (captionAXObject) {
        AXObjectSet visited;
        description =
            recursiveTextAlternative(*captionAXObject, false, visited);
        if (relatedObjects)
          relatedObjects->push_back(
              new NameSourceRelatedObject(captionAXObject, description));

        if (descriptionSources) {
          DescriptionSource& source = descriptionSources->back();
          source.relatedObjects = *relatedObjects;
          source.text = description;
          foundDescription = true;
        } else {
          return description;
        }
      }
    }
  }

  // summary, 5.6.2 from:
  // http://rawgit.com/w3c/aria/master/html-aam/html-aam.html
  if (nameFrom != AXNameFromContents && isHTMLSummaryElement(getNode())) {
    descriptionFrom = AXDescriptionFromContents;
    if (descriptionSources) {
      descriptionSources->push_back(DescriptionSource(foundDescription));
      descriptionSources->back().type = descriptionFrom;
    }

    AXObjectSet visited;
    description = textFromDescendants(visited, false);

    if (!description.isEmpty()) {
      if (descriptionSources) {
        foundDescription = true;
        descriptionSources->back().text = description;
      } else {
        return description;
      }
    }
  }

  // title attribute, from:
  // http://rawgit.com/w3c/aria/master/html-aam/html-aam.html
  if (nameFrom != AXNameFromTitle) {
    descriptionFrom = AXDescriptionFromAttribute;
    if (descriptionSources) {
      descriptionSources->push_back(
          DescriptionSource(foundDescription, titleAttr));
      descriptionSources->back().type = descriptionFrom;
    }
    const AtomicString& title = getAttribute(titleAttr);
    if (!title.isEmpty()) {
      description = title;
      if (descriptionSources) {
        foundDescription = true;
        descriptionSources->back().text = description;
      } else {
        return description;
      }
    }
  }

  // aria-help.
  // FIXME: this is not part of the official standard, but it's needed because
  // the built-in date/time controls use it.
  descriptionFrom = AXDescriptionFromAttribute;
  if (descriptionSources) {
    descriptionSources->push_back(
        DescriptionSource(foundDescription, aria_helpAttr));
    descriptionSources->back().type = descriptionFrom;
  }
  const AtomicString& help = getAttribute(aria_helpAttr);
  if (!help.isEmpty()) {
    description = help;
    if (descriptionSources) {
      foundDescription = true;
      descriptionSources->back().text = description;
    } else {
      return description;
    }
  }

  descriptionFrom = AXDescriptionFromUninitialized;

  if (foundDescription) {
    for (size_t i = 0; i < descriptionSources->size(); ++i) {
      if (!(*descriptionSources)[i].text.isNull() &&
          !(*descriptionSources)[i].superseded) {
        DescriptionSource& descriptionSource = (*descriptionSources)[i];
        descriptionFrom = descriptionSource.type;
        if (!descriptionSource.relatedObjects.isEmpty())
          *relatedObjects = descriptionSource.relatedObjects;
        return descriptionSource.text;
      }
    }
  }

  return String();
}

String AXNodeObject::placeholder(AXNameFrom nameFrom) const {
  if (nameFrom == AXNameFromPlaceholder)
    return String();

  Node* node = getNode();
  if (!node || !node->isHTMLElement())
    return String();

  String nativePlaceholder = placeholderFromNativeAttribute();
  if (!nativePlaceholder.isEmpty())
    return nativePlaceholder;

  const AtomicString& ariaPlaceholder =
      toHTMLElement(node)->fastGetAttribute(aria_placeholderAttr);
  if (!ariaPlaceholder.isEmpty())
    return ariaPlaceholder;

  return String();
}

String AXNodeObject::placeholderFromNativeAttribute() const {
  Node* node = getNode();
  if (!node || !isTextControlElement(node))
    return String();
  return toTextControlElement(node)->strippedPlaceholder();
}

DEFINE_TRACE(AXNodeObject) {
  visitor->trace(m_node);
  AXObject::trace(visitor);
}

}  // namespace blink
