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 18namespace content { 19namespace { 20const int kIndentSpaces = 4; 21const char* kSkipString = "@NO_DUMP"; 22const char* kChildrenDictAttr = "children"; 23} 24 25AccessibilityTreeFormatter::AccessibilityTreeFormatter( 26 BrowserAccessibility* root) 27 : root_(root) { 28 Initialize(); 29} 30 31// static 32AccessibilityTreeFormatter* 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 47AccessibilityTreeFormatter::~AccessibilityTreeFormatter() { 48} 49 50scoped_ptr<base::DictionaryValue> 51AccessibilityTreeFormatter::BuildAccessibilityTree() { 52 scoped_ptr<base::DictionaryValue> dict(new base::DictionaryValue); 53 RecursiveBuildAccessibilityTree(*root_, dict.get()); 54 return dict.Pass(); 55} 56 57void AccessibilityTreeFormatter::FormatAccessibilityTree( 58 base::string16* contents) { 59 scoped_ptr<base::DictionaryValue> dict = BuildAccessibilityTree(); 60 RecursiveFormatAccessibilityTree(*(dict.get()), contents); 61} 62 63void 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 78void 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)) 97void AccessibilityTreeFormatter::AddProperties(const BrowserAccessibility& node, 98 base::DictionaryValue* dict) { 99 dict->SetInteger("id", node.renderer_id()); 100} 101 102base::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 111void AccessibilityTreeFormatter::Initialize() {} 112 113// static 114const base::FilePath::StringType 115AccessibilityTreeFormatter::GetActualFileSuffix() { 116 return base::FilePath::StringType(); 117} 118 119// static 120const base::FilePath::StringType 121AccessibilityTreeFormatter::GetExpectedFileSuffix() { 122 return base::FilePath::StringType(); 123} 124 125// static 126const std::string AccessibilityTreeFormatter::GetAllowEmptyString() { 127 return std::string(); 128} 129 130// static 131const std::string AccessibilityTreeFormatter::GetAllowString() { 132 return std::string(); 133} 134 135// static 136const std::string AccessibilityTreeFormatter::GetDenyString() { 137 return std::string(); 138} 139#endif 140 141void AccessibilityTreeFormatter::SetFilters( 142 const std::vector<Filter>& filters) { 143 filters_ = filters; 144} 145 146bool 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 163base::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 174void AccessibilityTreeFormatter::WriteAttribute( 175 bool include_by_default, const std::string& attr, base::string16* line) { 176 WriteAttribute(include_by_default, UTF8ToUTF16(attr), line); 177} 178 179void 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