Home | History | Annotate | Download | only in accessibility
      1 // Copyright (c) 2012 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 "content/browser/accessibility/accessibility_tree_formatter.h"
      6 
      7 #include "base/logging.h"
      8 #include "base/memory/scoped_ptr.h"
      9 #include "base/strings/string_number_conversions.h"
     10 #include "base/strings/string_util.h"
     11 #include "base/strings/stringprintf.h"
     12 #include "base/strings/utf_string_conversions.h"
     13 #include "content/browser/accessibility/browser_accessibility_manager.h"
     14 #include "content/browser/renderer_host/render_widget_host_view_base.h"
     15 #include "content/public/browser/render_view_host.h"
     16 #include "content/public/browser/web_contents.h"
     17 
     18 namespace content {
     19 namespace {
     20 const int kIndentSpaces = 4;
     21 const char* kSkipString = "@NO_DUMP";
     22 const char* kChildrenDictAttr = "children";
     23 }
     24 
     25 AccessibilityTreeFormatter::AccessibilityTreeFormatter(
     26     BrowserAccessibility* root)
     27     : root_(root) {
     28   Initialize();
     29 }
     30 
     31 // static
     32 AccessibilityTreeFormatter* AccessibilityTreeFormatter::Create(
     33     RenderViewHost* rvh) {
     34   RenderWidgetHostViewBase* host_view = static_cast<RenderWidgetHostViewBase*>(
     35       WebContents::FromRenderViewHost(rvh)->GetRenderWidgetHostView());
     36 
     37   BrowserAccessibilityManager* manager =
     38       host_view->GetBrowserAccessibilityManager();
     39   if (!manager)
     40     return NULL;
     41 
     42   BrowserAccessibility* root = manager->GetRoot();
     43   return new AccessibilityTreeFormatter(root);
     44 }
     45 
     46 
     47 AccessibilityTreeFormatter::~AccessibilityTreeFormatter() {
     48 }
     49 
     50 scoped_ptr<base::DictionaryValue>
     51 AccessibilityTreeFormatter::BuildAccessibilityTree() {
     52   scoped_ptr<base::DictionaryValue> dict(new base::DictionaryValue);
     53   RecursiveBuildAccessibilityTree(*root_, dict.get());
     54   return dict.Pass();
     55 }
     56 
     57 void AccessibilityTreeFormatter::FormatAccessibilityTree(
     58     base::string16* contents) {
     59   scoped_ptr<base::DictionaryValue> dict = BuildAccessibilityTree();
     60   RecursiveFormatAccessibilityTree(*(dict.get()), contents);
     61 }
     62 
     63 void AccessibilityTreeFormatter::RecursiveBuildAccessibilityTree(
     64     const BrowserAccessibility& node, base::DictionaryValue* dict) {
     65   AddProperties(node, dict);
     66 
     67   base::ListValue* children = new base::ListValue;
     68   dict->Set(kChildrenDictAttr, children);
     69 
     70   for (size_t i = 0; i < node.PlatformChildCount(); ++i) {
     71     BrowserAccessibility* child_node = node.InternalGetChild(i);
     72     base::DictionaryValue* child_dict = new base::DictionaryValue;
     73     children->Append(child_dict);
     74     RecursiveBuildAccessibilityTree(*child_node, child_dict);
     75   }
     76 }
     77 
     78 void AccessibilityTreeFormatter::RecursiveFormatAccessibilityTree(
     79     const base::DictionaryValue& dict, base::string16* contents, int depth) {
     80   base::string16 line =
     81       ToString(dict, base::string16(depth * kIndentSpaces, ' '));
     82   if (line.find(base::ASCIIToUTF16(kSkipString)) != base::string16::npos)
     83     return;
     84 
     85   *contents += line;
     86   const base::ListValue* children;
     87   dict.GetList(kChildrenDictAttr, &children);
     88   const base::DictionaryValue* child_dict;
     89   for (size_t i = 0; i < children->GetSize(); i++) {
     90     children->GetDictionary(i, &child_dict);
     91     RecursiveFormatAccessibilityTree(*child_dict, contents, depth + 1);
     92   }
     93 }
     94 
     95 #if (!defined(OS_WIN) && !defined(OS_MACOSX) && !defined(OS_ANDROID))
     96 void AccessibilityTreeFormatter::AddProperties(const BrowserAccessibility& node,
     97                                                base::DictionaryValue* dict) {
     98   dict->SetInteger("id", node.GetId());
     99 }
    100 
    101 base::string16 AccessibilityTreeFormatter::ToString(
    102     const base::DictionaryValue& node,
    103     const base::string16& indent) {
    104   int id_value;
    105   node.GetInteger("id", &id_value);
    106   return indent + base::IntToString16(id_value) +
    107        base::ASCIIToUTF16("\n");
    108 }
    109 
    110 void AccessibilityTreeFormatter::Initialize() {}
    111 
    112 // static
    113 const base::FilePath::StringType
    114 AccessibilityTreeFormatter::GetActualFileSuffix() {
    115   return base::FilePath::StringType();
    116 }
    117 
    118 // static
    119 const base::FilePath::StringType
    120 AccessibilityTreeFormatter::GetExpectedFileSuffix() {
    121   return base::FilePath::StringType();
    122 }
    123 
    124 // static
    125 const std::string AccessibilityTreeFormatter::GetAllowEmptyString() {
    126   return std::string();
    127 }
    128 
    129 // static
    130 const std::string AccessibilityTreeFormatter::GetAllowString() {
    131   return std::string();
    132 }
    133 
    134 // static
    135 const std::string AccessibilityTreeFormatter::GetDenyString() {
    136   return std::string();
    137 }
    138 #endif
    139 
    140 void AccessibilityTreeFormatter::SetFilters(
    141     const std::vector<Filter>& filters) {
    142   filters_ = filters;
    143 }
    144 
    145 bool AccessibilityTreeFormatter::MatchesFilters(
    146     const base::string16& text, bool default_result) const {
    147   std::vector<Filter>::const_iterator iter = filters_.begin();
    148   bool allow = default_result;
    149   for (iter = filters_.begin(); iter != filters_.end(); ++iter) {
    150     if (MatchPattern(text, iter->match_str)) {
    151       if (iter->type == Filter::ALLOW_EMPTY)
    152         allow = true;
    153       else if (iter->type == Filter::ALLOW)
    154         allow = (!MatchPattern(text, base::UTF8ToUTF16("*=''")));
    155       else
    156         allow = false;
    157     }
    158   }
    159   return allow;
    160 }
    161 
    162 base::string16 AccessibilityTreeFormatter::FormatCoordinates(
    163     const char* name, const char* x_name, const char* y_name,
    164     const base::DictionaryValue& value) {
    165   int x, y;
    166   value.GetInteger(x_name, &x);
    167   value.GetInteger(y_name, &y);
    168   std::string xy_str(base::StringPrintf("%s=(%d, %d)", name, x, y));
    169 
    170   return base::UTF8ToUTF16(xy_str);
    171 }
    172 
    173 void AccessibilityTreeFormatter::WriteAttribute(
    174     bool include_by_default, const std::string& attr, base::string16* line) {
    175   WriteAttribute(include_by_default, base::UTF8ToUTF16(attr), line);
    176 }
    177 
    178 void AccessibilityTreeFormatter::WriteAttribute(
    179     bool include_by_default, const base::string16& attr, base::string16* line) {
    180   if (attr.empty())
    181     return;
    182   if (!MatchesFilters(attr, include_by_default))
    183     return;
    184   if (!line->empty())
    185     *line += base::ASCIIToUTF16(" ");
    186   *line += attr;
    187 }
    188 
    189 }  // namespace content
    190