// 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 "content/renderer/accessibility/blink_ax_tree_source.h"

#include <stddef.h>

#include <set>

#include "base/memory/ptr_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "content/common/accessibility_messages.h"
#include "content/renderer/accessibility/blink_ax_enum_conversion.h"
#include "content/renderer/accessibility/render_accessibility_impl.h"
#include "content/renderer/browser_plugin/browser_plugin.h"
#include "content/renderer/render_frame_impl.h"
#include "content/renderer/render_frame_proxy.h"
#include "content/renderer/render_view_impl.h"
#include "content/renderer/web_frame_utils.h"
#include "third_party/WebKit/public/platform/WebFloatRect.h"
#include "third_party/WebKit/public/platform/WebRect.h"
#include "third_party/WebKit/public/platform/WebSize.h"
#include "third_party/WebKit/public/platform/WebString.h"
#include "third_party/WebKit/public/platform/WebVector.h"
#include "third_party/WebKit/public/web/WebAXEnums.h"
#include "third_party/WebKit/public/web/WebAXObject.h"
#include "third_party/WebKit/public/web/WebDocument.h"
#include "third_party/WebKit/public/web/WebElement.h"
#include "third_party/WebKit/public/web/WebFormControlElement.h"
#include "third_party/WebKit/public/web/WebFrame.h"
#include "third_party/WebKit/public/web/WebLocalFrame.h"
#include "third_party/WebKit/public/web/WebNode.h"
#include "third_party/WebKit/public/web/WebPlugin.h"
#include "third_party/WebKit/public/web/WebPluginContainer.h"
#include "third_party/WebKit/public/web/WebView.h"

using base::ASCIIToUTF16;
using base::UTF16ToUTF8;
using blink::WebAXObject;
using blink::WebDocument;
using blink::WebElement;
using blink::WebFloatRect;
using blink::WebFrame;
using blink::WebLocalFrame;
using blink::WebNode;
using blink::WebPlugin;
using blink::WebPluginContainer;
using blink::WebVector;
using blink::WebView;

