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     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.children()[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(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      !defined(TOOLKIT_GTK))
     97 void AccessibilityTreeFormatter::AddProperties(const BrowserAccessibility& node,
     98                                                base::DictionaryValue* dict) {
     99   dict->SetInteger("id", node.renderer_id());
    100 }
    101 
    102 base::string16 AccessibilityTreeFormatter::ToString(
    103     const base::DictionaryValue& node,
    104     const base::string16& indent) {
    105   int id_value;
    106   node.GetInteger("id", &id_value);
    107   return indent + base::IntToString16(id_value) +
    108        ASCIIToUTF16("\n");
    109 }
    110 
    111 void AccessibilityTreeFormatter::Initialize() {}
    112 
    113 // static
    114 const base::FilePath::StringType
    115 AccessibilityTreeFormatter::GetActualFileSuffix() {
    116   return base::FilePath::StringType();
    117 }
    118 
    119 // static
    120 const base::FilePath::StringType
    121 AccessibilityTreeFormatter::GetExpectedFileSuffix() {
    122   return base::FilePath::StringType();
    123 }
    124 
    125 // static
    126 const std::string AccessibilityTreeFormatter::GetAllowEmptyString() {
    127   return std::string();
    128 }
    129 
    130 // static
    131 const std::string AccessibilityTreeFormatter::GetAllowString() {
    132   return std::string();
    133 }
    134 
    135 // static
    136 const std::string AccessibilityTreeFormatter::GetDenyString() {
    137   return std::string();
    138 }
    139 #endif
    140 
    141 void AccessibilityTreeFormatter::SetFilters(
    142     const std::vector<Filter>& filters) {
    143   filters_ = filters;
    144 }
    145 
    146 bool AccessibilityTreeFormatter::MatchesFilters(
    147     const base::string16& text, bool default_result) const {
    148   std::vector<Filter>::const_iterator iter = filters_.begin();
    149   bool allow = default_result;
    150   for (iter = filters_.begin(); iter != filters_.end(); ++iter) {
    151     if (MatchPattern(text, iter->match_str)) {
    152       if (iter->type == Filter::ALLOW_EMPTY)
    153         allow = true;
    154       else if (iter->type == Filter::ALLOW)
    155         allow = (!MatchPattern(text, UTF8ToUTF16("*=''")));
    156       else
    157         allow = false;
    158     }
    159   }
    160   return allow;
    161 }
    162 
    163 base::string16 AccessibilityTreeFormatter::FormatCoordinates(
    164     const char* name, const char* x_name, const char* y_name,
    165     const base::DictionaryValue& value) {
    166   int x, y;
    167   value.GetInteger(x_name, &x);
    168   value.GetInteger(y_name, &y);
    169   std::string xy_str(base::StringPrintf("%s=(%d, %d)", name, x, y));
    170 
    171   return UTF8ToUTF16(xy_str);
    172 }
    173 
    174 void AccessibilityTreeFormatter::WriteAttribute(
    175     bool include_by_default, const std::string& attr, base::string16* line) {
    176   WriteAttribute(include_by_default, UTF8ToUTF16(attr), line);
    177 }
    178 
    179 void AccessibilityTreeFormatter::WriteAttribute(
    180     bool include_by_default, const base::string16& attr, base::string16* line) {
    181   if (attr.empty())
    182     return;
    183   if (!MatchesFilters(attr, include_by_default))
    184     return;
    185   if (!line->empty())
    186     *line += ASCIIToUTF16(" ");
    187   *line += attr;
    188 }
    189 
    190 }  // namespace content
    191