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