namespace content {

namespace {

void AddIntListAttributeFromWebObjects(ui::AXIntListAttribute attr,
                                       const WebVector<WebAXObject>& objects,
                                       AXContentNodeData* dst) {
  std::vector<int32_t> ids;
  for (size_t i = 0; i < objects.size(); i++)
    ids.push_back(objects[i].axID());
  if (!ids.empty())
    dst->AddIntListAttribute(attr, ids);
}

class AXContentNodeDataSparseAttributeAdapter
    : public blink::WebAXSparseAttributeClient {
 public:
  AXContentNodeDataSparseAttributeAdapter(AXContentNodeData* dst) : dst_(dst) {
    DCHECK(dst_);
  }
  ~AXContentNodeDataSparseAttributeAdapter() override {}

 private:
  AXContentNodeData* dst_;

  void addBoolAttribute(blink::WebAXBoolAttribute attribute,
                        bool value) override {
    NOTREACHED();
  }

  void addStringAttribute(blink::WebAXStringAttribute attribute,
                          const blink::WebString& value) override {
    switch (attribute) {
      case blink::WebAXStringAttribute::AriaKeyShortcuts:
        // TODO(dmazzoni): implement aria-keyshortcuts. http://crbug.com/644766
        break;
      case blink::WebAXStringAttribute::AriaRoleDescription:
        // TODO(dmazzoni): implement aria-roledescription.
        // http://crbug.com/644766
        break;
      default:
        NOTREACHED();
    }
  }

  void addObjectAttribute(blink::WebAXObjectAttribute attribute,
                          const blink::WebAXObject& value) override {
    switch (attribute) {
      case blink::WebAXObjectAttribute::AriaActiveDescendant:
        dst_->AddIntAttribute(ui::AX_ATTR_ACTIVEDESCENDANT_ID, value.axID());
        break;
      case blink::WebAXObjectAttribute::AriaErrorMessage:
        // TODO(dmazzoni): implement aria-errormessage.
        // http://crbug.com/644766
        break;
      default:
        NOTREACHED();
    }
  }

  void addObjectVectorAttribute(
      blink::WebAXObjectVectorAttribute attribute,
      const blink::WebVector<WebAXObject>& value) override {
    switch (attribute) {
      case blink::WebAXObjectVectorAttribute::AriaControls:
        AddIntListAttributeFromWebObjects(ui::AX_ATTR_CONTROLS_IDS, value,
                                          dst_);
        break;
      case blink::WebAXObjectVectorAttribute::AriaDetails:
        // TODO(dmazzoni): implement aria-details. http://crbug.com/644766
        break;
      case blink::WebAXObjectVectorAttribute::AriaFlowTo:
        AddIntListAttributeFromWebObjects(ui::AX_ATTR_FLOWTO_IDS, value, dst_);
        break;
      default:
        NOTREACHED();
    }
  }
};

WebAXObject ParentObjectUnignored(WebAXObject child) {
  WebAXObject parent = child.parentObject();
  while (!parent.isDetached() && parent.accessibilityIsIgnored())
    parent = parent.parentObject();
  return parent;
}

// Returns true if |ancestor| is the first unignored parent of |child|,
// which means that when walking up the parent chain from |child|,
// |ancestor| is the *first* ancestor that isn't marked as
// accessibilityIsIgnored().
bool IsParentUnignoredOf(WebAXObject ancestor,
                         WebAXObject child) {
  WebAXObject parent = ParentObjectUnignored(child);
  return parent.equals(ancestor);
}

std::string GetEquivalentAriaRoleString(const ui::AXRole role) {
  switch (role) {
    case ui::AX_ROLE_ARTICLE:
      return "article";
    case ui::AX_ROLE_BANNER:
      return "banner";
    case ui::AX_ROLE_BUTTON:
      return "button";
    case ui::AX_ROLE_COMPLEMENTARY:
      return "complementary";
    case ui::AX_ROLE_FIGURE:
      return "figure";
    case ui::AX_ROLE_FOOTER:
      return "contentinfo";
    case ui::AX_ROLE_HEADING:
      return "heading";
    case ui::AX_ROLE_IMAGE:
      return "img";
    case ui::AX_ROLE_MAIN:
      return "main";
    case ui::AX_ROLE_NAVIGATION:
      return "navigation";
    case ui::AX_ROLE_RADIO_BUTTON:
      return "radio";
    case ui::AX_ROLE_REGION:
      return "region";
    case ui::AX_ROLE_SLIDER:
      return "slider";
    case ui::AX_ROLE_TIME:
      return "time";
    default:
      break;
  }

  return std::string();
}

}  // namespace

ScopedFreezeBlinkAXTreeSource::ScopedFreezeBlinkAXTreeSource(
    BlinkAXTreeSource* tree_source)
    : tree_source_(tree_source) {
  tree_source_->Freeze();
}

ScopedFreezeBlinkAXTreeSource::~ScopedFreezeBlinkAXTreeSource() {
  tree_source_->Thaw();
}

BlinkAXTreeSource::BlinkAXTreeSource(RenderFrameImpl* render_frame,
                                     AccessibilityMode mode)
    : render_frame_(render_frame),
      accessibility_mode_(mode),
      frozen_(false) {}

BlinkAXTreeSource::~BlinkAXTreeSource() {
}

void BlinkAXTreeSource::Freeze() {
  CHECK(!frozen_);
  frozen_ = true;

  if (render_frame_ && render_frame_->GetWebFrame())
    document_ = render_frame_->GetWebFrame()->document();
  else
    document_ = WebDocument();

  root_ = ComputeRoot();

  if (!document_.isNull())
    focus_ = document_.focusedAccessibilityObject();
  else
    focus_ = WebAXObject();
}

void BlinkAXTreeSource::Thaw() {
  CHECK(frozen_);
  frozen_ = false;
}

void BlinkAXTreeSource::SetRoot(blink::WebAXObject root) {
  CHECK(!frozen_);
  explicit_root_ = root;
}

bool BlinkAXTreeSource::IsInTree(blink::WebAXObject node) const {
  CHECK(frozen_);
  while (IsValid(node)) {
    if (node.equals(root()))
      return true;
    node = GetParent(node);
  }
  return false;
}

bool BlinkAXTreeSource::GetTreeData(AXContentTreeData* tree_data) const {
  CHECK(frozen_);
  tree_data->doctype = "html";
  tree_data->loaded = root().isLoaded();
  tree_data->loading_progress = root().estimatedLoadingProgress();
  tree_data->mimetype =
      document().isXHTMLDocument() ? "text/xhtml" : "text/html";
  tree_data->title = document().title().utf8();
  tree_data->url = document().url().string().utf8();

  if (!focus().isNull())
    tree_data->focus_id = focus().axID();

  WebAXObject anchor_object, focus_object;
  int anchor_offset, focus_offset;
  blink::WebAXTextAffinity anchor_affinity, focus_affinity;
  root().selection(anchor_object, anchor_offset, anchor_affinity, focus_object,
                   focus_offset, focus_affinity);
  if (!anchor_object.isNull() && !focus_object.isNull() &&
      anchor_offset >= 0 && focus_offset >= 0) {
    int32_t anchor_id = anchor_object.axID();
    int32_t focus_id = focus_object.axID();
    tree_data->sel_anchor_object_id = anchor_id;
    tree_data->sel_anchor_offset = anchor_offset;
    tree_data->sel_focus_object_id = focus_id;
    tree_data->sel_focus_offset = focus_offset;
    tree_data->sel_anchor_affinity = AXTextAffinityFromBlink(anchor_affinity);
    tree_data->sel_focus_affinity = AXTextAffinityFromBlink(focus_affinity);
  }

  // Get the tree ID for this frame and the parent frame.
  WebLocalFrame* web_frame = document().frame();
  if (web_frame) {
    RenderFrame* render_frame = RenderFrame::FromWebFrame(web_frame);
    tree_data->routing_id = render_frame->GetRoutingID();

    // Get the tree ID for the parent frame.
    blink::WebFrame* parent_web_frame = web_frame->parent();
    if (parent_web_frame) {
      tree_data->parent_routing_id =
          GetRoutingIdForFrameOrProxy(parent_web_frame);
    }
  }

  return true;
}

blink::WebAXObject BlinkAXTreeSource::GetRoot() const {
  if (frozen_)
    return root_;
  else
    return ComputeRoot();
}

blink::WebAXObject BlinkAXTreeSource::GetFromId(int32_t id) const {
  return GetMainDocument().accessibilityObjectFromID(id);
}

int32_t BlinkAXTreeSource::GetId(blink::WebAXObject node) const {
  return node.axID();
}

void BlinkAXTreeSource::GetChildren(
    blink::WebAXObject parent,
    std::vector<blink::WebAXObject>* out_children) const {
  CHECK(frozen_);

  if (parent.role() == blink::WebAXRoleStaticText) {
    int32_t focus_id = focus().axID();
    blink::WebAXObject ancestor = parent;
    while (!ancestor.isDetached()) {
      if (ancestor.axID() == accessibility_focus_id_ ||
          (ancestor.axID() == focus_id && ancestor.isEditable())) {
        parent.loadInlineTextBoxes();
        break;
      }
      ancestor = ancestor.parentObject();
    }
  }

  bool is_iframe = false;
  WebNode node = parent.node();
  if (!node.isNull() && node.isElementNode())
    is_iframe = node.to<WebElement>().hasHTMLTagName("iframe");

  for (unsigned i = 0; i < parent.childCount(); i++) {
    blink::WebAXObject child = parent.childAt(i);

    // The child may be invalid due to issues in blink accessibility code.
    if (child.isDetached())
      continue;

    // Skip children whose parent isn't |parent|.
    // As an exception, include children of an iframe element.
    if (!is_iframe && !IsParentUnignoredOf(parent, child))
      continue;

    out_children->push_back(child);
  }
}

blink::WebAXObject BlinkAXTreeSource::GetParent(
    blink::WebAXObject node) const {
  CHECK(frozen_);

  // Blink returns ignored objects when walking up the parent chain,
  // we have to skip those here. Also, stop when we get to the root
  // element.
  do {
    if (node.equals(root()))
      return blink::WebAXObject();
    node = node.parentObject();
  } while (!node.isDetached() && node.accessibilityIsIgnored());

  return node;
}

bool BlinkAXTreeSource::IsValid(blink::WebAXObject node) const {
  return !node.isDetached();  // This also checks if it's null.
}

bool BlinkAXTreeSource::IsEqual(blink::WebAXObject node1,
                                blink::WebAXObject node2) const {
  return node1.equals(node2);
}

blink::WebAXObject BlinkAXTreeSource::GetNull() const {
  return blink::WebAXObject();
}

void BlinkAXTreeSource::SerializeNode(blink::WebAXObject src,
                                      AXContentNodeData* dst) const {
  dst->role = AXRoleFromBlink(src.role());
  dst->state = AXStateFromBlink(src);
  dst->id = src.axID();

  WebAXObject offset_container;
  WebFloatRect bounds_in_container;
  SkMatrix44 container_transform;
  src.getRelativeBounds(
      offset_container, bounds_in_container, container_transform);
  dst->location = bounds_in_container;
  if (!container_transform.isIdentity())
    dst->transform = base::WrapUnique(new gfx::Transform(container_transform));
  if (!offset_container.isDetached())
    dst->offset_container_id = offset_container.axID();

  AXContentNodeDataSparseAttributeAdapter sparse_attribute_adapter(dst);
  src.getSparseAXAttributes(sparse_attribute_adapter);

  blink::WebAXNameFrom nameFrom;
  blink::WebVector<blink::WebAXObject> nameObjects;
  blink::WebString web_name = src.name(nameFrom, nameObjects);
  if (!web_name.isEmpty()) {
    dst->AddStringAttribute(ui::AX_ATTR_NAME, web_name.utf8());
    dst->AddIntAttribute(ui::AX_ATTR_NAME_FROM, AXNameFromFromBlink(nameFrom));
    AddIntListAttributeFromWebObjects(
        ui::AX_ATTR_LABELLEDBY_IDS, nameObjects, dst);
  }

  blink::WebAXDescriptionFrom descriptionFrom;
  blink::WebVector<blink::WebAXObject> descriptionObjects;
  blink::WebString web_description = src.description(
      nameFrom, descriptionFrom, descriptionObjects);
  if (!web_description.isEmpty()) {
    dst->AddStringAttribute(ui::AX_ATTR_DESCRIPTION, web_description.utf8());
    dst->AddIntAttribute(ui::AX_ATTR_DESCRIPTION_FROM,
        AXDescriptionFromFromBlink(descriptionFrom));
    AddIntListAttributeFromWebObjects(
        ui::AX_ATTR_DESCRIBEDBY_IDS, descriptionObjects, dst);
  }

  std::string value;
  if (src.valueDescription().length()) {
    dst->AddStringAttribute(ui::AX_ATTR_VALUE, src.valueDescription().utf8());
  } else {
    dst->AddStringAttribute(ui::AX_ATTR_VALUE, src.stringValue().utf8());
  }

  if (src.isButtonStateMixed())
    dst->AddBoolAttribute(ui::AX_ATTR_STATE_MIXED, true);

  if (src.canSetValueAttribute())
    dst->AddBoolAttribute(ui::AX_ATTR_CAN_SET_VALUE, true);

  if (!src.url().isEmpty())
    dst->AddStringAttribute(ui::AX_ATTR_URL, src.url().string().utf8());

  // The following set of attributes are only accessed when the accessibility
  // mode is set to screen reader mode, otherwise only the more basic
  // attributes are populated.
  if (accessibility_mode_ & ACCESSIBILITY_MODE_FLAG_SCREEN_READER) {
    blink::WebString web_placeholder = src.placeholder(nameFrom);
    if (!web_placeholder.isEmpty())
      dst->AddStringAttribute(ui::AX_ATTR_PLACEHOLDER, web_placeholder.utf8());

    if (dst->role == ui::AX_ROLE_COLOR_WELL)
      dst->AddIntAttribute(ui::AX_ATTR_COLOR_VALUE, src.colorValue());

    // Text attributes.
    if (src.backgroundColor())
      dst->AddIntAttribute(ui::AX_ATTR_BACKGROUND_COLOR, src.backgroundColor());

    if (src.color())
      dst->AddIntAttribute(ui::AX_ATTR_COLOR, src.color());

    WebAXObject parent = ParentObjectUnignored(src);
    if (src.fontFamily().length()) {
      if (parent.isNull() || parent.fontFamily() != src.fontFamily())
        dst->AddStringAttribute(ui::AX_ATTR_FONT_FAMILY,
                                src.fontFamily().utf8());
    }

    // Font size is in pixels.
    if (src.fontSize())
      dst->AddFloatAttribute(ui::AX_ATTR_FONT_SIZE, src.fontSize());

    if (src.ariaCurrentState()) {
      dst->AddIntAttribute(ui::AX_ATTR_ARIA_CURRENT_STATE,
                           AXAriaCurrentStateFromBlink(src.ariaCurrentState()));
    }

    if (src.invalidState()) {
      dst->AddIntAttribute(ui::AX_ATTR_INVALID_STATE,
                           AXInvalidStateFromBlink(src.invalidState()));
    }
    if (src.invalidState() == blink::WebAXInvalidStateOther &&
        src.ariaInvalidValue().length()) {
      dst->AddStringAttribute(
          ui::AX_ATTR_ARIA_INVALID_VALUE, src.ariaInvalidValue().utf8());
    }

    if (src.textDirection()) {
      dst->AddIntAttribute(ui::AX_ATTR_TEXT_DIRECTION,
                           AXTextDirectionFromBlink(src.textDirection()));
    }

    if (src.textStyle()) {
      dst->AddIntAttribute(ui::AX_ATTR_TEXT_STYLE,
                           AXTextStyleFromBlink(src.textStyle()));
    }

    if (dst->role == ui::AX_ROLE_INLINE_TEXT_BOX) {
      WebVector<int> src_character_offsets;
      src.characterOffsets(src_character_offsets);
      std::vector<int32_t> character_offsets;
      character_offsets.reserve(src_character_offsets.size());
      for (size_t i = 0; i < src_character_offsets.size(); ++i)
        character_offsets.push_back(src_character_offsets[i]);
      dst->AddIntListAttribute(ui::AX_ATTR_CHARACTER_OFFSETS,
                               character_offsets);

      WebVector<int> src_word_starts;
      WebVector<int> src_word_ends;
      src.wordBoundaries(src_word_starts, src_word_ends);
      std::vector<int32_t> word_starts;
      std::vector<int32_t> word_ends;
      word_starts.reserve(src_word_starts.size());
      word_ends.reserve(src_word_starts.size());
      for (size_t i = 0; i < src_word_starts.size(); ++i) {
        word_starts.push_back(src_word_starts[i]);
        word_ends.push_back(src_word_ends[i]);
      }
      dst->AddIntListAttribute(ui::AX_ATTR_WORD_STARTS, word_starts);
      dst->AddIntListAttribute(ui::AX_ATTR_WORD_ENDS, word_ends);
    }

    if (src.accessKey().length()) {
      dst->AddStringAttribute(ui::AX_ATTR_ACCESS_KEY, src.accessKey().utf8());
    }

    if (src.ariaAutoComplete().length()) {
      dst->AddStringAttribute(
          ui::AX_ATTR_AUTO_COMPLETE,
          src.ariaAutoComplete().utf8());
    }

    if (src.action() != blink::WebAXSupportedAction::None) {
      dst->AddIntAttribute(ui::AX_ATTR_ACTION,
                           AXSupportedActionFromBlink(src.action()));
    }

    if (src.isAriaReadOnly())
      dst->AddBoolAttribute(ui::AX_ATTR_ARIA_READONLY, true);

    if (src.hasComputedStyle()) {
      dst->AddStringAttribute(
          ui::AX_ATTR_DISPLAY, src.computedStyleDisplay().utf8());
    }

    if (src.language().length()) {
      if (parent.isNull() || parent.language() != src.language())
        dst->AddStringAttribute(ui::AX_ATTR_LANGUAGE, src.language().utf8());
    }

    if (src.keyboardShortcut().length()) {
      dst->AddStringAttribute(
          ui::AX_ATTR_SHORTCUT,
          src.keyboardShortcut().utf8());
    }

    if (!src.nextOnLine().isDetached()) {
      dst->AddIntAttribute(ui::AX_ATTR_NEXT_ON_LINE_ID,
                           src.nextOnLine().axID());
    }

    if (!src.previousOnLine().isDetached()) {
      dst->AddIntAttribute(ui::AX_ATTR_PREVIOUS_ON_LINE_ID,
                           src.previousOnLine().axID());
    }

    if (!src.ariaActiveDescendant().isDetached()) {
      dst->AddIntAttribute(ui::AX_ATTR_ACTIVEDESCENDANT_ID,
                           src.ariaActiveDescendant().axID());
    }

    if (dst->role == ui::AX_ROLE_HEADING && src.headingLevel()) {
      dst->AddIntAttribute(ui::AX_ATTR_HIERARCHICAL_LEVEL, src.headingLevel());
    } else if ((dst->role == ui::AX_ROLE_TREE_ITEM ||
                dst->role == ui::AX_ROLE_ROW) &&
               src.hierarchicalLevel()) {
      dst->AddIntAttribute(ui::AX_ATTR_HIERARCHICAL_LEVEL,
                           src.hierarchicalLevel());
    }

    if (src.setSize())
      dst->AddIntAttribute(ui::AX_ATTR_SET_SIZE, src.setSize());

    if (src.posInSet())
      dst->AddIntAttribute(ui::AX_ATTR_POS_IN_SET, src.posInSet());

    if (src.canvasHasFallbackContent())
      dst->AddBoolAttribute(ui::AX_ATTR_CANVAS_HAS_FALLBACK, true);

    // Spelling, grammar and other document markers.
    WebVector<blink::WebAXMarkerType> src_marker_types;
    WebVector<int> src_marker_starts;
    WebVector<int> src_marker_ends;
    src.markers(src_marker_types, src_marker_starts, src_marker_ends);
    DCHECK_EQ(src_marker_types.size(), src_marker_starts.size());
    DCHECK_EQ(src_marker_starts.size(), src_marker_ends.size());

    if (src_marker_types.size()) {
      std::vector<int32_t> marker_types;
      std::vector<int32_t> marker_starts;
      std::vector<int32_t> marker_ends;
      marker_types.reserve(src_marker_types.size());
      marker_starts.reserve(src_marker_starts.size());
      marker_ends.reserve(src_marker_ends.size());
      for (size_t i = 0; i < src_marker_types.size(); ++i) {
        marker_types.push_back(
            static_cast<int32_t>(AXMarkerTypeFromBlink(src_marker_types[i])));
        marker_starts.push_back(src_marker_starts[i]);
        marker_ends.push_back(src_marker_ends[i]);
      }
      dst->AddIntListAttribute(ui::AX_ATTR_MARKER_TYPES, marker_types);
      dst->AddIntListAttribute(ui::AX_ATTR_MARKER_STARTS, marker_starts);
      dst->AddIntListAttribute(ui::AX_ATTR_MARKER_ENDS, marker_ends);
    }

    if (src.isInLiveRegion()) {
      dst->AddBoolAttribute(ui::AX_ATTR_LIVE_ATOMIC, src.liveRegionAtomic());
      dst->AddBoolAttribute(ui::AX_ATTR_LIVE_BUSY, src.liveRegionBusy());
      if (src.liveRegionBusy())
        dst->state |= (1 << ui::AX_STATE_BUSY);
      if (!src.liveRegionStatus().isEmpty()) {
        dst->AddStringAttribute(
            ui::AX_ATTR_LIVE_STATUS,
            src.liveRegionStatus().utf8());
      }
      dst->AddStringAttribute(
          ui::AX_ATTR_LIVE_RELEVANT,
          src.liveRegionRelevant().utf8());
      // If we are not at the root of an atomic live region.
      if (src.containerLiveRegionAtomic() &&
          !src.liveRegionRoot().isDetached() &&
          !src.liveRegionAtomic()) {
        dst->AddIntAttribute(ui::AX_ATTR_MEMBER_OF_ID,
                             src.liveRegionRoot().axID());
      }
      dst->AddBoolAttribute(ui::AX_ATTR_CONTAINER_LIVE_ATOMIC,
                            src.containerLiveRegionAtomic());
      dst->AddBoolAttribute(ui::AX_ATTR_CONTAINER_LIVE_BUSY,
                            src.containerLiveRegionBusy());
      dst->AddStringAttribute(
          ui::AX_ATTR_CONTAINER_LIVE_STATUS,
          src.containerLiveRegionStatus().utf8());
      dst->AddStringAttribute(
          ui::AX_ATTR_CONTAINER_LIVE_RELEVANT,
          src.containerLiveRegionRelevant().utf8());
    }

    if (dst->role == ui::AX_ROLE_PROGRESS_INDICATOR ||
        dst->role == ui::AX_ROLE_METER ||
        dst->role == ui::AX_ROLE_SCROLL_BAR ||
        dst->role == ui::AX_ROLE_SLIDER ||
        dst->role == ui::AX_ROLE_SPIN_BUTTON) {
      dst->AddFloatAttribute(ui::AX_ATTR_VALUE_FOR_RANGE, src.valueForRange());
      dst->AddFloatAttribute(ui::AX_ATTR_MAX_VALUE_FOR_RANGE,
                             src.maxValueForRange());
      dst->AddFloatAttribute(ui::AX_ATTR_MIN_VALUE_FOR_RANGE,
                             src.minValueForRange());
    }

    if (dst->role == ui::AX_ROLE_ROOT_WEB_AREA)
      dst->AddStringAttribute(ui::AX_ATTR_HTML_TAG, "#document");

    if (dst->role == ui::AX_ROLE_TABLE) {
      int column_count = src.columnCount();
      int row_count = src.rowCount();
      if (column_count > 0 && row_count > 0) {
        std::set<int32_t> unique_cell_id_set;
        std::vector<int32_t> cell_ids;
        std::vector<int32_t> unique_cell_ids;
        dst->AddIntAttribute(ui::AX_ATTR_TABLE_COLUMN_COUNT, column_count);
        dst->AddIntAttribute(ui::AX_ATTR_TABLE_ROW_COUNT, row_count);
        WebAXObject header = src.headerContainerObject();
        if (!header.isDetached())
          dst->AddIntAttribute(ui::AX_ATTR_TABLE_HEADER_ID, header.axID());
        for (int i = 0; i < column_count * row_count; ++i) {
          WebAXObject cell = src.cellForColumnAndRow(
              i % column_count, i / column_count);
          int cell_id = -1;
          if (!cell.isDetached()) {
            cell_id = cell.axID();
            if (unique_cell_id_set.find(cell_id) == unique_cell_id_set.end()) {
              unique_cell_id_set.insert(cell_id);
              unique_cell_ids.push_back(cell_id);
            }
          }
          cell_ids.push_back(cell_id);
        }
        dst->AddIntListAttribute(ui::AX_ATTR_CELL_IDS, cell_ids);
        dst->AddIntListAttribute(ui::AX_ATTR_UNIQUE_CELL_IDS, unique_cell_ids);
      }
    }

    if (dst->role == ui::AX_ROLE_TABLE ||
        dst->role == ui::AX_ROLE_GRID ||
        dst->role == ui::AX_ROLE_TREE_GRID) {
      int aria_colcount = src.ariaColumnCount();
      if (aria_colcount)
        dst->AddIntAttribute(ui::AX_ATTR_ARIA_COL_COUNT, aria_colcount);

      int aria_rowcount = src.ariaRowCount();
      if (aria_rowcount)
        dst->AddIntAttribute(ui::AX_ATTR_ARIA_ROW_COUNT, aria_rowcount);
    }

    if (dst->role == ui::AX_ROLE_ROW) {
      dst->AddIntAttribute(ui::AX_ATTR_TABLE_ROW_INDEX, src.rowIndex());
      WebAXObject header = src.rowHeader();
      if (!header.isDetached())
        dst->AddIntAttribute(ui::AX_ATTR_TABLE_ROW_HEADER_ID, header.axID());
    }

    if (dst->role == ui::AX_ROLE_COLUMN) {
      dst->AddIntAttribute(ui::AX_ATTR_TABLE_COLUMN_INDEX, src.columnIndex());
      WebAXObject header = src.columnHeader();
      if (!header.isDetached())
        dst->AddIntAttribute(ui::AX_ATTR_TABLE_COLUMN_HEADER_ID, header.axID());
    }

    if (dst->role == ui::AX_ROLE_CELL ||
        dst->role == ui::AX_ROLE_ROW_HEADER ||
        dst->role == ui::AX_ROLE_COLUMN_HEADER ||
        dst->role == ui::AX_ROLE_ROW) {
      if (dst->role != ui::AX_ROLE_ROW) {
        dst->AddIntAttribute(ui::AX_ATTR_TABLE_CELL_COLUMN_INDEX,
                             src.cellColumnIndex());
        dst->AddIntAttribute(ui::AX_ATTR_TABLE_CELL_COLUMN_SPAN,
                             src.cellColumnSpan());
        dst->AddIntAttribute(ui::AX_ATTR_TABLE_CELL_ROW_INDEX,
                             src.cellRowIndex());
        dst->AddIntAttribute(ui::AX_ATTR_TABLE_CELL_ROW_SPAN,src.cellRowSpan());

        int aria_colindex = src.ariaColumnIndex();
        if (aria_colindex)
          dst->AddIntAttribute(ui::AX_ATTR_ARIA_COL_INDEX, aria_colindex);
      }

      int aria_rowindex = src.ariaRowIndex();
      if (aria_rowindex)
        dst->AddIntAttribute(ui::AX_ATTR_ARIA_ROW_INDEX, aria_rowindex);
    }

    if ((dst->role == ui::AX_ROLE_ROW_HEADER ||
         dst->role == ui::AX_ROLE_COLUMN_HEADER) && src.sortDirection()) {
      dst->AddIntAttribute(ui::AX_ATTR_SORT_DIRECTION,
                           AXSortDirectionFromBlink(src.sortDirection()));
    }
  }

  // The majority of the rest of this code computes attributes needed for
  // all modes, not just for screen readers.

  WebNode node = src.node();
  bool is_iframe = false;

  if (!node.isNull() && node.isElementNode()) {
    WebElement element = node.to<WebElement>();
    is_iframe = element.hasHTMLTagName("iframe");

    if (accessibility_mode_ & ACCESSIBILITY_MODE_FLAG_HTML) {
      // TODO(ctguil): The tagName in WebKit is lower cased but
      // HTMLElement::nodeName calls localNameUpper. Consider adding
      // a WebElement method that returns the original lower cased tagName.
      dst->AddStringAttribute(
          ui::AX_ATTR_HTML_TAG,
          base::ToLowerASCII(element.tagName().utf8()));
      for (unsigned i = 0; i < element.attributeCount(); ++i) {
        std::string name = base::ToLowerASCII(
            element.attributeLocalName(i).utf8());
        std::string value = element.attributeValue(i).utf8();
        dst->html_attributes.push_back(std::make_pair(name, value));
      }
    }

    if (src.isEditable()) {
      dst->AddIntAttribute(ui::AX_ATTR_TEXT_SEL_START, src.selectionStart());
      dst->AddIntAttribute(ui::AX_ATTR_TEXT_SEL_END, src.selectionEnd());

#if defined(OS_CHROMEOS)
      // This attribute will soon be deprecated; see crbug.com/669134.
      WebVector<int> src_line_breaks;
      src.lineBreaks(src_line_breaks);
      if (src_line_breaks.size()) {
        std::vector<int32_t> line_breaks;
        line_breaks.reserve(src_line_breaks.size());
        for (size_t i = 0; i < src_line_breaks.size(); ++i)
          line_breaks.push_back(src_line_breaks[i]);
        dst->AddIntListAttribute(ui::AX_ATTR_LINE_BREAKS, line_breaks);
      }
#endif  // defined OS_CHROMEOS
    }

    // ARIA role.
    if (element.hasAttribute("role")) {
      dst->AddStringAttribute(
          ui::AX_ATTR_ROLE,
          element.getAttribute("role").utf8());
    } else {
      std::string role = GetEquivalentAriaRoleString(dst->role);
      if (!role.empty())
        dst->AddStringAttribute(ui::AX_ATTR_ROLE, role);
    }

    // Browser plugin (used in a <webview>).
    BrowserPlugin* browser_plugin = BrowserPlugin::GetFromNode(element);
    if (browser_plugin) {
      dst->AddContentIntAttribute(
          AX_CONTENT_ATTR_CHILD_BROWSER_PLUGIN_INSTANCE_ID,
          browser_plugin->browser_plugin_instance_id());
    }

    // Frames and iframes.
    WebFrame* frame = WebFrame::fromFrameOwnerElement(element);
    if (frame) {
      dst->AddContentIntAttribute(
          AX_CONTENT_ATTR_CHILD_ROUTING_ID,
          GetRoutingIdForFrameOrProxy(frame));
    }
  }

  // Add the ids of *indirect* children - those who are children of this node,
  // but whose parent is *not* this node. One example is a table
  // cell, which is a child of both a row and a column. Because the cell's
  // parent is the row, the row adds it as a child, and the column adds it
  // as an indirect child.
  int child_count = src.childCount();
  for (int i = 0; i < child_count; ++i) {
    WebAXObject child = src.childAt(i);
    std::vector<int32_t> indirect_child_ids;
    if (!is_iframe && !child.isDetached() && !IsParentUnignoredOf(src, child))
      indirect_child_ids.push_back(child.axID());
    if (indirect_child_ids.size() > 0) {
      dst->AddIntListAttribute(
          ui::AX_ATTR_INDIRECT_CHILD_IDS, indirect_child_ids);
    }
  }

  if (src.isScrollableContainer()) {
    const gfx::Point& scrollOffset = src.getScrollOffset();
    dst->AddIntAttribute(ui::AX_ATTR_SCROLL_X, scrollOffset.x());
    dst->AddIntAttribute(ui::AX_ATTR_SCROLL_Y, scrollOffset.y());

    const gfx::Point& minScrollOffset = src.minimumScrollOffset();
    dst->AddIntAttribute(ui::AX_ATTR_SCROLL_X_MIN, minScrollOffset.x());
    dst->AddIntAttribute(ui::AX_ATTR_SCROLL_Y_MIN, minScrollOffset.y());

    const gfx::Point& maxScrollOffset = src.maximumScrollOffset();
    dst->AddIntAttribute(ui::AX_ATTR_SCROLL_X_MAX, maxScrollOffset.x());
    dst->AddIntAttribute(ui::AX_ATTR_SCROLL_Y_MAX, maxScrollOffset.y());
  }

  if (dst->id == image_data_node_id_) {
    dst->AddStringAttribute(ui::AX_ATTR_IMAGE_DATA_URL,
                            src.imageDataUrl(max_image_data_size_).utf8());
  }
}

blink::WebDocument BlinkAXTreeSource::GetMainDocument() const {
  CHECK(frozen_);
  return document_;
}

WebAXObject BlinkAXTreeSource::ComputeRoot() const {
  if (!explicit_root_.isNull())
    return explicit_root_;

  if (!render_frame_ || !render_frame_->GetWebFrame())
    return WebAXObject();

  WebDocument document = render_frame_->GetWebFrame()->document();
  if (!document.isNull())
    return document.accessibilityObject();

  return WebAXObject();
}

}  // namespace content
