// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "modules/accessibility/InspectorAccessibilityAgent.h"

#include "core/HTMLNames.h"
#include "core/dom/AXObjectCache.h"
#include "core/dom/DOMNodeIds.h"
#include "core/dom/Element.h"
#include "core/dom/Node.h"
#include "core/dom/NodeList.h"
#include "core/dom/shadow/ElementShadow.h"
#include "core/inspector/IdentifiersFactory.h"
#include "core/inspector/InspectorDOMAgent.h"
#include "core/inspector/InspectorStyleSheet.h"
#include "core/page/Page.h"
#include "modules/accessibility/AXObject.h"
#include "modules/accessibility/AXObjectCacheImpl.h"
#include "modules/accessibility/InspectorTypeBuilderHelper.h"
#include <memory>

namespace blink {

using protocol::Accessibility::AXGlobalStates;
using protocol::Accessibility::AXLiveRegionAttributes;
using protocol::Accessibility::AXNode;
using protocol::Accessibility::AXNodeId;
using protocol::Accessibility::AXProperty;
using protocol::Accessibility::AXValueSource;
using protocol::Accessibility::AXValueType;
using protocol::Accessibility::AXRelatedNode;
using protocol::Accessibility::AXRelationshipAttributes;
using protocol::Accessibility::AXValue;
using protocol::Accessibility::AXWidgetAttributes;
using protocol::Accessibility::AXWidgetStates;

using namespace HTMLNames;

namespace {

static const AXID kIDForInspectedNodeWithNoAXNode = 0;

void fillLiveRegionProperties(AXObject& axObject,
                              protocol::Array<AXProperty>& properties) {
  if (!axObject.liveRegionRoot())
    return;

  properties.addItem(
      createProperty(AXLiveRegionAttributesEnum::Live,
                     createValue(axObject.containerLiveRegionStatus(),
                                 AXValueTypeEnum::Token)));
  properties.addItem(
      createProperty(AXLiveRegionAttributesEnum::Atomic,
                     createBooleanValue(axObject.containerLiveRegionAtomic())));
  properties.addItem(
      createProperty(AXLiveRegionAttributesEnum::Relevant,
                     createValue(axObject.containerLiveRegionRelevant(),
                                 AXValueTypeEnum::TokenList)));
  properties.addItem(
      createProperty(AXLiveRegionAttributesEnum::Busy,
                     createBooleanValue(axObject.containerLiveRegionBusy())));

  if (!axObject.isLiveRegion()) {
    properties.addItem(createProperty(
        AXLiveRegionAttributesEnum::Root,
        createRelatedNodeListValue(*(axObject.liveRegionRoot()))));
  }
}

void fillGlobalStates(AXObject& axObject,
                      protocol::Array<AXProperty>& properties) {
  if (!axObject.isEnabled())
    properties.addItem(
        createProperty(AXGlobalStatesEnum::Disabled, createBooleanValue(true)));

  if (const AXObject* hiddenRoot = axObject.ariaHiddenRoot()) {
    properties.addItem(
        createProperty(AXGlobalStatesEnum::Hidden, createBooleanValue(true)));
    properties.addItem(createProperty(AXGlobalStatesEnum::HiddenRoot,
                                      createRelatedNodeListValue(*hiddenRoot)));
  }

