1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "chrome/browser/accessibility/browser_accessibility.h"
6
7 #include "base/logging.h"
8 #include "base/string_number_conversions.h"
9 #include "chrome/browser/accessibility/browser_accessibility_manager.h"
10
11 #if defined(OS_LINUX)
12 // There's no OS-specific implementation of BrowserAccessibilityManager
13 // on Linux, so just instantiate the base class.
14 // static
Create()15 BrowserAccessibility* BrowserAccessibility::Create() {
16 return new BrowserAccessibility();
17 }
18 #endif
19
BrowserAccessibility()20 BrowserAccessibility::BrowserAccessibility()
21 : manager_(NULL),
22 parent_(NULL),
23 child_id_(0),
24 index_in_parent_(0),
25 renderer_id_(0),
26 ref_count_(1),
27 role_(0),
28 state_(0),
29 instance_active_(false) {
30 }
31
~BrowserAccessibility()32 BrowserAccessibility::~BrowserAccessibility() {
33 }
34
ReplaceChild(BrowserAccessibility * old_acc,BrowserAccessibility * new_acc)35 void BrowserAccessibility::ReplaceChild(
36 BrowserAccessibility* old_acc, BrowserAccessibility* new_acc) {
37 DCHECK_EQ(children_[old_acc->index_in_parent_], old_acc);
38
39 old_acc = children_[old_acc->index_in_parent_];
40 children_[old_acc->index_in_parent_] = new_acc;
41 }
42
Initialize(BrowserAccessibilityManager * manager,BrowserAccessibility * parent,int32 child_id,int32 index_in_parent,const webkit_glue::WebAccessibility & src)43 void BrowserAccessibility::Initialize(
44 BrowserAccessibilityManager* manager,
45 BrowserAccessibility* parent,
46 int32 child_id,
47 int32 index_in_parent,
48 const webkit_glue::WebAccessibility& src) {
49 manager_ = manager;
50 parent_ = parent;
51 child_id_ = child_id;
52 index_in_parent_ = index_in_parent;
53
54 renderer_id_ = src.id;
55 name_ = src.name;
56 value_ = src.value;
57 attributes_ = src.attributes;
58 html_attributes_ = src.html_attributes;
59 location_ = src.location;
60 role_ = src.role;
61 state_ = src.state;
62 indirect_child_ids_ = src.indirect_child_ids;
63
64 Initialize();
65 }
66
Initialize()67 void BrowserAccessibility::Initialize() {
68 instance_active_ = true;
69 }
70
AddChild(BrowserAccessibility * child)71 void BrowserAccessibility::AddChild(BrowserAccessibility* child) {
72 children_.push_back(child);
73 }
74
DetachTree(std::vector<BrowserAccessibility * > * nodes)75 void BrowserAccessibility::DetachTree(
76 std::vector<BrowserAccessibility*>* nodes) {
77 nodes->push_back(this);
78 for (size_t i = 0; i < children_.size(); i++)
79 children_[i]->DetachTree(nodes);
80 children_.clear();
81 parent_ = NULL;
82 }
83
UpdateParent(BrowserAccessibility * parent,int index_in_parent)84 void BrowserAccessibility::UpdateParent(BrowserAccessibility* parent,
85 int index_in_parent) {
86 parent_ = parent;
87 index_in_parent_ = index_in_parent;
88 }
89
IsDescendantOf(BrowserAccessibility * ancestor)90 bool BrowserAccessibility::IsDescendantOf(
91 BrowserAccessibility* ancestor) {
92 if (this == ancestor) {
93 return true;
94 } else if (parent_) {
95 return parent_->IsDescendantOf(ancestor);
96 }
97
98 return false;
99 }
100
GetChild(uint32 child_index)101 BrowserAccessibility* BrowserAccessibility::GetChild(uint32 child_index) {
102 DCHECK(child_index < children_.size());
103 return children_[child_index];
104 }
105
GetPreviousSibling()106 BrowserAccessibility* BrowserAccessibility::GetPreviousSibling() {
107 if (parent_ && index_in_parent_ > 0)
108 return parent_->children_[index_in_parent_ - 1];
109
110 return NULL;
111 }
112
GetNextSibling()113 BrowserAccessibility* BrowserAccessibility::GetNextSibling() {
114 if (parent_ &&
115 index_in_parent_ >= 0 &&
116 index_in_parent_ < static_cast<int>(parent_->children_.size() - 1)) {
117 return parent_->children_[index_in_parent_ + 1];
118 }
119
120 return NULL;
121 }
122
GetBoundsRect()123 gfx::Rect BrowserAccessibility::GetBoundsRect() {
124 gfx::Rect bounds = location_;
125
126 // Adjust the bounds by the top left corner of the containing view's bounds
127 // in screen coordinates.
128 gfx::Point top_left = manager_->GetViewBounds().origin();
129 bounds.Offset(top_left);
130
131 // Adjust top left position by the root document's scroll offset.
132 BrowserAccessibility* root = manager_->GetRoot();
133 int scroll_x = 0;
134 int scroll_y = 0;
135 root->GetAttributeAsInt(
136 WebAccessibility::ATTR_DOC_SCROLLX, &scroll_x);
137 root->GetAttributeAsInt(
138 WebAccessibility::ATTR_DOC_SCROLLY, &scroll_y);
139 bounds.Offset(-scroll_x, -scroll_y);
140
141 return bounds;
142 }
143
BrowserAccessibilityForPoint(const gfx::Point & point)144 BrowserAccessibility* BrowserAccessibility::BrowserAccessibilityForPoint(
145 const gfx::Point& point) {
146 // Walk the children recursively looking for the BrowserAccessibility that
147 // most tightly encloses the specified point.
148 for (int i = children_.size() - 1; i >= 0; --i) {
149 BrowserAccessibility* child = children_[i];
150 if (child->GetBoundsRect().Contains(point))
151 return child->BrowserAccessibilityForPoint(point);
152 }
153 return this;
154 }
155
InternalAddReference()156 void BrowserAccessibility::InternalAddReference() {
157 ref_count_++;
158 }
159
InternalReleaseReference(bool recursive)160 void BrowserAccessibility::InternalReleaseReference(bool recursive) {
161 DCHECK_GT(ref_count_, 0);
162
163 if (recursive || ref_count_ == 1) {
164 for (std::vector<BrowserAccessibility*>::iterator iter = children_.begin();
165 iter != children_.end();
166 ++iter) {
167 (*iter)->InternalReleaseReference(true);
168 }
169 }
170
171 ref_count_--;
172 if (ref_count_ == 0) {
173 instance_active_ = false;
174 children_.clear();
175 manager_->Remove(child_id_, renderer_id_);
176 NativeReleaseReference();
177 }
178 }
179
NativeReleaseReference()180 void BrowserAccessibility::NativeReleaseReference() {
181 delete this;
182 }
183
HasAttribute(WebAccessibility::Attribute attribute)184 bool BrowserAccessibility::HasAttribute(
185 WebAccessibility::Attribute attribute) {
186 return (attributes_.find(attribute) != attributes_.end());
187 }
188
GetAttribute(WebAccessibility::Attribute attribute,string16 * value)189 bool BrowserAccessibility::GetAttribute(
190 WebAccessibility::Attribute attribute, string16* value) {
191 std::map<int32, string16>::iterator iter = attributes_.find(attribute);
192 if (iter != attributes_.end()) {
193 *value = iter->second;
194 return true;
195 }
196
197 return false;
198 }
199
GetAttributeAsInt(WebAccessibility::Attribute attribute,int * value_int)200 bool BrowserAccessibility::GetAttributeAsInt(
201 WebAccessibility::Attribute attribute, int* value_int) {
202 string16 value_str;
203
204 if (!GetAttribute(attribute, &value_str))
205 return false;
206
207 if (!base::StringToInt(value_str, value_int))
208 return false;
209
210 return true;
211 }
212