/*
 * Copyright (C) 2014, 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/AXObjectCacheImpl.h"

#include "core/HTMLNames.h"
#include "core/InputTypeNames.h"
#include "core/dom/Document.h"
#include "core/editing/EditingUtilities.h"
#include "core/frame/FrameView.h"
#include "core/frame/LocalFrame.h"
#include "core/frame/Settings.h"
#include "core/html/HTMLAreaElement.h"
#include "core/html/HTMLCanvasElement.h"
#include "core/html/HTMLImageElement.h"
#include "core/html/HTMLInputElement.h"
#include "core/html/HTMLLabelElement.h"
#include "core/html/HTMLOptionElement.h"
#include "core/html/HTMLSelectElement.h"
#include "core/layout/LayoutListBox.h"
#include "core/layout/LayoutMenuList.h"
#include "core/layout/LayoutProgress.h"
#include "core/layout/LayoutSlider.h"
#include "core/layout/LayoutTable.h"
#include "core/layout/LayoutTableCell.h"
#include "core/layout/LayoutTableRow.h"
#include "core/layout/LayoutView.h"
#include "core/layout/api/LineLayoutAPIShim.h"
#include "core/layout/line/AbstractInlineTextBox.h"
#include "core/page/ChromeClient.h"
#include "core/page/FocusController.h"
#include "core/page/Page.h"
#include "modules/accessibility/AXARIAGrid.h"
#include "modules/accessibility/AXARIAGridCell.h"
#include "modules/accessibility/AXARIAGridRow.h"
#include "modules/accessibility/AXImageMapLink.h"
#include "modules/accessibility/AXInlineTextBox.h"
#include "modules/accessibility/AXLayoutObject.h"
#include "modules/accessibility/AXList.h"
#include "modules/accessibility/AXListBox.h"
#include "modules/accessibility/AXListBoxOption.h"
#include "modules/accessibility/AXMediaControls.h"
#include "modules/accessibility/AXMenuList.h"
#include "modules/accessibility/AXMenuListOption.h"
#include "modules/accessibility/AXMenuListPopup.h"
#include "modules/accessibility/AXProgressIndicator.h"
#include "modules/accessibility/AXRadioInput.h"
#include "modules/accessibility/AXSVGRoot.h"
#include "modules/accessibility/AXSlider.h"
#include "modules/accessibility/AXSpinButton.h"
#include "modules/accessibility/AXTable.h"
#include "modules/accessibility/AXTableCell.h"
#include "modules/accessibility/AXTableColumn.h"
#include "modules/accessibility/AXTableHeaderContainer.h"
#include "modules/accessibility/AXTableRow.h"
#include "wtf/PassRefPtr.h"
#include "wtf/PtrUtil.h"

namespace blink {

using namespace HTMLNames;

// static
AXObjectCache* AXObjectCacheImpl::create(Document& document) {
  return new AXObjectCacheImpl(document);
}

AXObjectCacheImpl::AXObjectCacheImpl(Document& document)
    : m_document(document),
      m_modificationCount(0),
      m_notificationPostTimer(this,
                              &AXObjectCacheImpl::notificationPostTimerFired) {
}

AXObjectCacheImpl::~AXObjectCacheImpl() {
  ASSERT(m_hasBeenDisposed);
}

void AXObjectCacheImpl::dispose() {
  m_notificationPostTimer.stop();

  for (auto& entry : m_objects) {
    AXObject* obj = entry.value;
    obj->detach();
    removeAXID(obj);
  }

#if DCHECK_IS_ON()
  m_hasBeenDisposed = true;
#endif
}

AXObject* AXObjectCacheImpl::root() {
  return getOrCreate(m_document);
}

AXObject* AXObjectCacheImpl::focusedImageMapUIElement(
    HTMLAreaElement* areaElement) {
  // Find the corresponding accessibility object for the HTMLAreaElement. This
  // should be in the list of children for its corresponding image.
  if (!areaElement)
    return 0;

  HTMLImageElement* imageElement = areaElement->imageElement();
  if (!imageElement)
    return 0;

  AXObject* axLayoutImage = getOrCreate(imageElement);
  if (!axLayoutImage)
    return 0;

  const AXObject::AXObjectVector& imageChildren = axLayoutImage->children();
  unsigned count = imageChildren.size();
  for (unsigned k = 0; k < count; ++k) {
    AXObject* child = imageChildren[k];
    if (!child->isImageMapLink())
      continue;

    if (toAXImageMapLink(child)->areaElement() == areaElement)
      return child;
  }

  return 0;
}

AXObject* AXObjectCacheImpl::focusedObject() {
  if (!accessibilityEnabled())
    return nullptr;

  Node* focusedNode = m_document->focusedElement();
  if (!focusedNode)
    focusedNode = m_document;

  // If it's an image map, get the focused link within the image map.
  if (isHTMLAreaElement(focusedNode))
    return focusedImageMapUIElement(toHTMLAreaElement(focusedNode));

  // See if there's a page popup, for example a calendar picker.
  Element* adjustedFocusedElement = m_document->adjustedFocusedElement();
  if (isHTMLInputElement(adjustedFocusedElement)) {
    if (AXObject* axPopup =
            toHTMLInputElement(adjustedFocusedElement)->popupRootAXObject()) {
      if (Element* focusedElementInPopup =
              axPopup->getDocument()->focusedElement())
        focusedNode = focusedElementInPopup;
    }
  }

  AXObject* obj = getOrCreate(focusedNode);
  if (!obj)
    return nullptr;

  // the HTML element, for example, is focusable but has an AX object that is
  // ignored
  if (obj->accessibilityIsIgnored())
    obj = obj->parentObjectUnignored();

  return obj;
}

AXObject* AXObjectCacheImpl::get(LayoutObject* layoutObject) {
  if (!layoutObject)
    return 0;

  AXID axID = m_layoutObjectMapping.get(layoutObject);
  ASSERT(!HashTraits<AXID>::isDeletedValue(axID));
  if (!axID)
    return 0;

  return m_objects.get(axID);
}

// Returns true if |node| is an <option> element and its parent <select>
// is a menu list (not a list box).
static bool isMenuListOption(Node* node) {
  if (!isHTMLOptionElement(node))
    return false;
  HTMLSelectElement* select = toHTMLOptionElement(node)->ownerSelectElement();
  if (!select)
    return false;
  LayoutObject* layoutObject = select->layoutObject();
  return layoutObject && layoutObject->isMenuList();
}

AXObject* AXObjectCacheImpl::get(Node* node) {
  if (!node)
    return 0;

  // Menu list option and HTML area elements are indexed by DOM node, never by
  // layout object.
  LayoutObject* layoutObject = node->layoutObject();
  if (isMenuListOption(node) || isHTMLAreaElement(node))
    layoutObject = nullptr;

  AXID layoutID = layoutObject ? m_layoutObjectMapping.get(layoutObject) : 0;
  ASSERT(!HashTraits<AXID>::isDeletedValue(layoutID));

  AXID nodeID = m_nodeObjectMapping.get(node);
  ASSERT(!HashTraits<AXID>::isDeletedValue(nodeID));

  if (layoutObject && nodeID && !layoutID) {
    // This can happen if an AXNodeObject is created for a node that's not
    // laid out, but later something changes and it gets a layoutObject (like if
    // it's reparented).
    remove(nodeID);
    return 0;
  }

  if (layoutID)
    return m_objects.get(layoutID);

  if (!nodeID)
    return 0;

  return m_objects.get(nodeID);
}

AXObject* AXObjectCacheImpl::get(AbstractInlineTextBox* inlineTextBox) {
  if (!inlineTextBox)
    return 0;

  AXID axID = m_inlineTextBoxObjectMapping.get(inlineTextBox);
  ASSERT(!HashTraits<AXID>::isDeletedValue(axID));
  if (!axID)
    return 0;

  return m_objects.get(axID);
}

// FIXME: This probably belongs on Node.
// FIXME: This should take a const char*, but one caller passes nullAtom.
bool nodeHasRole(Node* node, const String& role) {
  if (!node || !node->isElementNode())
    return false;

  return equalIgnoringCase(toElement(node)->getAttribute(roleAttr), role);
}

AXObject* AXObjectCacheImpl::createFromRenderer(LayoutObject* layoutObject) {
  // FIXME: How could layoutObject->node() ever not be an Element?
  Node* node = layoutObject->node();

  // If the node is aria role="list" or the aria role is empty and its a
  // ul/ol/dl type (it shouldn't be a list if aria says otherwise).
  if (nodeHasRole(node, "list") || nodeHasRole(node, "directory") ||
      (nodeHasRole(node, nullAtom) &&
       (isHTMLUListElement(node) || isHTMLOListElement(node) ||
        isHTMLDListElement(node))))
    return AXList::create(layoutObject, *this);

  // aria tables
  if (nodeHasRole(node, "grid") || nodeHasRole(node, "treegrid"))
    return AXARIAGrid::create(layoutObject, *this);
  if (nodeHasRole(node, "row"))
    return AXARIAGridRow::create(layoutObject, *this);
  if (nodeHasRole(node, "gridcell") || nodeHasRole(node, "columnheader") ||
      nodeHasRole(node, "rowheader"))
    return AXARIAGridCell::create(layoutObject, *this);

  // media controls
  if (node && node->isMediaControlElement())
    return AccessibilityMediaControl::create(layoutObject, *this);

  if (isHTMLOptionElement(node))
    return AXListBoxOption::create(layoutObject, *this);

  if (isHTMLInputElement(node) &&
      toHTMLInputElement(node)->type() == InputTypeNames::radio)
    return AXRadioInput::create(layoutObject, *this);

  if (layoutObject->isSVGRoot())
    return AXSVGRoot::create(layoutObject, *this);

  if (layoutObject->isBoxModelObject()) {
    LayoutBoxModelObject* cssBox = toLayoutBoxModelObject(layoutObject);
    if (cssBox->isListBox())
      return AXListBox::create(toLayoutListBox(cssBox), *this);
    if (cssBox->isMenuList())
      return AXMenuList::create(toLayoutMenuList(cssBox), *this);

    // standard tables
    if (cssBox->isTable())
      return AXTable::create(toLayoutTable(cssBox), *this);
    if (cssBox->isTableRow())
      return AXTableRow::create(toLayoutTableRow(cssBox), *this);
    if (cssBox->isTableCell())
      return AXTableCell::create(toLayoutTableCell(cssBox), *this);

    // progress bar
    if (cssBox->isProgress())
      return AXProgressIndicator::create(toLayoutProgress(cssBox), *this);

    // input type=range
    if (cssBox->isSlider())
      return AXSlider::create(toLayoutSlider(cssBox), *this);
  }

  return AXLayoutObject::create(layoutObject, *this);
}

AXObject* AXObjectCacheImpl::createFromNode(Node* node) {
  if (isMenuListOption(node))
    return AXMenuListOption::create(toHTMLOptionElement(node), *this);

  if (isHTMLAreaElement(node))
    return AXImageMapLink::create(toHTMLAreaElement(node), *this);

  return AXNodeObject::create(node, *this);
}

AXObject* AXObjectCacheImpl::createFromInlineTextBox(
    AbstractInlineTextBox* inlineTextBox) {
  return AXInlineTextBox::create(inlineTextBox, *this);
}

AXObject* AXObjectCacheImpl::getOrCreate(Node* node) {
  if (!node)
    return 0;

  if (AXObject* obj = get(node))
    return obj;

  // If the node has a layout object, prefer using that as the primary key for
  // the AXObject, with the exception of an HTMLAreaElement, which is created
  // based on its node.
  if (node->layoutObject() && !isHTMLAreaElement(node))
    return getOrCreate(node->layoutObject());

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

  if (isHTMLHeadElement(node))
    return 0;

  AXObject* newObj = createFromNode(node);

  // Will crash later if we have two objects for the same node.
  ASSERT(!get(node));

  getAXID(newObj);

  m_nodeObjectMapping.set(node, newObj->axObjectID());
  m_objects.set(newObj->axObjectID(), newObj);
  newObj->init();
  newObj->setLastKnownIsIgnoredValue(newObj->accessibilityIsIgnored());

  if (node->isElementNode())
    updateTreeIfElementIdIsAriaOwned(toElement(node));

  return newObj;
}

AXObject* AXObjectCacheImpl::getOrCreate(LayoutObject* layoutObject) {
  if (!layoutObject)
    return 0;

  if (AXObject* obj = get(layoutObject))
    return obj;

  AXObject* newObj = createFromRenderer(layoutObject);

  // Will crash later if we have two objects for the same layoutObject.
  ASSERT(!get(layoutObject));

  getAXID(newObj);

  m_layoutObjectMapping.set(layoutObject, newObj->axObjectID());
  m_objects.set(newObj->axObjectID(), newObj);
  newObj->init();
  newObj->setLastKnownIsIgnoredValue(newObj->accessibilityIsIgnored());

  return newObj;
}

AXObject* AXObjectCacheImpl::getOrCreate(AbstractInlineTextBox* inlineTextBox) {
  if (!inlineTextBox)
    return 0;

  if (AXObject* obj = get(inlineTextBox))
    return obj;

  AXObject* newObj = createFromInlineTextBox(inlineTextBox);

  // Will crash later if we have two objects for the same inlineTextBox.
  ASSERT(!get(inlineTextBox));

  getAXID(newObj);

  m_inlineTextBoxObjectMapping.set(inlineTextBox, newObj->axObjectID());
  m_objects.set(newObj->axObjectID(), newObj);
  newObj->init();
  newObj->setLastKnownIsIgnoredValue(newObj->accessibilityIsIgnored());

  return newObj;
}

AXObject* AXObjectCacheImpl::rootObject() {
  if (!accessibilityEnabled())
    return 0;

  return getOrCreate(m_document);
}

AXObject* AXObjectCacheImpl::getOrCreate(AccessibilityRole role) {
  AXObject* obj = nullptr;

  // will be filled in...
  switch (role) {
    case ColumnRole:
      obj = AXTableColumn::create(*this);
      break;
    case TableHeaderContainerRole:
      obj = AXTableHeaderContainer::create(*this);
      break;
    case SliderThumbRole:
      obj = AXSliderThumb::create(*this);
      break;
    case MenuListPopupRole:
      obj = AXMenuListPopup::create(*this);
      break;
    case SpinButtonRole:
      obj = AXSpinButton::create(*this);
      break;
    case SpinButtonPartRole:
      obj = AXSpinButtonPart::create(*this);
      break;
    default:
      obj = nullptr;
  }

  if (obj)
    getAXID(obj);
  else
    return 0;

  m_objects.set(obj->axObjectID(), obj);
  obj->init();
  return obj;
}

void AXObjectCacheImpl::remove(AXID axID) {
  if (!axID)
    return;

  // first fetch object to operate some cleanup functions on it
  AXObject* obj = m_objects.get(axID);
  if (!obj)
    return;

  obj->detach();
  removeAXID(obj);

  // finally remove the object
  if (!m_objects.take(axID))
    return;

  ASSERT(m_objects.size() >= m_idsInUse.size());
}

void AXObjectCacheImpl::remove(LayoutObject* layoutObject) {
  if (!layoutObject)
    return;

  AXID axID = m_layoutObjectMapping.get(layoutObject);
  remove(axID);
  m_layoutObjectMapping.remove(layoutObject);
}

void AXObjectCacheImpl::remove(Node* node) {
  if (!node)
    return;

  // This is all safe even if we didn't have a mapping.
  AXID axID = m_nodeObjectMapping.get(node);
  remove(axID);
  m_nodeObjectMapping.remove(node);

  if (node->layoutObject()) {
    remove(node->layoutObject());
    return;
  }
}

void AXObjectCacheImpl::remove(AbstractInlineTextBox* inlineTextBox) {
  if (!inlineTextBox)
    return;

  AXID axID = m_inlineTextBoxObjectMapping.get(inlineTextBox);
  remove(axID);
  m_inlineTextBoxObjectMapping.remove(inlineTextBox);
}

AXID AXObjectCacheImpl::platformGenerateAXID() const {
  static AXID lastUsedID = 0;

  // Generate a new ID.
  AXID objID = lastUsedID;
  do {
    ++objID;
  } while (!objID || HashTraits<AXID>::isDeletedValue(objID) ||
           m_idsInUse.contains(objID));

  lastUsedID = objID;

  return objID;
}

AXID AXObjectCacheImpl::getAXID(AXObject* obj) {
  // check for already-assigned ID
  AXID objID = obj->axObjectID();
  if (objID) {
    ASSERT(m_idsInUse.contains(objID));
    return objID;
  }

  objID = platformGenerateAXID();

  m_idsInUse.add(objID);
  obj->setAXObjectID(objID);

  return objID;
}

void AXObjectCacheImpl::removeAXID(AXObject* object) {
  if (!object)
    return;

  AXID objID = object->axObjectID();
  if (!objID)
    return;
  ASSERT(!HashTraits<AXID>::isDeletedValue(objID));
  ASSERT(m_idsInUse.contains(objID));
  object->setAXObjectID(0);
  m_idsInUse.remove(objID);

  if (m_ariaOwnerToChildrenMapping.contains(objID)) {
    Vector<AXID> childAXIDs = m_ariaOwnerToChildrenMapping.get(objID);
    for (size_t i = 0; i < childAXIDs.size(); ++i)
      m_ariaOwnedChildToOwnerMapping.remove(childAXIDs[i]);
    m_ariaOwnerToChildrenMapping.remove(objID);
  }
  m_ariaOwnedChildToOwnerMapping.remove(objID);
  m_ariaOwnedChildToRealParentMapping.remove(objID);
  m_ariaOwnerToIdsMapping.remove(objID);
}

void AXObjectCacheImpl::selectionChanged(Node* node) {
  // Find the nearest ancestor that already has an accessibility object, since
  // we might be in the middle of a layout.
  while (node) {
    if (AXObject* obj = get(node)) {
      obj->selectionChanged();
      return;
    }
    node = node->parentNode();
  }
}

void AXObjectCacheImpl::textChanged(Node* node) {
  textChanged(getOrCreate(node));
}

void AXObjectCacheImpl::textChanged(LayoutObject* layoutObject) {
  textChanged(getOrCreate(layoutObject));
}

void AXObjectCacheImpl::textChanged(AXObject* obj) {
  if (!obj)
    return;

  bool parentAlreadyExists = obj->parentObjectIfExists();
  obj->textChanged();
  postNotification(obj, AXObjectCacheImpl::AXTextChanged);
  if (parentAlreadyExists)
    obj->notifyIfIgnoredValueChanged();
}

void AXObjectCacheImpl::updateCacheAfterNodeIsAttached(Node* node) {
  // Calling get() will update the AX object if we had an AXNodeObject but now
  // we need an AXLayoutObject, because it was reparented to a location outside
  // of a canvas.
  get(node);
  if (node->isElementNode())
    updateTreeIfElementIdIsAriaOwned(toElement(node));
}

void AXObjectCacheImpl::childrenChanged(Node* node) {
  childrenChanged(get(node));
}

void AXObjectCacheImpl::childrenChanged(LayoutObject* layoutObject) {
  childrenChanged(get(layoutObject));
}

void AXObjectCacheImpl::childrenChanged(AXObject* obj) {
  if (!obj)
    return;

  obj->childrenChanged();
}

void AXObjectCacheImpl::notificationPostTimerFired(TimerBase*) {
  m_notificationPostTimer.stop();

  unsigned i = 0, count = m_notificationsToPost.size();
  for (i = 0; i < count; ++i) {
    AXObject* obj = m_notificationsToPost[i].first;

    if (!obj->axObjectID())
      continue;

    if (obj->isDetached())
      continue;

#if DCHECK_IS_ON()
    // Make sure none of the layout views are in the process of being layed out.
    // Notifications should only be sent after the layoutObject has finished
    if (obj->isAXLayoutObject()) {
      AXLayoutObject* layoutObj = toAXLayoutObject(obj);
      LayoutObject* layoutObject = layoutObj->getLayoutObject();
      if (layoutObject && layoutObject->view())
        ASSERT(!layoutObject->view()->layoutState());
    }
#endif

    AXNotification notification = m_notificationsToPost[i].second;
    postPlatformNotification(obj, notification);

    if (notification == AXChildrenChanged && obj->parentObjectIfExists() &&
        obj->lastKnownIsIgnoredValue() != obj->accessibilityIsIgnored())
      childrenChanged(obj->parentObject());
  }

  m_notificationsToPost.clear();
}

void AXObjectCacheImpl::postNotification(LayoutObject* layoutObject,
                                         AXNotification notification) {
  if (!layoutObject)
    return;

  m_modificationCount++;
  postNotification(get(layoutObject), notification);
}

void AXObjectCacheImpl::postNotification(Node* node,
                                         AXNotification notification) {
  if (!node)
    return;

  m_modificationCount++;
  postNotification(get(node), notification);
}

void AXObjectCacheImpl::postNotification(AXObject* object,
                                         AXNotification notification) {
  m_modificationCount++;
  if (!object)
    return;

  m_notificationsToPost.push_back(std::make_pair(object, notification));
  if (!m_notificationPostTimer.isActive())
    m_notificationPostTimer.startOneShot(0, BLINK_FROM_HERE);
}

bool AXObjectCacheImpl::isAriaOwned(const AXObject* child) const {
  return m_ariaOwnedChildToOwnerMapping.contains(child->axObjectID());
}

AXObject* AXObjectCacheImpl::getAriaOwnedParent(const AXObject* child) const {
  return objectFromAXID(
      m_ariaOwnedChildToOwnerMapping.get(child->axObjectID()));
}

void AXObjectCacheImpl::updateAriaOwns(
    const AXObject* owner,
    const Vector<String>& idVector,
    HeapVector<Member<AXObject>>& ownedChildren) {
  //
  // Update the map from the AXID of this element to the ids of the owned
  // children, and the reverse map from ids to possible AXID owners.
  //

  HashSet<String> currentIds = m_ariaOwnerToIdsMapping.get(owner->axObjectID());
  HashSet<String> newIds;
  bool idsChanged = false;
  for (const String& id : idVector) {
    newIds.add(id);
    if (!currentIds.contains(id)) {
      idsChanged = true;
      HashSet<AXID>* owners = m_idToAriaOwnersMapping.get(id);
      if (!owners) {
        owners = new HashSet<AXID>();
        m_idToAriaOwnersMapping.set(id, WTF::wrapUnique(owners));
      }
      owners->add(owner->axObjectID());
    }
  }
  for (const String& id : currentIds) {
    if (!newIds.contains(id)) {
      idsChanged = true;
      HashSet<AXID>* owners = m_idToAriaOwnersMapping.get(id);
      if (owners) {
        owners->remove(owner->axObjectID());
        if (owners->isEmpty())
          m_idToAriaOwnersMapping.remove(id);
      }
    }
  }
  if (idsChanged)
    m_ariaOwnerToIdsMapping.set(owner->axObjectID(), newIds);

  //
  // Now figure out the ids that actually correspond to children that exist and
  // that we can legally own (not cyclical, not already owned, etc.) and update
  // the maps and |ownedChildren| based on that.
  //

  // Figure out the children that are owned by this object and are in the tree.
  TreeScope& scope = owner->getNode()->treeScope();
  Vector<AXID> newChildAXIDs;
  for (const String& idName : idVector) {
    Element* element = scope.getElementById(AtomicString(idName));
    if (!element)
      continue;

    AXObject* child = getOrCreate(element);
    if (!child)
      continue;

    // If this child is already aria-owned by a different owner, continue.
    // It's an author error if this happens and we don't worry about which of
    // the two owners wins ownership of the child, as long as only one of them
    // does.
    if (isAriaOwned(child) && getAriaOwnedParent(child) != owner)
      continue;

    // You can't own yourself!
    if (child == owner)
      continue;

    // Walk up the parents of the owner object, make sure that this child
    // doesn't appear there, as that would create a cycle.
    bool foundCycle = false;
    for (AXObject* parent = owner->parentObject(); parent && !foundCycle;
         parent = parent->parentObject()) {
      if (parent == child)
        foundCycle = true;
    }
    if (foundCycle)
      continue;

    newChildAXIDs.push_back(child->axObjectID());
    ownedChildren.push_back(child);
  }

  // Compare this to the current list of owned children, and exit early if there
  // are no changes.
  Vector<AXID> currentChildAXIDs =
      m_ariaOwnerToChildrenMapping.get(owner->axObjectID());
  bool same = true;
  if (currentChildAXIDs.size() != newChildAXIDs.size()) {
    same = false;
  } else {
    for (size_t i = 0; i < currentChildAXIDs.size() && same; ++i) {
      if (currentChildAXIDs[i] != newChildAXIDs[i])
        same = false;
    }
  }
  if (same)
    return;

  // The list of owned children has changed. Even if they were just reordered,
  // to be safe and handle all cases we remove all of the current owned children
  // and add the new list of owned children.
  for (size_t i = 0; i < currentChildAXIDs.size(); ++i) {
    // Find the AXObject for the child that this owner no longer owns.
    AXID removedChildID = currentChildAXIDs[i];
    AXObject* removedChild = objectFromAXID(removedChildID);

    // It's possible that this child has already been owned by some other owner,
    // in which case we don't need to do anything.
    if (removedChild && getAriaOwnedParent(removedChild) != owner)
      continue;

    // Remove it from the child -> owner mapping so it's not owned by this owner
    // anymore.
    m_ariaOwnedChildToOwnerMapping.remove(removedChildID);

    if (removedChild) {
      // If the child still exists, find its "real" parent, and reparent it back
      // to its real parent in the tree by detaching it from its current parent
      // and calling childrenChanged on its real parent.
      removedChild->detachFromParent();
      AXID realParentID =
          m_ariaOwnedChildToRealParentMapping.get(removedChildID);
      AXObject* realParent = objectFromAXID(realParentID);
      childrenChanged(realParent);
    }

    // Remove the child -> original parent mapping too since this object has now
    // been reparented back to its original parent.
    m_ariaOwnedChildToRealParentMapping.remove(removedChildID);
  }

  for (size_t i = 0; i < newChildAXIDs.size(); ++i) {
    // Find the AXObject for the child that will now be a child of this owner.
    AXID addedChildID = newChildAXIDs[i];
    AXObject* addedChild = objectFromAXID(addedChildID);

    // Add this child to the mapping from child to owner.
    m_ariaOwnedChildToOwnerMapping.set(addedChildID, owner->axObjectID());

    // Add its parent object to a mapping from child to real parent. If later
    // this owner doesn't own this child anymore, we need to return it to its
    // original parent.
    AXObject* originalParent = addedChild->parentObject();
    m_ariaOwnedChildToRealParentMapping.set(addedChildID,
                                            originalParent->axObjectID());

    // Now detach the object from its original parent and call childrenChanged
    // on the original parent so that it can recompute its list of children.
    addedChild->detachFromParent();
    childrenChanged(originalParent);
  }

  // Finally, update the mapping from the owner to the list of child IDs.
  m_ariaOwnerToChildrenMapping.set(owner->axObjectID(), newChildAXIDs);
}

void AXObjectCacheImpl::updateTreeIfElementIdIsAriaOwned(Element* element) {
  if (!element->hasID())
    return;

  String id = element->getIdAttribute();
  HashSet<AXID>* owners = m_idToAriaOwnersMapping.get(id);
  if (!owners)
    return;

  AXObject* axElement = getOrCreate(element);
  if (!axElement)
    return;

  // If it's already owned, call childrenChanged on the owner to make sure it's
  // still an owner.
  if (isAriaOwned(axElement)) {
    AXObject* ownedParent = getAriaOwnedParent(axElement);
    ASSERT(ownedParent);
    childrenChanged(ownedParent);
    return;
  }

  // If it's not already owned, check the possible owners based on our mapping
  // from ids to elements that have that id listed in their aria-owns attribute.
  for (const auto& axID : *owners) {
    AXObject* owner = objectFromAXID(axID);
    if (owner)
      childrenChanged(owner);
  }
}

void AXObjectCacheImpl::checkedStateChanged(Node* node) {
  postNotification(node, AXObjectCacheImpl::AXCheckedStateChanged);
}

void AXObjectCacheImpl::listboxOptionStateChanged(HTMLOptionElement* option) {
  postNotification(option, AXCheckedStateChanged);
}

void AXObjectCacheImpl::listboxSelectedChildrenChanged(
    HTMLSelectElement* select) {
  postNotification(select, AXSelectedChildrenChanged);
}

void AXObjectCacheImpl::listboxActiveIndexChanged(HTMLSelectElement* select) {
  AXObject* obj = get(select);
  if (!obj || !obj->isAXListBox())
    return;

  toAXListBox(obj)->activeIndexChanged();
}

void AXObjectCacheImpl::radiobuttonRemovedFromGroup(
    HTMLInputElement* groupMember) {
  AXObject* obj = get(groupMember);
  if (!obj || !obj->isAXRadioInput())
    return;

  // The 'posInSet' and 'setSize' attributes should be updated from the first
  // node, as the removed node is already detached from tree.
  HTMLInputElement* firstRadio =
      toAXRadioInput(obj)->findFirstRadioButtonInGroup(groupMember);
  AXObject* firstObj = get(firstRadio);
  if (!firstObj || !firstObj->isAXRadioInput())
    return;

  toAXRadioInput(firstObj)->updatePosAndSetSize(1);
  postNotification(firstObj, AXAriaAttributeChanged);
  toAXRadioInput(firstObj)->requestUpdateToNextNode(true);
}

void AXObjectCacheImpl::handleLayoutComplete(LayoutObject* layoutObject) {
  if (!layoutObject)
    return;

  m_modificationCount++;

  // Create the AXObject if it didn't yet exist - that's always safe at the end
  // of a layout, and it allows an AX notification to be sent when a page has
  // its first layout, rather than when the document first loads.
  if (AXObject* obj = getOrCreate(layoutObject))
    postNotification(obj, AXLayoutComplete);
}

void AXObjectCacheImpl::handleClicked(Node* node) {
  if (AXObject* obj = getOrCreate(node))
    postNotification(obj, AXClicked);
}

void AXObjectCacheImpl::handleAriaExpandedChange(Node* node) {
  if (AXObject* obj = getOrCreate(node))
    obj->handleAriaExpandedChanged();
}

void AXObjectCacheImpl::handleAriaSelectedChanged(Node* node) {
  AXObject* obj = get(node);
  if (!obj)
    return;

  postNotification(obj, AXCheckedStateChanged);

  AXObject* listbox = obj->parentObjectUnignored();
  if (listbox && listbox->roleValue() == ListBoxRole)
    postNotification(listbox, AXSelectedChildrenChanged);
}

void AXObjectCacheImpl::handleActiveDescendantChanged(Node* node) {
  // Changing the active descendant should trigger recomputing all
  // cached values even if it doesn't result in a notification, because
  // it can affect what's focusable or not.
  m_modificationCount++;

  if (AXObject* obj = getOrCreate(node))
    obj->handleActiveDescendantChanged();
}

void AXObjectCacheImpl::handleAriaRoleChanged(Node* node) {
  if (AXObject* obj = getOrCreate(node)) {
    obj->updateAccessibilityRole();
    m_modificationCount++;
    obj->notifyIfIgnoredValueChanged();
  }
}

void AXObjectCacheImpl::handleAttributeChanged(const QualifiedName& attrName,
                                               Element* element) {
  if (attrName == roleAttr)
    handleAriaRoleChanged(element);
  else if (attrName == altAttr || attrName == titleAttr)
    textChanged(element);
  else if (attrName == forAttr && isHTMLLabelElement(*element))
    labelChanged(element);
  else if (attrName == idAttr)
    updateTreeIfElementIdIsAriaOwned(element);

  if (!attrName.localName().startsWith("aria-"))
    return;

  if (attrName == aria_activedescendantAttr)
    handleActiveDescendantChanged(element);
  else if (attrName == aria_valuenowAttr || attrName == aria_valuetextAttr)
    postNotification(element, AXObjectCacheImpl::AXValueChanged);
  else if (attrName == aria_labelAttr || attrName == aria_labeledbyAttr ||
           attrName == aria_labelledbyAttr)
    textChanged(element);
  else if (attrName == aria_checkedAttr)
    checkedStateChanged(element);
  else if (attrName == aria_selectedAttr)
    handleAriaSelectedChanged(element);
  else if (attrName == aria_expandedAttr)
    handleAriaExpandedChange(element);
  else if (attrName == aria_hiddenAttr)
    childrenChanged(element->parentNode());
  else if (attrName == aria_invalidAttr)
    postNotification(element, AXObjectCacheImpl::AXInvalidStatusChanged);
  else if (attrName == aria_ownsAttr)
    childrenChanged(element);
  else
    postNotification(element, AXObjectCacheImpl::AXAriaAttributeChanged);
}

void AXObjectCacheImpl::labelChanged(Element* element) {
  textChanged(toHTMLLabelElement(element)->control());
}

void AXObjectCacheImpl::inlineTextBoxesUpdated(LineLayoutItem lineLayoutItem) {
  if (!inlineTextBoxAccessibilityEnabled())
    return;

  LayoutObject* layoutObject =
      LineLayoutAPIShim::layoutObjectFrom(lineLayoutItem);

  // Only update if the accessibility object already exists and it's
  // not already marked as dirty.
  if (AXObject* obj = get(layoutObject)) {
    if (!obj->needsToUpdateChildren()) {
      obj->setNeedsToUpdateChildren();
      postNotification(layoutObject, AXChildrenChanged);
    }
  }
}

Settings* AXObjectCacheImpl::settings() {
  return m_document->settings();
}

bool AXObjectCacheImpl::accessibilityEnabled() {
  Settings* settings = this->settings();
  if (!settings)
    return false;
  return settings->getAccessibilityEnabled();
}

bool AXObjectCacheImpl::inlineTextBoxAccessibilityEnabled() {
  Settings* settings = this->settings();
  if (!settings)
    return false;
  return settings->getInlineTextBoxAccessibilityEnabled();
}

const Element* AXObjectCacheImpl::rootAXEditableElement(const Node* node) {
  const Element* result = rootEditableElement(*node);
  const Element* element =
      node->isElementNode() ? toElement(node) : node->parentElement();

  for (; element; element = element->parentElement()) {
    if (nodeIsTextControl(element))
      result = element;
  }

  return result;
}

AXObject* AXObjectCacheImpl::firstAccessibleObjectFromNode(const Node* node) {
  if (!node)
    return 0;

  AXObject* accessibleObject = getOrCreate(node->layoutObject());
  while (accessibleObject && accessibleObject->accessibilityIsIgnored()) {
    node = NodeTraversal::next(*node);

    while (node && !node->layoutObject())
      node = NodeTraversal::nextSkippingChildren(*node);

    if (!node)
      return 0;

    accessibleObject = getOrCreate(node->layoutObject());
  }

  return accessibleObject;
}

bool AXObjectCacheImpl::nodeIsTextControl(const Node* node) {
  if (!node)
    return false;

  const AXObject* axObject = getOrCreate(const_cast<Node*>(node));
  return axObject && axObject->isTextControl();
}

bool isNodeAriaVisible(Node* node) {
  if (!node)
    return false;

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

  return equalIgnoringCase(toElement(node)->getAttribute(aria_hiddenAttr),
                           "false");
}

void AXObjectCacheImpl::postPlatformNotification(AXObject* obj,
                                                 AXNotification notification) {
  if (!obj || !obj->getDocument() || !obj->documentFrameView() ||
      !obj->documentFrameView()->frame().page())
    return;

  ChromeClient& client =
      obj->getDocument()->axObjectCacheOwner().page()->chromeClient();
  client.postAccessibilityNotification(obj, notification);
}

void AXObjectCacheImpl::handleFocusedUIElementChanged(Node* oldFocusedNode,
                                                      Node* newFocusedNode) {
  if (!newFocusedNode)
    return;

  Page* page = newFocusedNode->document().page();
  if (!page)
    return;

  AXObject* focusedObject = this->focusedObject();
  if (!focusedObject)
    return;

  AXObject* oldFocusedObject = get(oldFocusedNode);

  postPlatformNotification(oldFocusedObject, AXBlur);
  postPlatformNotification(focusedObject, AXFocusedUIElementChanged);
}

void AXObjectCacheImpl::handleInitialFocus() {
  postNotification(m_document, AXObjectCache::AXFocusedUIElementChanged);
}

void AXObjectCacheImpl::handleEditableTextContentChanged(Node* node) {
  AXObject* obj = get(node);
  while (obj && !obj->isNativeTextControl() && !obj->isNonNativeTextControl())
    obj = obj->parentObject();
  postNotification(obj, AXObjectCache::AXValueChanged);
}

void AXObjectCacheImpl::handleTextFormControlChanged(Node* node) {
  handleEditableTextContentChanged(node);
}

void AXObjectCacheImpl::handleValueChanged(Node* node) {
  postNotification(node, AXObjectCache::AXValueChanged);
}

void AXObjectCacheImpl::handleUpdateActiveMenuOption(LayoutMenuList* menuList,
                                                     int optionIndex) {
  AXObject* obj = get(menuList);
  if (!obj || !obj->isMenuList())
    return;

  toAXMenuList(obj)->didUpdateActiveOption(optionIndex);
}

void AXObjectCacheImpl::didShowMenuListPopup(LayoutMenuList* menuList) {
  AXObject* obj = get(menuList);
  if (!obj || !obj->isMenuList())
    return;

  toAXMenuList(obj)->didShowPopup();
}

void AXObjectCacheImpl::didHideMenuListPopup(LayoutMenuList* menuList) {
  AXObject* obj = get(menuList);
  if (!obj || !obj->isMenuList())
    return;

  toAXMenuList(obj)->didHidePopup();
}

void AXObjectCacheImpl::handleLoadComplete(Document* document) {
  postNotification(getOrCreate(document), AXObjectCache::AXLoadComplete);
}

void AXObjectCacheImpl::handleLayoutComplete(Document* document) {
  postNotification(getOrCreate(document), AXObjectCache::AXLayoutComplete);
}

void AXObjectCacheImpl::handleScrolledToAnchor(const Node* anchorNode) {
  // The anchor node may not be accessible. Post the notification for the
  // first accessible object.
  postPlatformNotification(firstAccessibleObjectFromNode(anchorNode),
                           AXScrolledToAnchor);
}

void AXObjectCacheImpl::handleScrollPositionChanged(FrameView* frameView) {
  AXObject* targetAXObject = getOrCreate(frameView->frame().document());
  postPlatformNotification(targetAXObject, AXScrollPositionChanged);
}

void AXObjectCacheImpl::handleScrollPositionChanged(
    LayoutObject* layoutObject) {
  postPlatformNotification(getOrCreate(layoutObject), AXScrollPositionChanged);
}

const AtomicString& AXObjectCacheImpl::computedRoleForNode(Node* node) {
  AXObject* obj = getOrCreate(node);
  if (!obj)
    return AXObject::roleName(UnknownRole);
  return AXObject::roleName(obj->roleValue());
}

String AXObjectCacheImpl::computedNameForNode(Node* node) {
  AXObject* obj = getOrCreate(node);
  if (!obj)
    return "";

  return obj->computedName();
}

void AXObjectCacheImpl::onTouchAccessibilityHover(const IntPoint& location) {
  AXObject* hit = root()->accessibilityHitTest(location);
  if (hit) {
    // Ignore events on a frame or plug-in, because the touch events
    // will be re-targeted there and we don't want to fire duplicate
    // accessibility events.
    if (hit->getLayoutObject() && hit->getLayoutObject()->isLayoutPart())
      return;

    postPlatformNotification(hit, AXHover);
  }
}

void AXObjectCacheImpl::setCanvasObjectBounds(HTMLCanvasElement* canvas,
                                              Element* element,
                                              const LayoutRect& rect) {
  AXObject* obj = getOrCreate(element);
  if (!obj)
    return;

  AXObject* axCanvas = getOrCreate(canvas);
  if (!axCanvas)
    return;

  obj->setElementRect(rect, axCanvas);
}

DEFINE_TRACE(AXObjectCacheImpl) {
  visitor->trace(m_document);
  visitor->trace(m_nodeObjectMapping);

  visitor->trace(m_objects);
  visitor->trace(m_notificationsToPost);

  AXObjectCache::trace(visitor);
}

}  // namespace blink