  InvalidState invalidState = axObject.getInvalidState();
  switch (invalidState) {
    case InvalidStateUndefined:
      break;
    case InvalidStateFalse:
      properties.addItem(
          createProperty(AXGlobalStatesEnum::Invalid,
                         createValue("false", AXValueTypeEnum::Token)));
      break;
    case InvalidStateTrue:
      properties.addItem(
          createProperty(AXGlobalStatesEnum::Invalid,
                         createValue("true", AXValueTypeEnum::Token)));
      break;
    case InvalidStateSpelling:
      properties.addItem(
          createProperty(AXGlobalStatesEnum::Invalid,
                         createValue("spelling", AXValueTypeEnum::Token)));
      break;
    case InvalidStateGrammar:
      properties.addItem(
          createProperty(AXGlobalStatesEnum::Invalid,
                         createValue("grammar", AXValueTypeEnum::Token)));
      break;
    default:
      // TODO(aboxhall): expose invalid: <nothing> and source: aria-invalid as
      // invalid value
      properties.addItem(createProperty(
          AXGlobalStatesEnum::Invalid,
          createValue(axObject.ariaInvalidValue(), AXValueTypeEnum::String)));
      break;
  }
}

bool roleAllowsMultiselectable(AccessibilityRole role) {
  return role == GridRole || role == ListBoxRole || role == TabListRole ||
         role == TreeGridRole || role == TreeRole;
}

bool roleAllowsOrientation(AccessibilityRole role) {
  return role == ScrollBarRole || role == SplitterRole || role == SliderRole;
}

bool roleAllowsReadonly(AccessibilityRole role) {
  return role == GridRole || role == CellRole || role == TextFieldRole ||
         role == ColumnHeaderRole || role == RowHeaderRole ||
         role == TreeGridRole;
}

bool roleAllowsRequired(AccessibilityRole role) {
  return role == ComboBoxRole || role == CellRole || role == ListBoxRole ||
         role == RadioGroupRole || role == SpinButtonRole ||
         role == TextFieldRole || role == TreeRole ||
         role == ColumnHeaderRole || role == RowHeaderRole ||
         role == TreeGridRole;
}

bool roleAllowsSort(AccessibilityRole role) {
  return role == ColumnHeaderRole || role == RowHeaderRole;
}

bool roleAllowsChecked(AccessibilityRole role) {
  return role == MenuItemCheckBoxRole || role == MenuItemRadioRole ||
         role == RadioButtonRole || role == CheckBoxRole ||
         role == TreeItemRole || role == ListBoxOptionRole ||
         role == SwitchRole;
}

bool roleAllowsSelected(AccessibilityRole role) {
  return role == CellRole || role == ListBoxOptionRole || role == RowRole ||
         role == TabRole || role == ColumnHeaderRole ||
         role == MenuItemRadioRole || role == RadioButtonRole ||
         role == RowHeaderRole || role == TreeItemRole;
}

void fillWidgetProperties(AXObject& axObject,
                          protocol::Array<AXProperty>& properties) {
  AccessibilityRole role = axObject.roleValue();
  String autocomplete = axObject.ariaAutoComplete();
  if (!autocomplete.isEmpty())
    properties.addItem(
        createProperty(AXWidgetAttributesEnum::Autocomplete,
                       createValue(autocomplete, AXValueTypeEnum::Token)));

  if (axObject.hasAttribute(HTMLNames::aria_haspopupAttr)) {
    bool hasPopup = axObject.ariaHasPopup();
    properties.addItem(createProperty(AXWidgetAttributesEnum::Haspopup,
                                      createBooleanValue(hasPopup)));
  }

  int headingLevel = axObject.headingLevel();
  if (headingLevel > 0) {
    properties.addItem(createProperty(AXWidgetAttributesEnum::Level,
                                      createValue(headingLevel)));
  }
  int hierarchicalLevel = axObject.hierarchicalLevel();
  if (hierarchicalLevel > 0 ||
      axObject.hasAttribute(HTMLNames::aria_levelAttr)) {
    properties.addItem(createProperty(AXWidgetAttributesEnum::Level,
                                      createValue(hierarchicalLevel)));
  }

  if (roleAllowsMultiselectable(role)) {
    bool multiselectable = axObject.isMultiSelectable();
    properties.addItem(createProperty(AXWidgetAttributesEnum::Multiselectable,
                                      createBooleanValue(multiselectable)));
  }

  if (roleAllowsOrientation(role)) {
    AccessibilityOrientation orientation = axObject.orientation();
    switch (orientation) {
      case AccessibilityOrientationVertical:
        properties.addItem(
            createProperty(AXWidgetAttributesEnum::Orientation,
                           createValue("vertical", AXValueTypeEnum::Token)));
        break;
      case AccessibilityOrientationHorizontal:
        properties.addItem(
            createProperty(AXWidgetAttributesEnum::Orientation,
                           createValue("horizontal", AXValueTypeEnum::Token)));
        break;
      case AccessibilityOrientationUndefined:
        break;
    }
  }

