/*
 * Copyright (C) 2008, 2009, 2011 Apple 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/AXObject.h"

#include "SkMatrix44.h"
#include "core/css/resolver/StyleResolver.h"
#include "core/dom/AccessibleNode.h"
#include "core/dom/DocumentUserGestureToken.h"
#include "core/editing/EditingUtilities.h"
#include "core/editing/VisibleUnits.h"
#include "core/frame/FrameView.h"
#include "core/frame/LocalFrame.h"
#include "core/frame/Settings.h"
#include "core/html/HTMLDialogElement.h"
#include "core/html/HTMLFrameOwnerElement.h"
#include "core/html/parser/HTMLParserIdioms.h"
#include "core/layout/LayoutBoxModelObject.h"
#include "modules/accessibility/AXObjectCacheImpl.h"
#include "platform/UserGestureIndicator.h"
#include "platform/text/PlatformLocale.h"
#include "wtf/HashSet.h"
#include "wtf/StdLibExtras.h"
#include "wtf/text/WTFString.h"

using blink::WebLocalizedString;

namespace blink {

using namespace HTMLNames;

namespace {
typedef HashMap<String, AccessibilityRole, CaseFoldingHash> ARIARoleMap;
typedef HashSet<String, CaseFoldingHash> ARIAWidgetSet;

struct RoleEntry {
  const char* ariaRole;
  AccessibilityRole webcoreRole;
};

const RoleEntry roles[] = {{"alert", AlertRole},
                           {"alertdialog", AlertDialogRole},
                           {"application", ApplicationRole},
                           {"article", ArticleRole},
                           {"banner", BannerRole},
                           {"button", ButtonRole},
                           {"cell", CellRole},
                           {"checkbox", CheckBoxRole},
                           {"columnheader", ColumnHeaderRole},
                           {"combobox", ComboBoxRole},
                           {"complementary", ComplementaryRole},
                           {"contentinfo", ContentInfoRole},
                           {"definition", DefinitionRole},
                           {"dialog", DialogRole},
                           {"directory", DirectoryRole},
                           {"document", DocumentRole},
                           {"feed", FeedRole},
                           {"figure", FigureRole},
                           {"form", FormRole},
                           {"grid", GridRole},
                           {"gridcell", CellRole},
                           {"group", GroupRole},
                           {"heading", HeadingRole},
                           {"img", ImageRole},
                           {"link", LinkRole},
                           {"list", ListRole},
                           {"listbox", ListBoxRole},
                           {"listitem", ListItemRole},
                           {"log", LogRole},
                           {"main", MainRole},
                           {"marquee", MarqueeRole},
                           {"math", MathRole},
                           {"menu", MenuRole},
                           {"menubar", MenuBarRole},
                           {"menuitem", MenuItemRole},
                           {"menuitemcheckbox", MenuItemCheckBoxRole},
                           {"menuitemradio", MenuItemRadioRole},
                           {"navigation", NavigationRole},
                           {"none", NoneRole},
                           {"note", NoteRole},
                           {"option", ListBoxOptionRole},
                           {"presentation", PresentationalRole},
                           {"progressbar", ProgressIndicatorRole},
                           {"radio", RadioButtonRole},
                           {"radiogroup", RadioGroupRole},
                           {"region", RegionRole},
                           {"row", RowRole},
                           {"rowheader", RowHeaderRole},
                           {"scrollbar", ScrollBarRole},
                           {"search", SearchRole},
                           {"searchbox", SearchBoxRole},
                           {"separator", SplitterRole},
                           {"slider", SliderRole},
                           {"spinbutton", SpinButtonRole},
                           {"status", StatusRole},
                           {"switch", SwitchRole},
                           {"tab", TabRole},
                           {"table", TableRole},
                           {"tablist", TabListRole},
                           {"tabpanel", TabPanelRole},
                           {"term", TermRole},
                           {"text", StaticTextRole},
                           {"textbox", TextFieldRole},
                           {"timer", TimerRole},
                           {"toolbar", ToolbarRole},
                           {"tooltip", UserInterfaceTooltipRole},
                           {"tree", TreeRole},
                           {"treegrid", TreeGridRole},
                           {"treeitem", TreeItemRole}};

struct InternalRoleEntry {
  AccessibilityRole webcoreRole;
  const char* internalRoleName;
};

const InternalRoleEntry internalRoles[] = {
    {UnknownRole, "Unknown"},
    {AbbrRole, "Abbr"},
    {AlertDialogRole, "AlertDialog"},
    {AlertRole, "Alert"},
    {AnchorRole, "Anchor"},
    {AnnotationRole, "Annotation"},
    {ApplicationRole, "Application"},
    {ArticleRole, "Article"},
    {AudioRole, "Audio"},
    {BannerRole, "Banner"},
    {BlockquoteRole, "Blockquote"},
    // TODO(nektar): Delete busy_indicator role. It's used nowhere.
    {BusyIndicatorRole, "BusyIndicator"},
    {ButtonRole, "Button"},
    {CanvasRole, "Canvas"},
    {CaptionRole, "Caption"},
    {CellRole, "Cell"},
    {CheckBoxRole, "CheckBox"},
    {ColorWellRole, "ColorWell"},
    {ColumnHeaderRole, "ColumnHeader"},
    {ColumnRole, "Column"},
    {ComboBoxRole, "ComboBox"},
    {ComplementaryRole, "Complementary"},
    {ContentInfoRole, "ContentInfo"},
    {DateRole, "Date"},
    {DateTimeRole, "DateTime"},
    {DefinitionRole, "Definition"},
    {DescriptionListDetailRole, "DescriptionListDetail"},
    {DescriptionListRole, "DescriptionList"},
    {DescriptionListTermRole, "DescriptionListTerm"},
    {DetailsRole, "Details"},
    {DialogRole, "Dialog"},
    {DirectoryRole, "Directory"},
    {DisclosureTriangleRole, "DisclosureTriangle"},
    {DivRole, "Div"},
    {DocumentRole, "Document"},
    {EmbeddedObjectRole, "EmbeddedObject"},
    {FeedRole, "feed"},
    {FigcaptionRole, "Figcaption"},
    {FigureRole, "Figure"},
    {FooterRole, "Footer"},
    {FormRole, "Form"},
    {GridRole, "Grid"},
    {GroupRole, "Group"},
    {HeadingRole, "Heading"},
    {IframePresentationalRole, "IframePresentational"},
    {IframeRole, "Iframe"},
    {IgnoredRole, "Ignored"},
    {ImageMapLinkRole, "ImageMapLink"},
    {ImageMapRole, "ImageMap"},
    {ImageRole, "Image"},
    {InlineTextBoxRole, "InlineTextBox"},
    {InputTimeRole, "InputTime"},
    {LabelRole, "Label"},
    {LegendRole, "Legend"},
    {LinkRole, "Link"},
    {LineBreakRole, "LineBreak"},
    {ListBoxOptionRole, "ListBoxOption"},
    {ListBoxRole, "ListBox"},
    {ListItemRole, "ListItem"},
    {ListMarkerRole, "ListMarker"},
    {ListRole, "List"},
    {LogRole, "Log"},
    {MainRole, "Main"},
    {MarkRole, "Mark"},
    {MarqueeRole, "Marquee"},
    {MathRole, "Math"},
    {MenuBarRole, "MenuBar"},
    {MenuButtonRole, "MenuButton"},
    {MenuItemRole, "MenuItem"},
    {MenuItemCheckBoxRole, "MenuItemCheckBox"},
    {MenuItemRadioRole, "MenuItemRadio"},
    {MenuListOptionRole, "MenuListOption"},
    {MenuListPopupRole, "MenuListPopup"},
    {MenuRole, "Menu"},
    {MeterRole, "Meter"},
    {NavigationRole, "Navigation"},
    {NoneRole, "None"},
    {NoteRole, "Note"},
    {OutlineRole, "Outline"},
    {ParagraphRole, "Paragraph"},
    {PopUpButtonRole, "PopUpButton"},
    {PreRole, "Pre"},
    {PresentationalRole, "Presentational"},
    {ProgressIndicatorRole, "ProgressIndicator"},
    {RadioButtonRole, "RadioButton"},
    {RadioGroupRole, "RadioGroup"},
    {RegionRole, "Region"},
    {RootWebAreaRole, "RootWebArea"},
    {RowHeaderRole, "RowHeader"},
    {RowRole, "Row"},
    {RubyRole, "Ruby"},
    {RulerRole, "Ruler"},
    {SVGRootRole, "SVGRoot"},
    {ScrollAreaRole, "ScrollArea"},
    {ScrollBarRole, "ScrollBar"},
    {SeamlessWebAreaRole, "SeamlessWebArea"},
    {SearchRole, "Search"},
    {SearchBoxRole, "SearchBox"},
    {SliderRole, "Slider"},
    {SliderThumbRole, "SliderThumb"},
    {SpinButtonPartRole, "SpinButtonPart"},
    {SpinButtonRole, "SpinButton"},
    {SplitterRole, "Splitter"},
    {StaticTextRole, "StaticText"},
    {StatusRole, "Status"},
    {SwitchRole, "Switch"},
    {TabGroupRole, "TabGroup"},
    {TabListRole, "TabList"},
    {TabPanelRole, "TabPanel"},
    {TabRole, "Tab"},
    {TableHeaderContainerRole, "TableHeaderContainer"},
    {TableRole, "Table"},
    {TermRole, "Term"},
    {TextFieldRole, "TextField"},
    {TimeRole, "Time"},
    {TimerRole, "Timer"},
    {ToggleButtonRole, "ToggleButton"},
    {ToolbarRole, "Toolbar"},
    {TreeGridRole, "TreeGrid"},
    {TreeItemRole, "TreeItem"},
    {TreeRole, "Tree"},
    {UserInterfaceTooltipRole, "UserInterfaceTooltip"},
    {VideoRole, "Video"},
    {WebAreaRole, "WebArea"},
    {WindowRole, "Window"}};

static_assert(WTF_ARRAY_LENGTH(internalRoles) == NumRoles,
              "Not all internal roles have an entry in internalRoles array");

// Roles which we need to map in the other direction
const RoleEntry reverseRoles[] = {
    {"button", ToggleButtonRole},     {"combobox", PopUpButtonRole},
    {"contentinfo", FooterRole},      {"menuitem", MenuButtonRole},
    {"menuitem", MenuListOptionRole}, {"progressbar", MeterRole},
    {"textbox", TextFieldRole}};

static ARIARoleMap* createARIARoleMap() {
  ARIARoleMap* roleMap = new ARIARoleMap;

  for (size_t i = 0; i < WTF_ARRAY_LENGTH(roles); ++i)
    roleMap->set(String(roles[i].ariaRole), roles[i].webcoreRole);
  return roleMap;
}

static Vector<AtomicString>* createRoleNameVector() {
  Vector<AtomicString>* roleNameVector = new Vector<AtomicString>(NumRoles);
  for (int i = 0; i < NumRoles; i++)
    (*roleNameVector)[i] = nullAtom;

  for (size_t i = 0; i < WTF_ARRAY_LENGTH(roles); ++i)
    (*roleNameVector)[roles[i].webcoreRole] = AtomicString(roles[i].ariaRole);

  for (size_t i = 0; i < WTF_ARRAY_LENGTH(reverseRoles); ++i)
    (*roleNameVector)[reverseRoles[i].webcoreRole] =
        AtomicString(reverseRoles[i].ariaRole);

  return roleNameVector;
}

static Vector<AtomicString>* createInternalRoleNameVector() {
  Vector<AtomicString>* internalRoleNameVector =
      new Vector<AtomicString>(NumRoles);
  for (size_t i = 0; i < WTF_ARRAY_LENGTH(internalRoles); i++)
    (*internalRoleNameVector)[internalRoles[i].webcoreRole] =
        AtomicString(internalRoles[i].internalRoleName);

  return internalRoleNameVector;
}

const char* ariaWidgets[] = {
    // From http://www.w3.org/TR/wai-aria/roles#widget_roles
    "alert", "alertdialog", "button", "checkbox", "dialog", "gridcell", "link",
    "log", "marquee", "menuitem", "menuitemcheckbox", "menuitemradio", "option",
    "progressbar", "radio", "scrollbar", "slider", "spinbutton", "status",
    "tab", "tabpanel", "textbox", "timer", "tooltip", "treeitem",
    // Composite user interface widgets.
    // This list is also from the w3.org site referenced above.
    "combobox", "grid", "listbox", "menu", "menubar", "radiogroup", "tablist",
    "tree", "treegrid"};

static ARIAWidgetSet* createARIARoleWidgetSet() {
  ARIAWidgetSet* widgetSet = new HashSet<String, CaseFoldingHash>();
  for (size_t i = 0; i < WTF_ARRAY_LENGTH(ariaWidgets); ++i)
    widgetSet->insert(String(ariaWidgets[i]));
  return widgetSet;
}

const char* ariaInteractiveWidgetAttributes[] = {
    // These attributes implicitly indicate the given widget is interactive.
    // From http://www.w3.org/TR/wai-aria/states_and_properties#attrs_widgets
    "aria-activedescendant", "aria-checked",  "aria-controls",
    "aria-disabled",  // If it's disabled, it can be made interactive.
    "aria-expanded",         "aria-haspopup", "aria-multiselectable",
    "aria-pressed",          "aria-required", "aria-selected"};

HTMLDialogElement* getActiveDialogElement(Node* node) {
  return node->document().activeModalDialog();
}

}  // namespace

unsigned AXObject::s_numberOfLiveAXObjects = 0;

AXObject::AXObject(AXObjectCacheImpl& axObjectCache)
    : m_id(0),
      m_haveChildren(false),
      m_role(UnknownRole),
      m_lastKnownIsIgnoredValue(DefaultBehavior),
      m_explicitContainerID(0),
      m_parent(nullptr),
      m_lastModificationCount(-1),
      m_cachedIsIgnored(false),
      m_cachedIsInertOrAriaHidden(false),
      m_cachedIsDescendantOfLeafNode(false),
      m_cachedIsDescendantOfDisabledNode(false),
      m_cachedHasInheritedPresentationalRole(false),
      m_cachedIsPresentationalChild(false),
      m_cachedAncestorExposesActiveDescendant(false),
      m_cachedLiveRegionRoot(nullptr),
      m_axObjectCache(&axObjectCache) {
  ++s_numberOfLiveAXObjects;
}

AXObject::~AXObject() {
  ASSERT(isDetached());
  --s_numberOfLiveAXObjects;
}

void AXObject::detach() {
  // Clear any children and call detachFromParent on them so that
  // no children are left with dangling pointers to their parent.
  clearChildren();

  m_axObjectCache = nullptr;
}

bool AXObject::isDetached() const {
  return !m_axObjectCache;
}

const AtomicString& AXObject::getAOMPropertyOrARIAAttribute(
    AOMStringProperty property) const {
  Node* node = this->getNode();
  if (!node || !node->isElementNode())
    return nullAtom;

  return AccessibleNode::getProperty(toElement(node), property);
}

bool AXObject::isARIATextControl() const {
  return ariaRoleAttribute() == TextFieldRole ||
         ariaRoleAttribute() == SearchBoxRole ||
         ariaRoleAttribute() == ComboBoxRole;
}

bool AXObject::isButton() const {
  AccessibilityRole role = roleValue();

  return role == ButtonRole || role == PopUpButtonRole ||
         role == ToggleButtonRole;
}

bool AXObject::isLandmarkRelated() const {
  switch (roleValue()) {
    case ApplicationRole:
    case ArticleRole:
    case BannerRole:
    case ComplementaryRole:
    case ContentInfoRole:
    case FooterRole:
    case FormRole:
    case MainRole:
    case NavigationRole:
    case RegionRole:
    case SearchRole:
      return true;
    default:
      return false;
  }
}

bool AXObject::isMenuRelated() const {
  switch (roleValue()) {
    case MenuRole:
    case MenuBarRole:
    case MenuButtonRole:
    case MenuItemRole:
    case MenuItemCheckBoxRole:
    case MenuItemRadioRole:
      return true;
    default:
      return false;
  }
}

bool AXObject::isPasswordFieldAndShouldHideValue() const {
  Settings* settings = getDocument()->settings();
  if (!settings || settings->getAccessibilityPasswordValuesEnabled())
    return false;

  return isPasswordField();
}

bool AXObject::isClickable() const {
  switch (roleValue()) {
    case ButtonRole:
    case CheckBoxRole:
    case ColorWellRole:
    case ComboBoxRole:
    case ImageMapLinkRole:
    case LinkRole:
    case ListBoxOptionRole:
    case MenuButtonRole:
    case PopUpButtonRole:
    case RadioButtonRole:
    case SpinButtonRole:
    case TabRole:
    case TextFieldRole:
    case ToggleButtonRole:
      return true;
    default:
      return false;
  }
}

bool AXObject::accessibilityIsIgnored() const {
  updateCachedAttributeValuesIfNeeded();
  return m_cachedIsIgnored;
}

void AXObject::updateCachedAttributeValuesIfNeeded() const {
  if (isDetached())
    return;

  AXObjectCacheImpl& cache = axObjectCache();

  if (cache.modificationCount() == m_lastModificationCount)
    return;

  m_lastModificationCount = cache.modificationCount();
  m_cachedBackgroundColor = computeBackgroundColor();
  m_cachedIsInertOrAriaHidden = computeIsInertOrAriaHidden();
  m_cachedIsDescendantOfLeafNode = (leafNodeAncestor() != 0);
  m_cachedIsDescendantOfDisabledNode = (disabledAncestor() != 0);
  m_cachedHasInheritedPresentationalRole =
      (inheritsPresentationalRoleFrom() != 0);
  m_cachedIsPresentationalChild =
      (ancestorForWhichThisIsAPresentationalChild() != 0);
  m_cachedIsIgnored = computeAccessibilityIsIgnored();
  m_cachedLiveRegionRoot =
      isLiveRegion()
          ? const_cast<AXObject*>(this)
          : (parentObjectIfExists() ? parentObjectIfExists()->liveRegionRoot()
                                    : 0);
  m_cachedAncestorExposesActiveDescendant =
      computeAncestorExposesActiveDescendant();
}

bool AXObject::accessibilityIsIgnoredByDefault(
    IgnoredReasons* ignoredReasons) const {
  return defaultObjectInclusion(ignoredReasons) == IgnoreObject;
}

AXObjectInclusion AXObject::accessibilityPlatformIncludesObject() const {
  if (isMenuListPopup() || isMenuListOption())
    return IncludeObject;

  return DefaultBehavior;
}

AXObjectInclusion AXObject::defaultObjectInclusion(
    IgnoredReasons* ignoredReasons) const {
  if (isInertOrAriaHidden()) {
    if (ignoredReasons)
      computeIsInertOrAriaHidden(ignoredReasons);
    return IgnoreObject;
  }

  if (isPresentationalChild()) {
    if (ignoredReasons) {
      AXObject* ancestor = ancestorForWhichThisIsAPresentationalChild();
      ignoredReasons->push_back(
          IgnoredReason(AXAncestorDisallowsChild, ancestor));
    }
    return IgnoreObject;
  }

  return accessibilityPlatformIncludesObject();
}

bool AXObject::isInertOrAriaHidden() const {
  updateCachedAttributeValuesIfNeeded();
  return m_cachedIsInertOrAriaHidden;
}

bool AXObject::computeIsInertOrAriaHidden(
    IgnoredReasons* ignoredReasons) const {
  if (getNode()) {
    if (getNode()->isInert()) {
      if (ignoredReasons) {
        HTMLDialogElement* dialog = getActiveDialogElement(getNode());
        if (dialog) {
          AXObject* dialogObject = axObjectCache().getOrCreate(dialog);
          if (dialogObject)
            ignoredReasons->push_back(
                IgnoredReason(AXActiveModalDialog, dialogObject));
          else
            ignoredReasons->push_back(IgnoredReason(AXInert));
        } else {
          // TODO(aboxhall): handle inert attribute if it eventuates
          ignoredReasons->push_back(IgnoredReason(AXInert));
        }
      }
      return true;
    }
  } else {
    AXObject* parent = parentObject();
    if (parent && parent->isInertOrAriaHidden()) {
      if (ignoredReasons)
        parent->computeIsInertOrAriaHidden(ignoredReasons);
      return true;
    }
  }

  const AXObject* hiddenRoot = ariaHiddenRoot();
  if (hiddenRoot) {
    if (ignoredReasons) {
      if (hiddenRoot == this)
        ignoredReasons->push_back(IgnoredReason(AXAriaHidden));
      else
        ignoredReasons->push_back(IgnoredReason(AXAriaHiddenRoot, hiddenRoot));
    }
    return true;
  }

  return false;
}

bool AXObject::isDescendantOfLeafNode() const {
  updateCachedAttributeValuesIfNeeded();
  return m_cachedIsDescendantOfLeafNode;
}

AXObject* AXObject::leafNodeAncestor() const {
  if (AXObject* parent = parentObject()) {
    if (!parent->canHaveChildren())
      return parent;

    return parent->leafNodeAncestor();
  }

  return 0;
}

const AXObject* AXObject::ariaHiddenRoot() const {
  for (const AXObject* object = this; object; object = object->parentObject()) {
    if (equalIgnoringCase(object->getAttribute(aria_hiddenAttr), "true"))
      return object;
  }

  return 0;
}

bool AXObject::isDescendantOfDisabledNode() const {
  updateCachedAttributeValuesIfNeeded();
  return m_cachedIsDescendantOfDisabledNode;
}

const AXObject* AXObject::disabledAncestor() const {
  const AtomicString& disabled = getAttribute(aria_disabledAttr);
  if (equalIgnoringCase(disabled, "true"))
    return this;
  if (equalIgnoringCase(disabled, "false"))
    return 0;

  if (AXObject* parent = parentObject())
    return parent->disabledAncestor();

  return 0;
}

bool AXObject::lastKnownIsIgnoredValue() {
  if (m_lastKnownIsIgnoredValue == DefaultBehavior)
    m_lastKnownIsIgnoredValue =
        accessibilityIsIgnored() ? IgnoreObject : IncludeObject;

  return m_lastKnownIsIgnoredValue == IgnoreObject;
}

void AXObject::setLastKnownIsIgnoredValue(bool isIgnored) {
  m_lastKnownIsIgnoredValue = isIgnored ? IgnoreObject : IncludeObject;
}

bool AXObject::hasInheritedPresentationalRole() const {
  updateCachedAttributeValuesIfNeeded();
  return m_cachedHasInheritedPresentationalRole;
}

bool AXObject::isPresentationalChild() const {
  updateCachedAttributeValuesIfNeeded();
  return m_cachedIsPresentationalChild;
}

bool AXObject::ancestorExposesActiveDescendant() const {
  updateCachedAttributeValuesIfNeeded();
  return m_cachedAncestorExposesActiveDescendant;
}

bool AXObject::computeAncestorExposesActiveDescendant() const {
  const AXObject* parent = parentObjectUnignored();
  if (!parent)
    return false;

  if (parent->supportsActiveDescendant() &&
      !parent->getAttribute(aria_activedescendantAttr).isEmpty()) {
    return true;
  }

  return parent->ancestorExposesActiveDescendant();
}

// Simplify whitespace, but preserve a single leading and trailing whitespace
// character if it's present.
// static
String AXObject::collapseWhitespace(const String& str) {
  StringBuilder result;
  if (!str.isEmpty() && isHTMLSpace<UChar>(str[0]))
    result.append(' ');
  result.append(str.simplifyWhiteSpace(isHTMLSpace<UChar>));
  if (!str.isEmpty() && isHTMLSpace<UChar>(str[str.length() - 1]))
    result.append(' ');
  return result.toString();
}

String AXObject::computedName() const {
  AXNameFrom nameFrom;
  AXObject::AXObjectVector nameObjects;
  return name(nameFrom, &nameObjects);
}

String AXObject::name(AXNameFrom& nameFrom,
                      AXObject::AXObjectVector* nameObjects) const {
  HeapHashSet<Member<const AXObject>> visited;
  AXRelatedObjectVector relatedObjects;
  String text = textAlternative(false, false, visited, nameFrom,
                                &relatedObjects, nullptr);

  AccessibilityRole role = roleValue();
  if (!getNode() || (!isHTMLBRElement(getNode()) && role != StaticTextRole &&
                     role != InlineTextBoxRole))
    text = collapseWhitespace(text);

  if (nameObjects) {
    nameObjects->clear();
    for (size_t i = 0; i < relatedObjects.size(); i++)
      nameObjects->push_back(relatedObjects[i]->object);
  }

  return text;
}

String AXObject::name(NameSources* nameSources) const {
  AXObjectSet visited;
  AXNameFrom tmpNameFrom;
  AXRelatedObjectVector tmpRelatedObjects;
  String text = textAlternative(false, false, visited, tmpNameFrom,
                                &tmpRelatedObjects, nameSources);
  text = text.simplifyWhiteSpace(isHTMLSpace<UChar>);
  return text;
}

String AXObject::recursiveTextAlternative(const AXObject& axObj,
                                          bool inAriaLabelledByTraversal,
                                          AXObjectSet& visited) {
  if (visited.contains(&axObj) && !inAriaLabelledByTraversal)
    return String();

  AXNameFrom tmpNameFrom;
  return axObj.textAlternative(true, inAriaLabelledByTraversal, visited,
                               tmpNameFrom, nullptr, nullptr);
}

bool AXObject::isHiddenForTextAlternativeCalculation() const {
  if (equalIgnoringCase(getAttribute(aria_hiddenAttr), "false"))
    return false;

  if (getLayoutObject())
    return getLayoutObject()->style()->visibility() != EVisibility::kVisible;

  // This is an obscure corner case: if a node has no LayoutObject, that means
  // it's not rendered, but we still may be exploring it as part of a text
  // alternative calculation, for example if it was explicitly referenced by
  // aria-labelledby. So we need to explicitly call the style resolver to check
  // whether it's invisible or display:none, rather than relying on the style
  // cached in the LayoutObject.
  Document* document = getDocument();
  if (!document || !document->frame())
    return false;
  if (Node* node = getNode()) {
    if (node->isConnected() && node->isElementNode()) {
      RefPtr<ComputedStyle> style =
          document->ensureStyleResolver().styleForElement(toElement(node));
      return style->display() == EDisplay::kNone ||
             style->visibility() != EVisibility::kVisible;
    }
  }
  return false;
}

String AXObject::ariaTextAlternative(bool recursive,
                                     bool inAriaLabelledByTraversal,
                                     AXObjectSet& visited,
                                     AXNameFrom& nameFrom,
                                     AXRelatedObjectVector* relatedObjects,
                                     NameSources* nameSources,
                                     bool* foundTextAlternative) const {
  String textAlternative;
  bool alreadyVisited = visited.contains(this);
  visited.insert(this);

  // Step 2A from: http://www.w3.org/TR/accname-aam-1.1
  // If you change this logic, update AXNodeObject::nameFromLabelElement, too.
  if (!inAriaLabelledByTraversal && isHiddenForTextAlternativeCalculation()) {
    *foundTextAlternative = true;
    return String();
  }

  // Step 2B from: http://www.w3.org/TR/accname-aam-1.1
  // If you change this logic, update AXNodeObject::nameFromLabelElement, too.
  if (!inAriaLabelledByTraversal && !alreadyVisited) {
    const QualifiedName& attr =
        hasAttribute(aria_labeledbyAttr) && !hasAttribute(aria_labelledbyAttr)
            ? aria_labeledbyAttr
            : aria_labelledbyAttr;
    nameFrom = AXNameFromRelatedElement;
    if (nameSources) {
      nameSources->push_back(NameSource(*foundTextAlternative, attr));
      nameSources->back().type = nameFrom;
    }

    const AtomicString& ariaLabelledby = getAttribute(attr);
    if (!ariaLabelledby.isNull()) {
      if (nameSources)
        nameSources->back().attributeValue = ariaLabelledby;

      // Operate on a copy of |visited| so that if |nameSources| is not null,
      // the set of visited objects is preserved unmodified for future
      // calculations.
      AXObjectSet visitedCopy = visited;
      textAlternative = textFromAriaLabelledby(visitedCopy, relatedObjects);
      if (!textAlternative.isNull()) {
        if (nameSources) {
          NameSource& source = nameSources->back();
          source.type = nameFrom;
          source.relatedObjects = *relatedObjects;
          source.text = textAlternative;
          *foundTextAlternative = true;
        } else {
          *foundTextAlternative = true;
          return textAlternative;
        }
      } else if (nameSources) {
        nameSources->back().invalid = true;
      }
    }
  }

  // Step 2C from: http://www.w3.org/TR/accname-aam-1.1
  // If you change this logic, update AXNodeObject::nameFromLabelElement, too.
  nameFrom = AXNameFromAttribute;
  if (nameSources) {
    nameSources->push_back(NameSource(*foundTextAlternative, aria_labelAttr));
    nameSources->back().type = nameFrom;
  }
  const AtomicString& ariaLabel =
      getAOMPropertyOrARIAAttribute(AOMStringProperty::kLabel);
  if (!ariaLabel.isEmpty()) {
    textAlternative = ariaLabel;

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

  return textAlternative;
}

String AXObject::textFromElements(bool inAriaLabelledbyTraversal,
                                  AXObjectSet& visited,
                                  HeapVector<Member<Element>>& elements,
                                  AXRelatedObjectVector* relatedObjects) const {
  StringBuilder accumulatedText;
  bool foundValidElement = false;
  AXRelatedObjectVector localRelatedObjects;

  for (const auto& element : elements) {
    AXObject* axElement = axObjectCache().getOrCreate(element);
    if (axElement) {
      foundValidElement = true;

      String result = recursiveTextAlternative(
          *axElement, inAriaLabelledbyTraversal, visited);
      localRelatedObjects.push_back(
          new NameSourceRelatedObject(axElement, result));
      if (!result.isEmpty()) {
        if (!accumulatedText.isEmpty())
          accumulatedText.append(' ');
        accumulatedText.append(result);
      }
    }
  }
  if (!foundValidElement)
    return String();
  if (relatedObjects)
    *relatedObjects = localRelatedObjects;
  return accumulatedText.toString();
}

void AXObject::tokenVectorFromAttribute(Vector<String>& tokens,
                                        const QualifiedName& attribute) const {
  Node* node = this->getNode();
  if (!node || !node->isElementNode())
    return;

  String attributeValue = getAttribute(attribute).getString();
  if (attributeValue.isEmpty())
    return;

  attributeValue.simplifyWhiteSpace();
  attributeValue.split(' ', tokens);
}

void AXObject::elementsFromAttribute(HeapVector<Member<Element>>& elements,
                                     const QualifiedName& attribute) const {
  Vector<String> ids;
  tokenVectorFromAttribute(ids, attribute);
  if (ids.isEmpty())
    return;

  TreeScope& scope = getNode()->treeScope();
  for (const auto& id : ids) {
    if (Element* idElement = scope.getElementById(AtomicString(id)))
      elements.push_back(idElement);
  }
}

void AXObject::ariaLabelledbyElementVector(
    HeapVector<Member<Element>>& elements) const {
  // Try both spellings, but prefer aria-labelledby, which is the official spec.
  elementsFromAttribute(elements, aria_labelledbyAttr);
  if (!elements.size())
    elementsFromAttribute(elements, aria_labeledbyAttr);
}

String AXObject::textFromAriaLabelledby(
    AXObjectSet& visited,
    AXRelatedObjectVector* relatedObjects) const {
  HeapVector<Member<Element>> elements;
  ariaLabelledbyElementVector(elements);
  return textFromElements(true, visited, elements, relatedObjects);
}

String AXObject::textFromAriaDescribedby(
    AXRelatedObjectVector* relatedObjects) const {
  AXObjectSet visited;
  HeapVector<Member<Element>> elements;
  elementsFromAttribute(elements, aria_describedbyAttr);
  return textFromElements(true, visited, elements, relatedObjects);
}

RGBA32 AXObject::backgroundColor() const {
  updateCachedAttributeValuesIfNeeded();
  return m_cachedBackgroundColor;
}

AccessibilityOrientation AXObject::orientation() const {
  // In ARIA 1.1, the default value for aria-orientation changed from
  // horizontal to undefined.
  return AccessibilityOrientationUndefined;
}

AXSupportedAction AXObject::action() const {
  if (!actionElement())
    return AXSupportedAction::None;

  switch (roleValue()) {
    case ButtonRole:
    case ToggleButtonRole:
      return AXSupportedAction::Press;
    case TextFieldRole:
      return AXSupportedAction::Activate;
    case RadioButtonRole:
      return AXSupportedAction::Select;
    case CheckBoxRole:
    case SwitchRole:
      return isChecked() ? AXSupportedAction::Check
                         : AXSupportedAction::Uncheck;
    case LinkRole:
      return AXSupportedAction::Jump;
    case PopUpButtonRole:
      return AXSupportedAction::Open;
    default:
      return AXSupportedAction::Click;
  }
}

AccessibilityButtonState AXObject::checkboxOrRadioValue() const {
  const AtomicString& checkedAttribute = getAttribute(aria_checkedAttr);
  if (equalIgnoringCase(checkedAttribute, "true"))
    return ButtonStateOn;

  if (equalIgnoringCase(checkedAttribute, "mixed")) {
    // Only checkboxes should support the mixed state.
    AccessibilityRole role = ariaRoleAttribute();
    if (role == CheckBoxRole || role == MenuItemCheckBoxRole)
      return ButtonStateMixed;
  }

  return ButtonStateOff;
}

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

  if (isHTMLTextAreaElement(*node))
    return true;

  if (hasEditableStyle(*node))
    return true;

  if (!isNativeTextControl() && !isNonNativeTextControl())
    return false;

  return equalIgnoringCase(getAttribute(aria_multilineAttr), "true");
}

bool AXObject::ariaPressedIsPresent() const {
  return !getAttribute(aria_pressedAttr).isEmpty();
}

bool AXObject::supportsActiveDescendant() const {
  // According to the ARIA Spec, all ARIA composite widgets, ARIA text boxes
  // and ARIA groups should be able to expose an active descendant.
  // Implicitly, <input> and <textarea> elements should also have this ability.
  switch (ariaRoleAttribute()) {
    case ComboBoxRole:
    case GridRole:
    case GroupRole:
    case ListBoxRole:
    case MenuRole:
    case MenuBarRole:
    case RadioGroupRole:
    case RowRole:
    case SearchBoxRole:
    case TabListRole:
    case TextFieldRole:
    case ToolbarRole:
    case TreeRole:
    case TreeGridRole:
      return true;
    default:
      return false;
  }
}

bool AXObject::supportsARIAAttributes() const {
  return isLiveRegion() || supportsARIADragging() || supportsARIADropping() ||
         supportsARIAFlowTo() || supportsARIAOwns() ||
         hasAttribute(aria_labelAttr);
}

bool AXObject::supportsRangeValue() const {
  return isProgressIndicator() || isMeter() || isSlider() || isScrollbar() ||
         isSpinButton();
}

bool AXObject::supportsSetSizeAndPosInSet() const {
  AXObject* parent = parentObject();
  if (!parent)
    return false;

  int role = roleValue();
  int parentRole = parent->roleValue();

  if ((role == ListBoxOptionRole && parentRole == ListBoxRole) ||
      (role == ListItemRole && parentRole == ListRole) ||
      (role == MenuItemRole && parentRole == MenuRole) ||
      (role == RadioButtonRole) ||
      (role == TabRole && parentRole == TabListRole) ||
      (role == TreeItemRole && parentRole == TreeRole) ||
      (role == TreeItemRole && parentRole == GroupRole)) {
    return true;
  }

  return false;
}

int AXObject::indexInParent() const {
  if (!parentObject())
    return 0;

  const auto& siblings = parentObject()->children();
  int childCount = siblings.size();

  for (int index = 0; index < childCount; ++index) {
    if (siblings[index].get() == this) {
      return index;
    }
  }
  return 0;
}

bool AXObject::isLiveRegion() const {
  const AtomicString& liveRegion = liveRegionStatus();
  return equalIgnoringCase(liveRegion, "polite") ||
         equalIgnoringCase(liveRegion, "assertive");
}

AXObject* AXObject::liveRegionRoot() const {
  updateCachedAttributeValuesIfNeeded();
  return m_cachedLiveRegionRoot;
}

const AtomicString& AXObject::containerLiveRegionStatus() const {
  updateCachedAttributeValuesIfNeeded();
  return m_cachedLiveRegionRoot ? m_cachedLiveRegionRoot->liveRegionStatus()
                                : nullAtom;
}

const AtomicString& AXObject::containerLiveRegionRelevant() const {
  updateCachedAttributeValuesIfNeeded();
  return m_cachedLiveRegionRoot ? m_cachedLiveRegionRoot->liveRegionRelevant()
                                : nullAtom;
}

bool AXObject::containerLiveRegionAtomic() const {
  updateCachedAttributeValuesIfNeeded();
  return m_cachedLiveRegionRoot && m_cachedLiveRegionRoot->liveRegionAtomic();
}

bool AXObject::containerLiveRegionBusy() const {
  updateCachedAttributeValuesIfNeeded();
  return m_cachedLiveRegionRoot && m_cachedLiveRegionRoot->liveRegionBusy();
}

AXObject* AXObject::elementAccessibilityHitTest(const IntPoint& point) const {
  // Check if there are any mock elements that need to be handled.
  for (const auto& child : m_children) {
    if (child->isMockObject() &&
        child->getBoundsInFrameCoordinates().contains(point))
      return child->elementAccessibilityHitTest(point);
  }

  return const_cast<AXObject*>(this);
}

const AXObject::AXObjectVector& AXObject::children() {
  updateChildrenIfNecessary();

  return m_children;
}

AXObject* AXObject::parentObject() const {
  if (isDetached())
    return 0;

  if (m_parent)
    return m_parent;

  if (axObjectCache().isAriaOwned(this))
    return axObjectCache().getAriaOwnedParent(this);

  return computeParent();
}

AXObject* AXObject::parentObjectIfExists() const {
  if (isDetached())
    return 0;

  if (m_parent)
    return m_parent;

  return computeParentIfExists();
}

AXObject* AXObject::parentObjectUnignored() const {
  AXObject* parent;
  for (parent = parentObject(); parent && parent->accessibilityIsIgnored();
       parent = parent->parentObject()) {
  }

  return parent;
}

void AXObject::updateChildrenIfNecessary() {
  if (!hasChildren())
    addChildren();
}

void AXObject::clearChildren() {
  // Detach all weak pointers from objects to their parents.
  for (const auto& child : m_children)
    child->detachFromParent();

  m_children.clear();
  m_haveChildren = false;
}

Document* AXObject::getDocument() const {
  FrameView* frameView = documentFrameView();
  if (!frameView)
    return 0;

  return frameView->frame().document();
}

FrameView* AXObject::documentFrameView() const {
  const AXObject* object = this;
  while (object && !object->isAXLayoutObject())
    object = object->parentObject();

  if (!object)
    return 0;

  return object->documentFrameView();
}

String AXObject::language() const {
  const AtomicString& lang = getAttribute(langAttr);
  if (!lang.isEmpty())
    return lang;

  AXObject* parent = parentObject();

  // As a last resort, fall back to the content language specified in the meta
  // tag.
  if (!parent) {
    Document* doc = getDocument();
    if (doc)
      return doc->contentLanguage();
    return nullAtom;
  }

  return parent->language();
}

bool AXObject::hasAttribute(const QualifiedName& attribute) const {
  Node* elementNode = getNode();
  if (!elementNode)
    return false;

  if (!elementNode->isElementNode())
    return false;

  Element* element = toElement(elementNode);
  return element->fastHasAttribute(attribute);
}

const AtomicString& AXObject::getAttribute(
    const QualifiedName& attribute) const {
  Node* elementNode = getNode();
  if (!elementNode)
    return nullAtom;

  if (!elementNode->isElementNode())
    return nullAtom;

  Element* element = toElement(elementNode);
  return element->fastGetAttribute(attribute);
}

//
// Scrollable containers.
//

bool AXObject::isScrollableContainer() const {
  return !!getScrollableAreaIfScrollable();
}

IntPoint AXObject::getScrollOffset() const {
  ScrollableArea* area = getScrollableAreaIfScrollable();
  if (!area)
    return IntPoint();

  return IntPoint(area->scrollOffsetInt().width(),
                  area->scrollOffsetInt().height());
}

IntPoint AXObject::minimumScrollOffset() const {
  ScrollableArea* area = getScrollableAreaIfScrollable();
  if (!area)
    return IntPoint();

  return IntPoint(area->minimumScrollOffsetInt().width(),
                  area->minimumScrollOffsetInt().height());
}

IntPoint AXObject::maximumScrollOffset() const {
  ScrollableArea* area = getScrollableAreaIfScrollable();
  if (!area)
    return IntPoint();

  return IntPoint(area->maximumScrollOffsetInt().width(),
                  area->maximumScrollOffsetInt().height());
}

void AXObject::setScrollOffset(const IntPoint& offset) const {
  ScrollableArea* area = getScrollableAreaIfScrollable();
  if (!area)
    return;

  // TODO(bokan): This should potentially be a UserScroll.
  area->setScrollOffset(ScrollOffset(offset.x(), offset.y()),
                        ProgrammaticScroll);
}

void AXObject::getRelativeBounds(AXObject** outContainer,
                                 FloatRect& outBoundsInContainer,
                                 SkMatrix44& outContainerTransform) const {
  *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;
    }
  }

  LayoutObject* layoutObject = layoutObjectForRelativeBounds();
  if (!layoutObject)
    return;

  if (isWebArea()) {
    if (layoutObject->frame()->view())
      outBoundsInContainer.setSize(
          FloatSize(layoutObject->frame()->view()->contentsSize()));
    return;
  }

  // First compute the container. The container must be an ancestor in the
  // accessibility tree, and its LayoutObject must be an ancestor in the layout
  // tree. Get the first such ancestor that's either scrollable or has a paint
  // layer.
  AXObject* container = parentObjectUnignored();
  LayoutObject* containerLayoutObject = nullptr;
  while (container) {
    containerLayoutObject = container->getLayoutObject();
    if (containerLayoutObject && containerLayoutObject->isBoxModelObject() &&
        layoutObject->isDescendantOf(containerLayoutObject)) {
      if (container->isScrollableContainer() ||
          containerLayoutObject->hasLayer())
        break;
    }

    container = container->parentObjectUnignored();
  }

  if (!container)
    return;
  *outContainer = container;
  outBoundsInContainer = layoutObject->localBoundingBoxRectForAccessibility();

  // If the container has a scroll offset, subtract that out because we want our
  // bounds to be relative to the *unscrolled* position of the container object.
  ScrollableArea* scrollableArea = container->getScrollableAreaIfScrollable();
  if (scrollableArea && !container->isWebArea()) {
    ScrollOffset scrollOffset = scrollableArea->getScrollOffset();
    outBoundsInContainer.move(scrollOffset);
  }

  // Compute the transform between the container's coordinate space and this
  // object.  If the transform is just a simple translation, apply that to the
  // bounding box, but if it's a non-trivial transformation like a rotation,
  // scaling, etc. then return the full matrix instead.
  TransformationMatrix transform = layoutObject->localToAncestorTransform(
      toLayoutBoxModelObject(containerLayoutObject));
  if (transform.isIdentityOr2DTranslation()) {
    outBoundsInContainer.move(transform.to2DTranslation());
  } else {
    outContainerTransform = TransformationMatrix::toSkMatrix44(transform);
  }
}

LayoutRect AXObject::getBoundsInFrameCoordinates() const {
  AXObject* container = nullptr;
  FloatRect bounds;
  SkMatrix44 transform;
  getRelativeBounds(&container, bounds, transform);
  FloatRect computedBounds(0, 0, bounds.width(), bounds.height());
  while (container && container != this) {
    computedBounds.move(bounds.x(), bounds.y());
    if (!container->isWebArea()) {
      computedBounds.move(-container->getScrollOffset().x(),
                          -container->getScrollOffset().y());
    }
    if (!transform.isIdentity()) {
      TransformationMatrix transformationMatrix(transform);
      transformationMatrix.mapRect(computedBounds);
    }
    container->getRelativeBounds(&container, bounds, transform);
  }
  return LayoutRect(computedBounds);
}

//
// Modify or take an action on an object.
//

bool AXObject::press() {
  Document* document = getDocument();
  if (!document)
    return false;

  UserGestureIndicator gestureIndicator(
      DocumentUserGestureToken::create(document, UserGestureToken::NewGesture));
  Element* actionElem = actionElement();
  if (actionElem) {
    actionElem->accessKeyAction(true);
    return true;
  }

  if (canSetFocusAttribute()) {
    setFocused(true);
    return true;
  }

  return false;
}

void AXObject::scrollToMakeVisible() const {
  IntRect objectRect = pixelSnappedIntRect(getBoundsInFrameCoordinates());
  objectRect.setLocation(IntPoint());
  scrollToMakeVisibleWithSubFocus(objectRect);
}

// This is a 1-dimensional scroll offset helper function that's applied
// separately in the horizontal and vertical directions, because the
// logic is the same. The goal is to compute the best scroll offset
// in order to make an object visible within a viewport.
//
// If the object is already fully visible, returns the same scroll
// offset.
//
// In case the whole object cannot fit, you can specify a
// subfocus - a smaller region within the object that should
// be prioritized. If the whole object can fit, the subfocus is
// ignored.
//
// If possible, the object and subfocus are centered within the
// viewport.
//
// Example 1: the object is already visible, so nothing happens.
//   +----------Viewport---------+
//                 +---Object---+
//                 +--SubFocus--+
//
// Example 2: the object is not fully visible, so it's centered
// within the viewport.
//   Before:
//   +----------Viewport---------+
//                         +---Object---+
//                         +--SubFocus--+
//
//   After:
//                 +----------Viewport---------+
//                         +---Object---+
//                         +--SubFocus--+
//
// Example 3: the object is larger than the viewport, so the
// viewport moves to show as much of the object as possible,
// while also trying to center the subfocus.
//   Before:
//   +----------Viewport---------+
//     +---------------Object--------------+
//                         +-SubFocus-+
//
//   After:
//             +----------Viewport---------+
//     +---------------Object--------------+
//                         +-SubFocus-+
//
// When constraints cannot be fully satisfied, the min
// (left/top) position takes precedence over the max (right/bottom).
//
// Note that the return value represents the ideal new scroll offset.
// This may be out of range - the calling function should clip this
// to the available range.
static int computeBestScrollOffset(int currentScrollOffset,
                                   int subfocusMin,
                                   int subfocusMax,
                                   int objectMin,
                                   int objectMax,
                                   int viewportMin,
                                   int viewportMax) {
  int viewportSize = viewportMax - viewportMin;

  // If the object size is larger than the viewport size, consider
  // only a portion that's as large as the viewport, centering on
  // the subfocus as much as possible.
  if (objectMax - objectMin > viewportSize) {
    // Since it's impossible to fit the whole object in the
    // viewport, exit now if the subfocus is already within the viewport.
    if (subfocusMin - currentScrollOffset >= viewportMin &&
        subfocusMax - currentScrollOffset <= viewportMax)
      return currentScrollOffset;

    // Subfocus must be within focus.
    subfocusMin = std::max(subfocusMin, objectMin);
    subfocusMax = std::min(subfocusMax, objectMax);

    // Subfocus must be no larger than the viewport size; favor top/left.
    if (subfocusMax - subfocusMin > viewportSize)
      subfocusMax = subfocusMin + viewportSize;

    // Compute the size of an object centered on the subfocus, the size of the
    // viewport.
    int centeredObjectMin = (subfocusMin + subfocusMax - viewportSize) / 2;
    int centeredObjectMax = centeredObjectMin + viewportSize;

    objectMin = std::max(objectMin, centeredObjectMin);
    objectMax = std::min(objectMax, centeredObjectMax);
  }

  // Exit now if the focus is already within the viewport.
  if (objectMin - currentScrollOffset >= viewportMin &&
      objectMax - currentScrollOffset <= viewportMax)
    return currentScrollOffset;

  // Center the object in the viewport.
  return (objectMin + objectMax - viewportMin - viewportMax) / 2;
}

void AXObject::scrollToMakeVisibleWithSubFocus(const IntRect& subfocus) const {
  // Search up the parent chain until we find the first one that's scrollable.
  const AXObject* scrollParent = parentObject() ? parentObject() : this;
  ScrollableArea* scrollableArea = 0;
  while (scrollParent) {
    scrollableArea = scrollParent->getScrollableAreaIfScrollable();
    if (scrollableArea)
      break;
    scrollParent = scrollParent->parentObject();
  }
  if (!scrollParent || !scrollableArea)
    return;

  IntRect objectRect = pixelSnappedIntRect(getBoundsInFrameCoordinates());
  IntSize scrollOffset = scrollableArea->scrollOffsetInt();
  IntRect scrollVisibleRect = scrollableArea->visibleContentRect();

  // Convert the object rect into local coordinates.
  if (!scrollParent->isWebArea()) {
    objectRect.moveBy(IntPoint(scrollOffset));
    objectRect.moveBy(
        -pixelSnappedIntRect(scrollParent->getBoundsInFrameCoordinates())
             .location());
  }

  int desiredX = computeBestScrollOffset(
      scrollOffset.width(), objectRect.x() + subfocus.x(),
      objectRect.x() + subfocus.maxX(), objectRect.x(), objectRect.maxX(), 0,
      scrollVisibleRect.width());
  int desiredY = computeBestScrollOffset(
      scrollOffset.height(), objectRect.y() + subfocus.y(),
      objectRect.y() + subfocus.maxY(), objectRect.y(), objectRect.maxY(), 0,
      scrollVisibleRect.height());

  scrollParent->setScrollOffset(IntPoint(desiredX, desiredY));

  // Convert the subfocus into the coordinates of the scroll parent.
  IntRect newSubfocus = subfocus;
  IntRect newElementRect = pixelSnappedIntRect(getBoundsInFrameCoordinates());
  IntRect scrollParentRect =
      pixelSnappedIntRect(scrollParent->getBoundsInFrameCoordinates());
  newSubfocus.move(newElementRect.x(), newElementRect.y());
  newSubfocus.move(-scrollParentRect.x(), -scrollParentRect.y());

  if (scrollParent->parentObject()) {
    // Recursively make sure the scroll parent itself is visible.
    scrollParent->scrollToMakeVisibleWithSubFocus(newSubfocus);
  } else {
    // To minimize the number of notifications, only fire one on the topmost
    // object that has been scrolled.
    axObjectCache().postNotification(const_cast<AXObject*>(this),
                                     AXObjectCacheImpl::AXLocationChanged);
  }
}

void AXObject::scrollToGlobalPoint(const IntPoint& globalPoint) const {
  // Search up the parent chain and create a vector of all scrollable parent
  // objects and ending with this object itself.
  HeapVector<Member<const AXObject>> objects;
  AXObject* parentObject;
  for (parentObject = this->parentObject(); parentObject;
       parentObject = parentObject->parentObject()) {
    if (parentObject->getScrollableAreaIfScrollable())
      objects.push_front(parentObject);
  }
  objects.push_back(this);

  // Start with the outermost scrollable (the main window) and try to scroll the
  // next innermost object to the given point.
  int offsetX = 0, offsetY = 0;
  IntPoint point = globalPoint;
  size_t levels = objects.size() - 1;
  for (size_t i = 0; i < levels; i++) {
    const AXObject* outer = objects[i];
    const AXObject* inner = objects[i + 1];
    ScrollableArea* scrollableArea = outer->getScrollableAreaIfScrollable();

    IntRect innerRect =
        inner->isWebArea()
            ? pixelSnappedIntRect(
                  inner->parentObject()->getBoundsInFrameCoordinates())
            : pixelSnappedIntRect(inner->getBoundsInFrameCoordinates());
    IntRect objectRect = innerRect;
    IntSize scrollOffset = scrollableArea->scrollOffsetInt();

    // Convert the object rect into local coordinates.
    objectRect.move(offsetX, offsetY);
    if (!outer->isWebArea())
      objectRect.move(scrollOffset.width(), scrollOffset.height());

    int desiredX = computeBestScrollOffset(0, objectRect.x(), objectRect.maxX(),
                                           objectRect.x(), objectRect.maxX(),
                                           point.x(), point.x());
    int desiredY = computeBestScrollOffset(0, objectRect.y(), objectRect.maxY(),
                                           objectRect.y(), objectRect.maxY(),
                                           point.y(), point.y());
    outer->setScrollOffset(IntPoint(desiredX, desiredY));

    if (outer->isWebArea() && !inner->isWebArea()) {
      // If outer object we just scrolled is a web area (frame) but the inner
      // object is not, keep track of the coordinate transformation to apply to
      // future nested calculations.
      scrollOffset = scrollableArea->scrollOffsetInt();
      offsetX -= (scrollOffset.width() + point.x());
      offsetY -= (scrollOffset.height() + point.y());
      point.move(scrollOffset.width() - innerRect.width(),
                 scrollOffset.height() - innerRect.y());
    } else if (inner->isWebArea()) {
      // Otherwise, if the inner object is a web area, reset the coordinate
      // transformation.
      offsetX = 0;
      offsetY = 0;
    }
  }

  // To minimize the number of notifications, only fire one on the topmost
  // object that has been scrolled.
  DCHECK(objects[0]);
  // TODO(nektar): Switch to postNotification(objects[0] and remove |getNode|.
  axObjectCache().postNotification(objects[0]->getNode(),
                                   AXObjectCacheImpl::AXLocationChanged);
}

void AXObject::setSequentialFocusNavigationStartingPoint() {
  // Call it on the nearest ancestor that overrides this with a specific
  // implementation.
  if (parentObject())
    parentObject()->setSequentialFocusNavigationStartingPoint();
}

void AXObject::notifyIfIgnoredValueChanged() {
  bool isIgnored = accessibilityIsIgnored();
  if (lastKnownIsIgnoredValue() != isIgnored) {
    axObjectCache().childrenChanged(parentObject());
    setLastKnownIsIgnoredValue(isIgnored);
  }
}

void AXObject::selectionChanged() {
  if (AXObject* parent = parentObjectIfExists())
    parent->selectionChanged();
}

int AXObject::lineForPosition(const VisiblePosition& position) const {
  if (position.isNull() || !getNode())
    return -1;

  // If the position is not in the same editable region as this AX object,
  // return -1.
  Node* containerNode = position.deepEquivalent().computeContainerNode();
  if (!containerNode->isShadowIncludingInclusiveAncestorOf(getNode()) &&
      !getNode()->isShadowIncludingInclusiveAncestorOf(containerNode))
    return -1;

  int lineCount = -1;
  VisiblePosition currentPosition = position;
  VisiblePosition previousPosition;

  // Move up until we get to the top.
  // FIXME: This only takes us to the top of the rootEditableElement, not the
  // top of the top document.
  do {
    previousPosition = currentPosition;
    currentPosition =
        previousLinePosition(currentPosition, LayoutUnit(), HasEditableAXRole);
    ++lineCount;
  } while (currentPosition.isNotNull() &&
           !inSameLine(currentPosition, previousPosition));

  return lineCount;
}

bool AXObject::isARIAControl(AccessibilityRole ariaRole) {
  return isARIAInput(ariaRole) || ariaRole == ButtonRole ||
         ariaRole == ComboBoxRole || ariaRole == SliderRole;
}

bool AXObject::isARIAInput(AccessibilityRole ariaRole) {
  return ariaRole == RadioButtonRole || ariaRole == CheckBoxRole ||
         ariaRole == TextFieldRole || ariaRole == SwitchRole ||
         ariaRole == SearchBoxRole;
}

AccessibilityRole AXObject::ariaRoleToWebCoreRole(const String& value) {
  ASSERT(!value.isEmpty());

  static const ARIARoleMap* roleMap = createARIARoleMap();

  Vector<String> roleVector;
  value.split(' ', roleVector);
  AccessibilityRole role = UnknownRole;
  for (const auto& child : roleVector) {
    role = roleMap->at(child);
    if (role)
      return role;
  }

  return role;
}

bool AXObject::isInsideFocusableElementOrARIAWidget(const Node& node) {
  const Node* curNode = &node;
  do {
    if (curNode->isElementNode()) {
      const Element* element = toElement(curNode);
      if (element->isFocusable())
        return true;
      String role = element->getAttribute("role");
      if (!role.isEmpty() && AXObject::includesARIAWidgetRole(role))
        return true;
      if (hasInteractiveARIAAttribute(*element))
        return true;
    }
    curNode = curNode->parentNode();
  } while (curNode && !isHTMLBodyElement(node));
  return false;
}

bool AXObject::hasInteractiveARIAAttribute(const Element& element) {
  for (size_t i = 0; i < WTF_ARRAY_LENGTH(ariaInteractiveWidgetAttributes);
       ++i) {
    const char* attribute = ariaInteractiveWidgetAttributes[i];
    if (element.hasAttribute(attribute)) {
      return true;
    }
  }
  return false;
}

bool AXObject::includesARIAWidgetRole(const String& role) {
  static const HashSet<String, CaseFoldingHash>* roleSet =
      createARIARoleWidgetSet();

  Vector<String> roleVector;
  role.split(' ', roleVector);
  for (const auto& child : roleVector) {
    if (roleSet->contains(child))
      return true;
  }
  return false;
}

bool AXObject::nameFromContents() const {
  switch (roleValue()) {
    case AnchorRole:
    case ButtonRole:
    case CheckBoxRole:
    case DirectoryRole:
    case DisclosureTriangleRole:
    case HeadingRole:
    case LineBreakRole:
    case LinkRole:
    case ListBoxOptionRole:
    case ListItemRole:
    case MenuItemRole:
    case MenuItemCheckBoxRole:
    case MenuItemRadioRole:
    case MenuListOptionRole:
    case PopUpButtonRole:
    case RadioButtonRole:
    case StaticTextRole:
    case StatusRole:
    case SwitchRole:
    case TabRole:
    case ToggleButtonRole:
    case TreeItemRole:
      return true;
    default:
      return false;
  }
}

AccessibilityRole AXObject::buttonRoleType() const {
  // If aria-pressed is present, then it should be exposed as a toggle button.
  // http://www.w3.org/TR/wai-aria/states_and_properties#aria-pressed
  if (ariaPressedIsPresent())
    return ToggleButtonRole;
  if (ariaHasPopup())
    return PopUpButtonRole;
  // We don't contemplate RadioButtonRole, as it depends on the input
  // type.

  return ButtonRole;
}

const AtomicString& AXObject::roleName(AccessibilityRole role) {
  static const Vector<AtomicString>* roleNameVector = createRoleNameVector();

  return roleNameVector->at(role);
}

const AtomicString& AXObject::internalRoleName(AccessibilityRole role) {
  static const Vector<AtomicString>* internalRoleNameVector =
      createInternalRoleNameVector();

  return internalRoleNameVector->at(role);
}

DEFINE_TRACE(AXObject) {
  visitor->trace(m_children);
  visitor->trace(m_parent);
  visitor->trace(m_cachedLiveRegionRoot);
  visitor->trace(m_axObjectCache);
}

}  // namespace blink
