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 15 BrowserAccessibility* BrowserAccessibility::Create() { 16 return new BrowserAccessibility(); 17 } 18 #endif 19 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 32 BrowserAccessibility::~BrowserAccessibility() { 33 } 34 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 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 67 void BrowserAccessibility::Initialize() { 68 instance_active_ = true; 69 } 70 71 void BrowserAccessibility::AddChild(BrowserAccessibility* child) { 72 children_.push_back(child); 73 } 74 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 84 void BrowserAccessibility::UpdateParent(BrowserAccessibility* parent, 85 int index_in_parent) { 86 parent_ = parent; 87 index_in_parent_ = index_in_parent; 88 } 89 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 101 BrowserAccessibility* BrowserAccessibility::GetChild(uint32 child_index) { 102 DCHECK(child_index < children_.size()); 103 return children_[child_index]; 104 } 105 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 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 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 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 156 void BrowserAccessibility::InternalAddReference() { 157 ref_count_++; 158 } 159 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 180 void BrowserAccessibility::NativeReleaseReference() { 181 delete this; 182 } 183 184 bool BrowserAccessibility::HasAttribute( 185 WebAccessibility::Attribute attribute) { 186 return (attributes_.find(attribute) != attributes_.end()); 187 } 188 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 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