  if (role == TextFieldRole) {
    properties.addItem(
        createProperty(AXWidgetAttributesEnum::Multiline,
                       createBooleanValue(axObject.isMultiline())));
  }

  if (roleAllowsReadonly(role)) {
    properties.addItem(
        createProperty(AXWidgetAttributesEnum::Readonly,
                       createBooleanValue(axObject.isReadOnly())));
  }

  if (roleAllowsRequired(role)) {
    properties.addItem(
        createProperty(AXWidgetAttributesEnum::Required,
                       createBooleanValue(axObject.isRequired())));
  }

  if (roleAllowsSort(role)) {
    // TODO(aboxhall): sort
  }

  if (axObject.isRange()) {
    properties.addItem(
        createProperty(AXWidgetAttributesEnum::Valuemin,
                       createValue(axObject.minValueForRange())));
    properties.addItem(
        createProperty(AXWidgetAttributesEnum::Valuemax,
                       createValue(axObject.maxValueForRange())));
    properties.addItem(
        createProperty(AXWidgetAttributesEnum::Valuetext,
                       createValue(axObject.valueDescription())));
  }
}

void fillWidgetStates(AXObject& axObject,
                      protocol::Array<AXProperty>& properties) {
  AccessibilityRole role = axObject.roleValue();
  if (roleAllowsChecked(role)) {
    AccessibilityButtonState checked = axObject.checkboxOrRadioValue();
    switch (checked) {
      case ButtonStateOff:
        properties.addItem(
            createProperty(AXWidgetStatesEnum::Checked,
                           createValue("false", AXValueTypeEnum::Tristate)));
        break;
      case ButtonStateOn:
        properties.addItem(
            createProperty(AXWidgetStatesEnum::Checked,
                           createValue("true", AXValueTypeEnum::Tristate)));
        break;
      case ButtonStateMixed:
        properties.addItem(
            createProperty(AXWidgetStatesEnum::Checked,
                           createValue("mixed", AXValueTypeEnum::Tristate)));
        break;
    }
  }

  AccessibilityExpanded expanded = axObject.isExpanded();
  switch (expanded) {
    case ExpandedUndefined:
      break;
    case ExpandedCollapsed:
      properties.addItem(createProperty(
          AXWidgetStatesEnum::Expanded,
          createBooleanValue(false, AXValueTypeEnum::BooleanOrUndefined)));
      break;
    case ExpandedExpanded:
      properties.addItem(createProperty(
          AXWidgetStatesEnum::Expanded,
          createBooleanValue(true, AXValueTypeEnum::BooleanOrUndefined)));
      break;
  }

  if (role == ToggleButtonRole) {
    if (!axObject.isPressed()) {
      properties.addItem(
          createProperty(AXWidgetStatesEnum::Pressed,
                         createValue("false", AXValueTypeEnum::Tristate)));
    } else {
      const AtomicString& pressedAttr =
          axObject.getAttribute(HTMLNames::aria_pressedAttr);
      if (equalIgnoringCase(pressedAttr, "mixed"))
        properties.addItem(
            createProperty(AXWidgetStatesEnum::Pressed,
                           createValue("mixed", AXValueTypeEnum::Tristate)));
      else
        properties.addItem(
            createProperty(AXWidgetStatesEnum::Pressed,
                           createValue("true", AXValueTypeEnum::Tristate)));
    }
  }

