15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/browser/accessibility/browser_accessibility.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
8868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string_number_conversions.h"
9868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string_util.h"
103551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "base/strings/utf_string_conversions.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/browser/accessibility/browser_accessibility_manager.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/common/accessibility_messages.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace content {
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if !defined(OS_MACOSX) && \
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    !defined(OS_WIN) && \
187d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    !defined(OS_ANDROID)
19a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch// We have subclassess of BrowserAccessibility on Mac and Win. For any other
20a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch// platform, instantiate the base class.
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BrowserAccessibility* BrowserAccessibility::Create() {
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return new BrowserAccessibility();
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BrowserAccessibility::BrowserAccessibility()
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : manager_(NULL),
290529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      node_(NULL) {
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BrowserAccessibility::~BrowserAccessibility() {
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
350529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochvoid BrowserAccessibility::Init(BrowserAccessibilityManager* manager,
360529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    ui::AXNode* node) {
370529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  manager_ = manager;
380529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  node_ = node;
390529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch}
400529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
410529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochvoid BrowserAccessibility::OnDataChanged() {
420529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  GetStringAttribute(ui::AX_ATTR_NAME, &name_);
430529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  GetStringAttribute(ui::AX_ATTR_VALUE, &value_);
440529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch}
450529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
460f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)bool BrowserAccessibility::PlatformIsLeaf() const {
47a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  if (InternalChildCount() == 0)
485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return true;
495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // All of these roles may have children that we use as internal
515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // implementation details, but we want to expose them as leaves
525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // to platform accessibility APIs.
53a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  switch (GetRole()) {
545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    case ui::AX_ROLE_EDITABLE_TEXT:
555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    case ui::AX_ROLE_SLIDER:
565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    case ui::AX_ROLE_STATIC_TEXT:
575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    case ui::AX_ROLE_TEXT_AREA:
585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    case ui::AX_ROLE_TEXT_FIELD:
595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      return true;
605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    default:
615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      return false;
625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
630f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)}
640f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)
650f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)uint32 BrowserAccessibility::PlatformChildCount() const {
66a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  return PlatformIsLeaf() ? 0 : InternalChildCount();
670f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)}
680f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool BrowserAccessibility::IsNative() const {
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool BrowserAccessibility::IsDescendantOf(
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    BrowserAccessibility* ancestor) {
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (this == ancestor) {
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
77a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  } else if (GetParent()) {
78a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    return GetParent()->IsDescendantOf(ancestor);
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
840f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)BrowserAccessibility* BrowserAccessibility::PlatformGetChild(
850f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    uint32 child_index) const {
86a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  DCHECK(child_index < InternalChildCount());
871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  BrowserAccessibility* result = InternalGetChild(child_index);
881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (result->HasBoolAttribute(ui::AX_ATTR_IS_AX_TREE_HOST)) {
901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    BrowserAccessibilityManager* child_manager =
911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        manager_->delegate()->AccessibilityGetChildFrame(result->GetId());
921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if (child_manager)
931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      result = child_manager->GetRoot();
941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return result;
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BrowserAccessibility* BrowserAccessibility::GetPreviousSibling() {
100a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  if (GetParent() && GetIndexInParent() > 0)
101a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    return GetParent()->InternalGetChild(GetIndexInParent() - 1);
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return NULL;
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BrowserAccessibility* BrowserAccessibility::GetNextSibling() {
107a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  if (GetParent() &&
108a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      GetIndexInParent() >= 0 &&
109a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      GetIndexInParent() < static_cast<int>(
110a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch          GetParent()->InternalChildCount() - 1)) {
111a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    return GetParent()->InternalGetChild(GetIndexInParent() + 1);
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return NULL;
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1170529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochuint32 BrowserAccessibility::InternalChildCount() const {
1180529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  if (!node_ || !manager_)
1190529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    return 0;
1200529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  return static_cast<uint32>(node_->child_count());
1210529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch}
1220529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
1230529e5d033099cbfc42635f6f6183833b09dff6eBen MurdochBrowserAccessibility* BrowserAccessibility::InternalGetChild(
1240529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    uint32 child_index) const {
1250529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  if (!node_ || !manager_)
1260529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    return NULL;
1270529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  return manager_->GetFromAXNode(node_->children()[child_index]);
1280529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch}
1290529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
1300529e5d033099cbfc42635f6f6183833b09dff6eBen MurdochBrowserAccessibility* BrowserAccessibility::GetParent() const {
1310529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  if (!node_ || !manager_)
1320529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    return NULL;
1330529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  ui::AXNode* parent = node_->parent();
1341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (parent)
1351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return manager_->GetFromAXNode(parent);
1361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (!manager_->delegate())
1381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return NULL;
1391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  BrowserAccessibility* host_node =
1411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      manager_->delegate()->AccessibilityGetParentFrame();
1421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (!host_node)
1431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return NULL;
1441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return host_node->GetParent();
1460529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch}
1470529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
1480529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochint32 BrowserAccessibility::GetIndexInParent() const {
1490529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  return node_ ? node_->index_in_parent() : -1;
1500529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch}
1510529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
1520529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochint32 BrowserAccessibility::GetId() const {
1530529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  return node_ ? node_->id() : -1;
1540529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch}
1550529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
1560529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochconst ui::AXNodeData& BrowserAccessibility::GetData() const {
1570529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  CR_DEFINE_STATIC_LOCAL(ui::AXNodeData, empty_data, ());
1580529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  if (node_)
1590529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    return node_->data();
1600529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  else
1610529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    return empty_data;
1620529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch}
1630529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
1640529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochgfx::Rect BrowserAccessibility::GetLocation() const {
1650529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  return GetData().location;
1660529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch}
1670529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
1680529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochint32 BrowserAccessibility::GetRole() const {
1690529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  return GetData().role;
1700529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch}
1710529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
1720529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochint32 BrowserAccessibility::GetState() const {
1730529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  return GetData().state;
1740529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch}
1750529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
1761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciconst BrowserAccessibility::HtmlAttributes&
1770529e5d033099cbfc42635f6f6183833b09dff6eBen MurdochBrowserAccessibility::GetHtmlAttributes() const {
1780529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  return GetData().html_attributes;
1790529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch}
1800529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
1817d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)gfx::Rect BrowserAccessibility::GetLocalBoundsRect() const {
182a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  gfx::Rect bounds = GetLocation();
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Walk up the parent chain. Every time we encounter a Web Area, offset
1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // based on the scroll bars and then offset based on the origin of that
1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // nested web area.
187a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  BrowserAccessibility* parent = GetParent();
1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool need_to_offset_web_area =
189a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      (GetRole() == ui::AX_ROLE_WEB_AREA ||
190a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch       GetRole() == ui::AX_ROLE_ROOT_WEB_AREA);
1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  while (parent) {
1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (need_to_offset_web_area &&
193a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch        parent->GetLocation().width() > 0 &&
194a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch        parent->GetLocation().height() > 0) {
195a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      bounds.Offset(parent->GetLocation().x(), parent->GetLocation().y());
1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      need_to_offset_web_area = false;
1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
1987d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
1997d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    // On some platforms, we don't want to take the root scroll offsets
2007d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    // into account.
201a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    if (parent->GetRole() == ui::AX_ROLE_ROOT_WEB_AREA &&
2027d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        !manager()->UseRootScrollOffsetsWhenComputingBounds()) {
2037d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      break;
2047d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    }
2057d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
206a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    if (parent->GetRole() == ui::AX_ROLE_WEB_AREA ||
207a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch        parent->GetRole() == ui::AX_ROLE_ROOT_WEB_AREA) {
2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      int sx = 0;
2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      int sy = 0;
2105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      if (parent->GetIntAttribute(ui::AX_ATTR_SCROLL_X, &sx) &&
2115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          parent->GetIntAttribute(ui::AX_ATTR_SCROLL_Y, &sy)) {
2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        bounds.Offset(-sx, -sy);
2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      need_to_offset_web_area = true;
2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
216a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    parent = parent->GetParent();
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return bounds;
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2227d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)gfx::Rect BrowserAccessibility::GetGlobalBoundsRect() const {
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Rect bounds = GetLocalBoundsRect();
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Adjust the bounds by the top left corner of the containing view's bounds
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // in screen coordinates.
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bounds.Offset(manager_->GetViewBounds().OffsetFromOrigin());
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return bounds;
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2320f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)gfx::Rect BrowserAccessibility::GetLocalBoundsForRange(int start, int len)
2330f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    const {
234a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  if (GetRole() != ui::AX_ROLE_STATIC_TEXT) {
2355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Apply recursively to all static text descendants. For example, if
2365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // you call it on a div with two text node children, it just calls
2375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // GetLocalBoundsForRange on each of the two children (adjusting
2385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // |start| for each one) and unions the resulting rects.
2395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    gfx::Rect bounds;
240a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    for (size_t i = 0; i < InternalChildCount(); ++i) {
241a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      BrowserAccessibility* child = InternalGetChild(i);
2425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      int child_len = child->GetStaticTextLenRecursive();
2435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      if (start < child_len && start + len > 0) {
2445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        gfx::Rect child_rect = child->GetLocalBoundsForRange(start, len);
2455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        bounds.Union(child_rect);
2465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      }
2475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      start -= child_len;
2485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
2495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return bounds;
2505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
2515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2520f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  int end = start + len;
2530f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  int child_start = 0;
2540f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  int child_end = 0;
2550f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)
2560f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  gfx::Rect bounds;
257a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  for (size_t i = 0; i < InternalChildCount() && child_end < start + len; ++i) {
258a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    BrowserAccessibility* child = InternalGetChild(i);
259a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    DCHECK_EQ(child->GetRole(), ui::AX_ROLE_INLINE_TEXT_BOX);
2600f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    std::string child_text;
2615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    child->GetStringAttribute(ui::AX_ATTR_VALUE, &child_text);
2620f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    int child_len = static_cast<int>(child_text.size());
2630f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    child_start = child_end;
2640f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    child_end += child_len;
2650f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)
2660f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    if (child_end < start)
2670f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)      continue;
2680f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)
2690f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    int overlap_start = std::max(start, child_start);
2700f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    int overlap_end = std::min(end, child_end);
2710f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)
2720f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    int local_start = overlap_start - child_start;
2730f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    int local_end = overlap_end - child_start;
2740f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)
275a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    gfx::Rect child_rect = child->GetLocation();
2760f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    int text_direction = child->GetIntAttribute(
2775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        ui::AX_ATTR_TEXT_DIRECTION);
2780f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    const std::vector<int32>& character_offsets = child->GetIntListAttribute(
2795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        ui::AX_ATTR_CHARACTER_OFFSETS);
2800f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    int start_pixel_offset =
2810f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)        local_start > 0 ? character_offsets[local_start - 1] : 0;
2820f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    int end_pixel_offset =
2830f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)        local_end > 0 ? character_offsets[local_end - 1] : 0;
2840f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)
2850f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    gfx::Rect child_overlap_rect;
2860f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    switch (text_direction) {
2875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      case ui::AX_TEXT_DIRECTION_NONE:
2885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      case ui::AX_TEXT_DIRECTION_LR: {
2890f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)        int left = child_rect.x() + start_pixel_offset;
2900f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)        int right = child_rect.x() + end_pixel_offset;
2910f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)        child_overlap_rect = gfx::Rect(left, child_rect.y(),
2920f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)                                       right - left, child_rect.height());
2930f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)        break;
2940f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)      }
2955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      case ui::AX_TEXT_DIRECTION_RL: {
2960f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)        int right = child_rect.right() - start_pixel_offset;
2970f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)        int left = child_rect.right() - end_pixel_offset;
2980f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)        child_overlap_rect = gfx::Rect(left, child_rect.y(),
2990f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)                                       right - left, child_rect.height());
3000f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)        break;
3010f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)      }
3025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      case ui::AX_TEXT_DIRECTION_TB: {
3030f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)        int top = child_rect.y() + start_pixel_offset;
3040f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)        int bottom = child_rect.y() + end_pixel_offset;
3050f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)        child_overlap_rect = gfx::Rect(child_rect.x(), top,
3060f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)                                       child_rect.width(), bottom - top);
3070f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)        break;
3080f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)      }
3095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      case ui::AX_TEXT_DIRECTION_BT: {
3100f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)        int bottom = child_rect.bottom() - start_pixel_offset;
3110f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)        int top = child_rect.bottom() - end_pixel_offset;
3120f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)        child_overlap_rect = gfx::Rect(child_rect.x(), top,
3130f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)                                       child_rect.width(), bottom - top);
3140f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)        break;
3150f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)      }
3160f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)      default:
3170f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)        NOTREACHED();
3180f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    }
3190f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)
3200f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    if (bounds.width() == 0 && bounds.height() == 0)
3210f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)      bounds = child_overlap_rect;
3220f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    else
3230f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)      bounds.Union(child_overlap_rect);
3240f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  }
3250f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)
3260f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  return bounds;
3270f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)}
3280f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)
3290f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)gfx::Rect BrowserAccessibility::GetGlobalBoundsForRange(int start, int len)
3300f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    const {
3310f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  gfx::Rect bounds = GetLocalBoundsForRange(start, len);
3320f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)
3330f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  // Adjust the bounds by the top left corner of the containing view's bounds
3340f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  // in screen coordinates.
3350f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  bounds.Offset(manager_->GetViewBounds().OffsetFromOrigin());
3360f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)
3370f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  return bounds;
3380f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)}
3390f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BrowserAccessibility* BrowserAccessibility::BrowserAccessibilityForPoint(
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const gfx::Point& point) {
342effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  // The best result found that's a child of this object.
343effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  BrowserAccessibility* child_result = NULL;
344effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  // The best result that's an indirect descendant like grandchild, etc.
345effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  BrowserAccessibility* descendant_result = NULL;
346effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Walk the children recursively looking for the BrowserAccessibility that
348effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  // most tightly encloses the specified point. Walk backwards so that in
349effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  // the absence of any other information, we assume the object that occurs
350effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  // later in the tree is on top of one that comes before it.
351f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  for (int i = static_cast<int>(PlatformChildCount()) - 1; i >= 0; --i) {
352f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    BrowserAccessibility* child = PlatformGetChild(i);
353a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
354a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    // Skip table columns because cells are only contained in rows,
355a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    // not columns.
356a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    if (child->GetRole() == ui::AX_ROLE_COLUMN)
357a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      continue;
358a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
359effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    if (child->GetGlobalBoundsRect().Contains(point)) {
360effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      BrowserAccessibility* result = child->BrowserAccessibilityForPoint(point);
361effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      if (result == child && !child_result)
362effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch        child_result = result;
363effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      if (result != child && !descendant_result)
364effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch        descendant_result = result;
365effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    }
366effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
367effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    if (child_result && descendant_result)
368effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      break;
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
370effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
371effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  // Explanation of logic: it's possible that this point overlaps more than
372effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  // one child of this object. If so, as a heuristic we prefer if the point
373effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  // overlaps a descendant of one of the two children and not the other.
374effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  // As an example, suppose you have two rows of buttons - the buttons don't
375effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  // overlap, but the rows do. Without this heuristic, we'd greedily only
376effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  // consider one of the containers.
377effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  if (descendant_result)
378effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    return descendant_result;
379effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  if (child_result)
380effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    return child_result;
381effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return this;
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void BrowserAccessibility::Destroy() {
3862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Allow the object to fire a TextRemoved notification.
3872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  name_.clear();
3882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  value_.clear();
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  manager_->NotifyAccessibilityEvent(ui::AX_EVENT_HIDE, this);
3910529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  node_ = NULL;
3920529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  manager_ = NULL;
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  NativeReleaseReference();
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BrowserAccessibility::NativeReleaseReference() {
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delete this;
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool BrowserAccessibility::HasBoolAttribute(
4025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    ui::AXBoolAttribute attribute) const {
4030529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  const ui::AXNodeData& data = GetData();
4040529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  for (size_t i = 0; i < data.bool_attributes.size(); ++i) {
4050529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    if (data.bool_attributes[i].first == attribute)
4063551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      return true;
4073551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
4083551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
4093551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return false;
4103551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
4113551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
4123551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
4135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool BrowserAccessibility::GetBoolAttribute(
4145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    ui::AXBoolAttribute attribute) const {
4150529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  const ui::AXNodeData& data = GetData();
4160529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  for (size_t i = 0; i < data.bool_attributes.size(); ++i) {
4170529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    if (data.bool_attributes[i].first == attribute)
4180529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      return data.bool_attributes[i].second;
4193551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
4203551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
4213551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return false;
4223551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
4233551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool BrowserAccessibility::GetBoolAttribute(
4255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    ui::AXBoolAttribute attribute, bool* value) const {
4260529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  const ui::AXNodeData& data = GetData();
4270529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  for (size_t i = 0; i < data.bool_attributes.size(); ++i) {
4280529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    if (data.bool_attributes[i].first == attribute) {
4290529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      *value = data.bool_attributes[i].second;
4303551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      return true;
4313551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    }
4323551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
4333551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
4343551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return false;
4353551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
4363551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
4375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool BrowserAccessibility::HasFloatAttribute(
4385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    ui::AXFloatAttribute attribute) const {
4390529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  const ui::AXNodeData& data = GetData();
4400529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  for (size_t i = 0; i < data.float_attributes.size(); ++i) {
4410529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    if (data.float_attributes[i].first == attribute)
4423551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      return true;
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)float BrowserAccessibility::GetFloatAttribute(
4495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    ui::AXFloatAttribute attribute) const {
4500529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  const ui::AXNodeData& data = GetData();
4510529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  for (size_t i = 0; i < data.float_attributes.size(); ++i) {
4520529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    if (data.float_attributes[i].first == attribute)
4530529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      return data.float_attributes[i].second;
4543551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
4553551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
4563551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return 0.0;
4573551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
4583551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool BrowserAccessibility::GetFloatAttribute(
4605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    ui::AXFloatAttribute attribute, float* value) const {
4610529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  const ui::AXNodeData& data = GetData();
4620529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  for (size_t i = 0; i < data.float_attributes.size(); ++i) {
4630529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    if (data.float_attributes[i].first == attribute) {
4640529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      *value = data.float_attributes[i].second;
4653551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      return true;
4663551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    }
4673551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
4683551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
4693551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return false;
4703551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
4713551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
4725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool BrowserAccessibility::HasIntAttribute(
4735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    ui::AXIntAttribute attribute) const {
4740529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  const ui::AXNodeData& data = GetData();
4750529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  for (size_t i = 0; i < data.int_attributes.size(); ++i) {
4760529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    if (data.int_attributes[i].first == attribute)
4773551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      return true;
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)int BrowserAccessibility::GetIntAttribute(ui::AXIntAttribute attribute) const {
4840529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  const ui::AXNodeData& data = GetData();
4850529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  for (size_t i = 0; i < data.int_attributes.size(); ++i) {
4860529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    if (data.int_attributes[i].first == attribute)
4870529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      return data.int_attributes[i].second;
4883551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
4893551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
4903551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return 0;
4913551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
4923551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool BrowserAccessibility::GetIntAttribute(
4945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    ui::AXIntAttribute attribute, int* value) const {
4950529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  const ui::AXNodeData& data = GetData();
4960529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  for (size_t i = 0; i < data.int_attributes.size(); ++i) {
4970529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    if (data.int_attributes[i].first == attribute) {
4980529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      *value = data.int_attributes[i].second;
4993551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      return true;
5003551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    }
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool BrowserAccessibility::HasStringAttribute(
5075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    ui::AXStringAttribute attribute) const {
5080529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  const ui::AXNodeData& data = GetData();
5090529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  for (size_t i = 0; i < data.string_attributes.size(); ++i) {
5100529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    if (data.string_attributes[i].first == attribute)
5113551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      return true;
5123551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
5133551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
5143551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return false;
5153551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
5163551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
5173551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)const std::string& BrowserAccessibility::GetStringAttribute(
5185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    ui::AXStringAttribute attribute) const {
5190529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  const ui::AXNodeData& data = GetData();
5203551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  CR_DEFINE_STATIC_LOCAL(std::string, empty_string, ());
5210529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  for (size_t i = 0; i < data.string_attributes.size(); ++i) {
5220529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    if (data.string_attributes[i].first == attribute)
5230529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      return data.string_attributes[i].second;
5243551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
5253551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
5263551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return empty_string;
5273551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
5283551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool BrowserAccessibility::GetStringAttribute(
5305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    ui::AXStringAttribute attribute, std::string* value) const {
5310529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  const ui::AXNodeData& data = GetData();
5320529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  for (size_t i = 0; i < data.string_attributes.size(); ++i) {
5330529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    if (data.string_attributes[i].first == attribute) {
5340529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      *value = data.string_attributes[i].second;
5353551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      return true;
5363551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    }
5373551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
5383551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
5393551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return false;
5403551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
5413551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
542a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)base::string16 BrowserAccessibility::GetString16Attribute(
5435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    ui::AXStringAttribute attribute) const {
5443551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  std::string value_utf8;
5453551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (!GetStringAttribute(attribute, &value_utf8))
546a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    return base::string16();
5475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return base::UTF8ToUTF16(value_utf8);
5483551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
5493551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
5503551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)bool BrowserAccessibility::GetString16Attribute(
5515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    ui::AXStringAttribute attribute,
552a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    base::string16* value) const {
5533551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  std::string value_utf8;
5543551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (!GetStringAttribute(attribute, &value_utf8))
5553551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return false;
5565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  *value = base::UTF8ToUTF16(value_utf8);
5573551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return true;
5583551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
5593551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
5603551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void BrowserAccessibility::SetStringAttribute(
5615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    ui::AXStringAttribute attribute, const std::string& value) {
5620529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  if (!node_)
5630529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    return;
5640529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  ui::AXNodeData data = GetData();
5650529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  for (size_t i = 0; i < data.string_attributes.size(); ++i) {
5660529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    if (data.string_attributes[i].first == attribute) {
5670529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      data.string_attributes[i].second = value;
5680529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      node_->SetData(data);
5693551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      return;
5703551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    }
5713551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
5720529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  if (!value.empty()) {
5730529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    data.string_attributes.push_back(std::make_pair(attribute, value));
5740529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    node_->SetData(data);
5750529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  }
5763551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
5773551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
5783551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)bool BrowserAccessibility::HasIntListAttribute(
5795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    ui::AXIntListAttribute attribute) const {
5800529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  const ui::AXNodeData& data = GetData();
5810529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  for (size_t i = 0; i < data.intlist_attributes.size(); ++i) {
5820529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    if (data.intlist_attributes[i].first == attribute)
5833551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      return true;
5843551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
5853551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
5863551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return false;
5873551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
5883551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
5893551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)const std::vector<int32>& BrowserAccessibility::GetIntListAttribute(
5905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    ui::AXIntListAttribute attribute) const {
5910529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  const ui::AXNodeData& data = GetData();
5923551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  CR_DEFINE_STATIC_LOCAL(std::vector<int32>, empty_vector, ());
5930529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  for (size_t i = 0; i < data.intlist_attributes.size(); ++i) {
5940529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    if (data.intlist_attributes[i].first == attribute)
5950529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      return data.intlist_attributes[i].second;
5963551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
5973551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
5983551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return empty_vector;
5993551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
6003551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
6013551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)bool BrowserAccessibility::GetIntListAttribute(
6025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    ui::AXIntListAttribute attribute,
6033551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    std::vector<int32>* value) const {
6040529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  const ui::AXNodeData& data = GetData();
6050529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  for (size_t i = 0; i < data.intlist_attributes.size(); ++i) {
6060529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    if (data.intlist_attributes[i].first == attribute) {
6070529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      *value = data.intlist_attributes[i].second;
6083551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      return true;
6093551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    }
6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool BrowserAccessibility::GetHtmlAttribute(
6163551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    const char* html_attr, std::string* value) const {
617a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  for (size_t i = 0; i < GetHtmlAttributes().size(); ++i) {
618a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    const std::string& attr = GetHtmlAttributes()[i].first;
6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (LowerCaseEqualsASCII(attr, html_attr)) {
620a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      *value = GetHtmlAttributes()[i].second;
6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6283551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)bool BrowserAccessibility::GetHtmlAttribute(
629a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    const char* html_attr, base::string16* value) const {
6303551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  std::string value_utf8;
6313551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (!GetHtmlAttribute(html_attr, &value_utf8))
6323551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return false;
6335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  *value = base::UTF8ToUTF16(value_utf8);
6343551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return true;
6353551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
6363551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool BrowserAccessibility::GetAriaTristate(
6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const char* html_attr,
6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool* is_defined,
6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool* is_mixed) const {
6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *is_defined = false;
6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *is_mixed = false;
6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
644a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  base::string16 value;
6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!GetHtmlAttribute(html_attr, &value) ||
6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      value.empty() ||
6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EqualsASCII(value, "undefined")) {
6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;  // Not set (and *is_defined is also false)
6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *is_defined = true;
6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (EqualsASCII(value, "true"))
6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (EqualsASCII(value, "mixed"))
6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *is_mixed = true;
6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;  // Not set
6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool BrowserAccessibility::HasState(ui::AXState state_enum) const {
663a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  return (GetState() >> state_enum) & 1;
6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool BrowserAccessibility::IsEditableText() const {
6677d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // These roles don't have readonly set, but they're not editable text.
668a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  if (GetRole() == ui::AX_ROLE_SCROLL_AREA ||
669a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      GetRole() == ui::AX_ROLE_COLUMN ||
670a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      GetRole() == ui::AX_ROLE_TABLE_HEADER_CONTAINER) {
6717d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    return false;
6727d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  }
6737d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
67458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // Note: WebAXStateReadonly being false means it's either a text control,
6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // or contenteditable. We also check for editable text roles to cover
6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // another element that has role=textbox set on it.
6775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return (!HasState(ui::AX_STATE_READ_ONLY) ||
678a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch          GetRole() == ui::AX_ROLE_TEXT_FIELD ||
679a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch          GetRole() == ui::AX_ROLE_TEXT_AREA);
6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6823551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)std::string BrowserAccessibility::GetTextRecursive() const {
6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!name_.empty()) {
6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return name_;
6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6873551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  std::string result;
688f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  for (uint32 i = 0; i < PlatformChildCount(); ++i)
689f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    result += PlatformGetChild(i)->GetTextRecursive();
6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return result;
6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)int BrowserAccessibility::GetStaticTextLenRecursive() const {
694a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  if (GetRole() == ui::AX_ROLE_STATIC_TEXT)
6955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return static_cast<int>(GetStringAttribute(ui::AX_ATTR_VALUE).size());
6965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
6975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  int len = 0;
698a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  for (size_t i = 0; i < InternalChildCount(); ++i)
699a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    len += InternalGetChild(i)->GetStaticTextLenRecursive();
7005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return len;
7015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
7025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace content
704