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