  if (roleAllowsSelected(role)) {
    properties.addItem(
        createProperty(AXWidgetStatesEnum::Selected,
                       createBooleanValue(axObject.isSelected())));
  }
}

std::unique_ptr<AXProperty> createRelatedNodeListProperty(
    const String& key,
    AXRelatedObjectVector& nodes) {
  std::unique_ptr<AXValue> nodeListValue =
      createRelatedNodeListValue(nodes, AXValueTypeEnum::NodeList);
  return createProperty(key, std::move(nodeListValue));
}

std::unique_ptr<AXProperty> createRelatedNodeListProperty(
    const String& key,
    AXObject::AXObjectVector& nodes,
    const QualifiedName& attr,
    AXObject& axObject) {
  std::unique_ptr<AXValue> nodeListValue = createRelatedNodeListValue(nodes);
  const AtomicString& attrValue = axObject.getAttribute(attr);
  nodeListValue->setValue(protocol::StringValue::create(attrValue));
  return createProperty(key, std::move(nodeListValue));
}

class SparseAttributeAXPropertyAdapter
    : public GarbageCollected<SparseAttributeAXPropertyAdapter>,
      public AXSparseAttributeClient {
 public:
  SparseAttributeAXPropertyAdapter(AXObject& axObject,
                                   protocol::Array<AXProperty>& properties)
      : m_axObject(&axObject), m_properties(properties) {}

  DEFINE_INLINE_TRACE() { visitor->trace(m_axObject); }

 private:
  Member<AXObject> m_axObject;
  protocol::Array<AXProperty>& m_properties;

  void addBoolAttribute(AXBoolAttribute attribute, bool value) {}

  void addStringAttribute(AXStringAttribute attribute, const String& value) {}

  void addObjectAttribute(AXObjectAttribute attribute, AXObject& object) {
    switch (attribute) {
      case AXObjectAttribute::AriaActiveDescendant:
        m_properties.addItem(
            createProperty(AXRelationshipAttributesEnum::Activedescendant,
                           createRelatedNodeListValue(object)));
        break;
    }
  }

  void addObjectVectorAttribute(AXObjectVectorAttribute attribute,
                                HeapVector<Member<AXObject>>& objects) {
    switch (attribute) {
      case AXObjectVectorAttribute::AriaControls:
        m_properties.addItem(createRelatedNodeListProperty(
            AXRelationshipAttributesEnum::Controls, objects, aria_controlsAttr,
            *m_axObject));
        break;
      case AXObjectVectorAttribute::AriaFlowTo:
        m_properties.addItem(createRelatedNodeListProperty(
            AXRelationshipAttributesEnum::Flowto, objects, aria_flowtoAttr,
            *m_axObject));
        break;
    }
  }
};

void fillRelationships(AXObject& axObject,
                       protocol::Array<AXProperty>& properties) {
  AXObject::AXObjectVector results;
  axObject.ariaDescribedbyElements(results);
  if (!results.isEmpty())
    properties.addItem(
        createRelatedNodeListProperty(AXRelationshipAttributesEnum::Describedby,
                                      results, aria_describedbyAttr, axObject));
  results.clear();

