Home | History | Annotate | Download | only in accessibility
      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