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/port/browser/render_widget_host_view_port.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   RenderWidgetHostViewPort* host_view = static_cast<RenderWidgetHostViewPort*>(
     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     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   if (!IncludeChildren(node))
     70     return;
     71 
     72   for (size_t i = 0; i < node.children().size(); ++i) {
     73     BrowserAccessibility* child_node = node.children()[i];
     74     base::DictionaryValue* child_dict = new base::DictionaryValue;
     75     children->Append(child_dict);
     76     RecursiveBuildAccessibilityTree(*child_node, child_dict);
     77   }
     78 }
     79 
     80 void AccessibilityTreeFormatter::RecursiveFormatAccessibilityTree(
     81     const base::DictionaryValue& dict, string16* contents, int depth) {
     82   string16 line = ToString(dict, string16(depth * kIndentSpaces, ' '));
     83   if (line.find(ASCIIToUTF16(kSkipString)) != string16::npos)
     84     return;
     85 
     86   *contents += line;
     87   const base::ListValue* children;
     88   dict.GetList(kChildrenDictAttr, &children);
     89   const base::DictionaryValue* child_dict;
     90   for (size_t i = 0; i < children->GetSize(); i++) {
     91     children->GetDictionary(i, &child_dict);
     92     RecursiveFormatAccessibilityTree(*child_dict, contents, depth + 1);
     93   }
     94 }
     95 
     96 #if !defined(OS_ANDROID)
     97 bool AccessibilityTreeFormatter::IncludeChildren(
     98     const BrowserAccessibility& node) {
     99   return true;
    100 }
    101 #endif
    102 
    103 #if (!defined(OS_WIN) && !defined(OS_MACOSX) && !defined(OS_ANDROID) && \
    104      !defined(TOOLKIT_GTK))
    105 void AccessibilityTreeFormatter::AddProperties(const BrowserAccessibility& node,
    106                                                base::DictionaryValue* dict) {
    107   dict->SetInteger("id", node.renderer_id());
    108 }
    109 
    110 string16 AccessibilityTreeFormatter::ToString(const base::DictionaryValue& node,
    111                                               const string16& indent) {
    112   int id_value;
    113   node.GetInteger("id", &id_value);
    114   return indent + base::IntToString16(id_value) +
    115        ASCIIToUTF16("\n");
    116 }
    117 
    118 void AccessibilityTreeFormatter::Initialize() {}
    119 
    120 // static
    121 const base::FilePath::StringType
    122 AccessibilityTreeFormatter::GetActualFileSuffix() {
    123   return base::FilePath::StringType();
    124 }
    125 
    126 // static
    127 const base::FilePath::StringType
    128 AccessibilityTreeFormatter::GetExpectedFileSuffix() {
    129   return base::FilePath::StringType();
    130 }
    131 
    132 // static
    133 const std::string AccessibilityTreeFormatter::GetAllowEmptyString() {
    134   return std::string();
    135 }
    136 
    137 // static
    138 const std::string AccessibilityTreeFormatter::GetAllowString() {
    139   return std::string();
    140 }
    141 
    142 // static
    143 const std::string AccessibilityTreeFormatter::GetDenyString() {
    144   return std::string();
    145 }
    146 #endif
    147 
    148 void AccessibilityTreeFormatter::SetFilters(
    149     const std::vector<Filter>& filters) {
    150   filters_ = filters;
    151 }
    152 
    153 bool AccessibilityTreeFormatter::MatchesFilters(
    154     const string16& text, bool default_result) const {
    155   std::vector<Filter>::const_iterator iter = filters_.begin();
    156   bool allow = default_result;
    157   for (iter = filters_.begin(); iter != filters_.end(); ++iter) {
    158     if (MatchPattern(text, iter->match_str)) {
    159       if (iter->type == Filter::ALLOW_EMPTY)
    160         allow = true;
    161       else if (iter->type == Filter::ALLOW)
    162         allow = (!MatchPattern(text, UTF8ToUTF16("*=''")));
    163       else
    164         allow = false;
    165     }
    166   }
    167   return allow;
    168 }
    169 
    170 string16 AccessibilityTreeFormatter::FormatCoordinates(
    171     const char* name, const char* x_name, const char* y_name,
    172     const base::DictionaryValue& value) {
    173   int x, y;
    174   value.GetInteger(x_name, &x);
    175   value.GetInteger(y_name, &y);
    176   std::string xy_str(base::StringPrintf("%s=(%d, %d)", name, x, y));
    177 
    178   return UTF8ToUTF16(xy_str);
    179 }
    180 
    181 void AccessibilityTreeFormatter::WriteAttribute(
    182     bool include_by_default, const std::string& attr, string16* line) {
    183   WriteAttribute(include_by_default, UTF8ToUTF16(attr), line);
    184 }
    185 
    186 void AccessibilityTreeFormatter::WriteAttribute(
    187     bool include_by_default, const string16& attr, string16* line) {
    188   if (attr.empty())
    189     return;
    190   if (!MatchesFilters(attr, include_by_default))
    191     return;
    192   if (!line->empty())
    193     *line += ASCIIToUTF16(" ");
    194   *line += attr;
    195 }
    196 
    197 }  // namespace content
    198