  axObject.ariaOwnsElements(results);
  if (!results.isEmpty())
    properties.addItem(createRelatedNodeListProperty(
        AXRelationshipAttributesEnum::Owns, results, aria_ownsAttr, axObject));
  results.clear();
}

std::unique_ptr<AXValue> createRoleNameValue(AccessibilityRole role) {
  AtomicString roleName = AXObject::roleName(role);
  std::unique_ptr<AXValue> roleNameValue;
  if (!roleName.isNull()) {
    roleNameValue = createValue(roleName, AXValueTypeEnum::Role);
  } else {
    roleNameValue = createValue(AXObject::internalRoleName(role),
                                AXValueTypeEnum::InternalRole);
  }
  return roleNameValue;
}

}  // namespace

InspectorAccessibilityAgent::InspectorAccessibilityAgent(
    Page* page,
    InspectorDOMAgent* domAgent)
    : m_page(page), m_domAgent(domAgent) {}

Response InspectorAccessibilityAgent::getPartialAXTree(
    int domNodeId,
    Maybe<bool> fetchRelatives,
    std::unique_ptr<protocol::Array<AXNode>>* nodes) {
  if (!m_domAgent->enabled())
    return Response::Error("DOM agent must be enabled");
  Node* domNode = nullptr;
  Response response = m_domAgent->assertNode(domNodeId, domNode);
  if (!response.isSuccess())
    return response;

  Document& document = domNode->document();
  document.updateStyleAndLayoutIgnorePendingStylesheets();
  DocumentLifecycle::DisallowTransitionScope disallowTransition(
      document.lifecycle());
  LocalFrame* localFrame = document.frame();
  if (!localFrame)
    return Response::Error("Frame is detached.");
  std::unique_ptr<ScopedAXObjectCache> scopedCache =
      ScopedAXObjectCache::create(document);
  AXObjectCacheImpl* cache = toAXObjectCacheImpl(scopedCache->get());

  AXObject* inspectedAXObject = cache->getOrCreate(domNode);
  *nodes = protocol::Array<protocol::Accessibility::AXNode>::create();
  if (!inspectedAXObject || inspectedAXObject->accessibilityIsIgnored()) {
    (*nodes)->addItem(buildObjectForIgnoredNode(domNode, inspectedAXObject,
                                                fetchRelatives.fromMaybe(true),
                                                *nodes, *cache));
  } else {
    (*nodes)->addItem(
        buildProtocolAXObject(*inspectedAXObject, inspectedAXObject,
                              fetchRelatives.fromMaybe(true), *nodes, *cache));
  }

  if (!inspectedAXObject || !inspectedAXObject->isAXLayoutObject())
    return Response::OK();

  AXObject* parent = inspectedAXObject->parentObjectUnignored();
  if (!parent)
    return Response::OK();

  if (fetchRelatives.fromMaybe(true))
    addAncestors(*parent, inspectedAXObject, *nodes, *cache);

  return Response::OK();
}

void InspectorAccessibilityAgent::addAncestors(
    AXObject& firstAncestor,
    AXObject* inspectedAXObject,
    std::unique_ptr<protocol::Array<AXNode>>& nodes,
    AXObjectCacheImpl& cache) const {
  AXObject* ancestor = &firstAncestor;
  while (ancestor) {
    nodes->addItem(buildProtocolAXObject(*ancestor, inspectedAXObject, true,
                                         nodes, cache));
    ancestor = ancestor->parentObjectUnignored();
  }
}

std::unique_ptr<AXNode> InspectorAccessibilityAgent::buildObjectForIgnoredNode(
    Node* domNode,
    AXObject* axObject,
    bool fetchRelatives,
    std::unique_ptr<protocol::Array<AXNode>>& nodes,
    AXObjectCacheImpl& cache) const {
  AXObject::IgnoredReasons ignoredReasons;
  AXID axID = kIDForInspectedNodeWithNoAXNode;
  if (axObject && axObject->isAXLayoutObject())
    axID = axObject->axObjectID();
  std::unique_ptr<AXNode> ignoredNodeObject =
      AXNode::create().setNodeId(String::number(axID)).setIgnored(true).build();
  AccessibilityRole role = AccessibilityRole::IgnoredRole;
  ignoredNodeObject->setRole(createRoleNameValue(role));

  if (axObject && axObject->isAXLayoutObject()) {
    axObject->computeAccessibilityIsIgnored(&ignoredReasons);

    AXObject* parentObject = axObject->parentObjectUnignored();
    if (parentObject && fetchRelatives)
      addAncestors(*parentObject, axObject, nodes, cache);
  } else if (domNode && !domNode->layoutObject()) {
    if (fetchRelatives) {
      populateDOMNodeAncestors(*domNode, *(ignoredNodeObject.get()), nodes,
                               cache);
    }
    ignoredReasons.push_back(IgnoredReason(AXNotRendered));
  }

  if (domNode)
    ignoredNodeObject->setBackendDOMNodeId(DOMNodeIds::idForNode(domNode));

  std::unique_ptr<protocol::Array<AXProperty>> ignoredReasonProperties =
      protocol::Array<AXProperty>::create();
  for (size_t i = 0; i < ignoredReasons.size(); i++)
    ignoredReasonProperties->addItem(createProperty(ignoredReasons[i]));
  ignoredNodeObject->setIgnoredReasons(std::move(ignoredReasonProperties));

  return ignoredNodeObject;
}

void InspectorAccessibilityAgent::populateDOMNodeAncestors(
    Node& inspectedDOMNode,
    AXNode& nodeObject,
    std::unique_ptr<protocol::Array<AXNode>>& nodes,
    AXObjectCacheImpl& cache) const {
  // Walk up parents until an AXObject can be found.
  Node* parentNode = inspectedDOMNode.isShadowRoot()
                         ? &toShadowRoot(inspectedDOMNode).host()
                         : FlatTreeTraversal::parent(inspectedDOMNode);
  AXObject* parentAXObject = cache.getOrCreate(parentNode);
  while (parentNode && !parentAXObject) {
    parentNode = parentNode->isShadowRoot()
                     ? &toShadowRoot(parentNode)->host()
                     : FlatTreeTraversal::parent(*parentNode);
    parentAXObject = cache.getOrCreate(parentNode);
  }

  if (!parentAXObject)
    return;

  if (parentAXObject->accessibilityIsIgnored())
    parentAXObject = parentAXObject->parentObjectUnignored();
  if (!parentAXObject)
    return;

  // Populate parent and ancestors.
  std::unique_ptr<AXNode> parentNodeObject =
      buildProtocolAXObject(*parentAXObject, nullptr, true, nodes, cache);
  std::unique_ptr<protocol::Array<AXNodeId>> childIds =
      protocol::Array<AXNodeId>::create();
  childIds->addItem(String::number(kIDForInspectedNodeWithNoAXNode));
  parentNodeObject->setChildIds(std::move(childIds));
  nodes->addItem(std::move(parentNodeObject));

  AXObject* grandparentAXObject = parentAXObject->parentObjectUnignored();
  if (grandparentAXObject)
    addAncestors(*grandparentAXObject, nullptr, nodes, cache);
}

std::unique_ptr<AXNode> InspectorAccessibilityAgent::buildProtocolAXObject(
    AXObject& axObject,
    AXObject* inspectedAXObject,
    bool fetchRelatives,
    std::unique_ptr<protocol::Array<AXNode>>& nodes,
    AXObjectCacheImpl& cache) const {
  AccessibilityRole role = axObject.roleValue();
  std::unique_ptr<AXNode> nodeObject =
      AXNode::create()
          .setNodeId(String::number(axObject.axObjectID()))
          .setIgnored(false)
          .build();
  nodeObject->setRole(createRoleNameValue(role));

  std::unique_ptr<protocol::Array<AXProperty>> properties =
      protocol::Array<AXProperty>::create();
  fillLiveRegionProperties(axObject, *(properties.get()));
  fillGlobalStates(axObject, *(properties.get()));
  fillWidgetProperties(axObject, *(properties.get()));
  fillWidgetStates(axObject, *(properties.get()));
  fillRelationships(axObject, *(properties.get()));

  SparseAttributeAXPropertyAdapter adapter(axObject, *properties);
  axObject.getSparseAXAttributes(adapter);

  AXObject::NameSources nameSources;
  String computedName = axObject.name(&nameSources);
  if (!nameSources.isEmpty()) {
    std::unique_ptr<AXValue> name =
        createValue(computedName, AXValueTypeEnum::ComputedString);
    if (!nameSources.isEmpty()) {
      std::unique_ptr<protocol::Array<AXValueSource>> nameSourceProperties =
          protocol::Array<AXValueSource>::create();
      for (size_t i = 0; i < nameSources.size(); ++i) {
        NameSource& nameSource = nameSources[i];
        nameSourceProperties->addItem(createValueSource(nameSource));
        if (nameSource.text.isNull() || nameSource.superseded)
          continue;
        if (!nameSource.relatedObjects.isEmpty()) {
          properties->addItem(createRelatedNodeListProperty(
              AXRelationshipAttributesEnum::Labelledby,
              nameSource.relatedObjects));
        }
      }
      name->setSources(std::move(nameSourceProperties));
    }
    nodeObject->setProperties(std::move(properties));
    nodeObject->setName(std::move(name));
  } else {
    nodeObject->setProperties(std::move(properties));
  }

  fillCoreProperties(axObject, inspectedAXObject, fetchRelatives,
                     *(nodeObject.get()), nodes, cache);
  return nodeObject;
}

void InspectorAccessibilityAgent::fillCoreProperties(
    AXObject& axObject,
    AXObject* inspectedAXObject,
    bool fetchRelatives,
    AXNode& nodeObject,
    std::unique_ptr<protocol::Array<AXNode>>& nodes,
    AXObjectCacheImpl& cache) const {
  AXNameFrom nameFrom;
  AXObject::AXObjectVector nameObjects;
  axObject.name(nameFrom, &nameObjects);

  AXDescriptionFrom descriptionFrom;
  AXObject::AXObjectVector descriptionObjects;
  String description =
      axObject.description(nameFrom, descriptionFrom, &descriptionObjects);
  if (!description.isEmpty()) {
    nodeObject.setDescription(
        createValue(description, AXValueTypeEnum::ComputedString));
  }
  // Value.
  if (axObject.supportsRangeValue()) {
    nodeObject.setValue(createValue(axObject.valueForRange()));
  } else {
    String stringValue = axObject.stringValue();
    if (!stringValue.isEmpty())
      nodeObject.setValue(createValue(stringValue));
  }

  if (fetchRelatives)
    populateRelatives(axObject, inspectedAXObject, nodeObject, nodes, cache);

  Node* node = axObject.getNode();
  if (node)
    nodeObject.setBackendDOMNodeId(DOMNodeIds::idForNode(node));
}

void InspectorAccessibilityAgent::populateRelatives(
    AXObject& axObject,
    AXObject* inspectedAXObject,
    AXNode& nodeObject,
    std::unique_ptr<protocol::Array<AXNode>>& nodes,
    AXObjectCacheImpl& cache) const {
  AXObject* parentObject = axObject.parentObject();
  if (parentObject && parentObject != inspectedAXObject) {
    // Use unignored parent unless parent is inspected ignored object.
    parentObject = axObject.parentObjectUnignored();
  }

  std::unique_ptr<protocol::Array<AXNodeId>> childIds =
      protocol::Array<AXNodeId>::create();

  if (&axObject != inspectedAXObject ||
      (inspectedAXObject && !inspectedAXObject->accessibilityIsIgnored())) {
    addChildren(axObject, inspectedAXObject, childIds, nodes, cache);
  }
  nodeObject.setChildIds(std::move(childIds));
}

void InspectorAccessibilityAgent::addChild(
    std::unique_ptr<protocol::Array<AXNodeId>>& childIds,
    AXObject& childAXObject,
    AXObject* inspectedAXObject,
    std::unique_ptr<protocol::Array<AXNode>>& nodes,
    AXObjectCacheImpl& cache) const {
  childIds->addItem(String::number(childAXObject.axObjectID()));
  if (&childAXObject == inspectedAXObject)
    return;
  nodes->addItem(buildProtocolAXObject(childAXObject, inspectedAXObject, true,
                                       nodes, cache));
}

void InspectorAccessibilityAgent::addChildren(
    AXObject& axObject,
    AXObject* inspectedAXObject,
    std::unique_ptr<protocol::Array<AXNodeId>>& childIds,
    std::unique_ptr<protocol::Array<AXNode>>& nodes,
    AXObjectCacheImpl& cache) const {
  if (inspectedAXObject && inspectedAXObject->accessibilityIsIgnored() &&
      &axObject == inspectedAXObject->parentObjectUnignored()) {
    childIds->addItem(String::number(inspectedAXObject->axObjectID()));
    return;
  }

  const AXObject::AXObjectVector& children = axObject.children();
  for (unsigned i = 0; i < children.size(); i++) {
    AXObject& childAXObject = *children[i].get();
    childIds->addItem(String::number(childAXObject.axObjectID()));
    if (&childAXObject == inspectedAXObject)
      continue;
    if (&axObject != inspectedAXObject) {
      if (!inspectedAXObject)
        continue;
      if (&axObject != inspectedAXObject->parentObjectUnignored())
        continue;
    }

    // Only add children/siblings of inspected node to returned nodes.
    std::unique_ptr<AXNode> childNode = buildProtocolAXObject(
        childAXObject, inspectedAXObject, true, nodes, cache);
    nodes->addItem(std::move(childNode));
  }
}

DEFINE_TRACE(InspectorAccessibilityAgent) {
  visitor->trace(m_page);
  visitor->trace(m_domAgent);
  InspectorBaseAgent::trace(visitor);
}

}  // namespace blink
