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/browser/web_contents/web_contents_impl.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 WebContents* web_contents) { 34 BrowserAccessibilityManager* manager = 35 static_cast<WebContentsImpl*>(web_contents)-> 36 GetRootBrowserAccessibilityManager(); 37 if (!manager) 38 return NULL; 39 40 BrowserAccessibility* root = manager->GetRoot(); 41 return new AccessibilityTreeFormatter(root); 42 } 43 44 45 AccessibilityTreeFormatter::~AccessibilityTreeFormatter() { 46 } 47 48 scoped_ptr<base::DictionaryValue> 49 AccessibilityTreeFormatter::BuildAccessibilityTree() { 50 scoped_ptr<base::DictionaryValue> dict(new base::DictionaryValue); 51 RecursiveBuildAccessibilityTree(*root_, dict.get()); 52 return dict.Pass(); 53 } 54 55 void AccessibilityTreeFormatter::FormatAccessibilityTree( 56 base::string16* contents) { 57 scoped_ptr<base::DictionaryValue> dict = BuildAccessibilityTree(); 58 RecursiveFormatAccessibilityTree(*(dict.get()), contents); 59 } 60 61 void AccessibilityTreeFormatter::RecursiveBuildAccessibilityTree( 62 const BrowserAccessibility& node, base::DictionaryValue* dict) { 63 AddProperties(node, dict); 64 65 base::ListValue* children = new base::ListValue; 66 dict->Set(kChildrenDictAttr, children); 67 68 for (size_t i = 0; i < node.PlatformChildCount(); ++i) { 69 BrowserAccessibility* child_node = node.PlatformGetChild(i); 70 base::DictionaryValue* child_dict = new base::DictionaryValue; 71 children->Append(child_dict); 72 RecursiveBuildAccessibilityTree(*child_node, child_dict); 73 } 74 } 75 76 void AccessibilityTreeFormatter::RecursiveFormatAccessibilityTree( 77 const base::DictionaryValue& dict, base::string16* contents, int depth) { 78 base::string16 line = 79 ToString(dict, base::string16(depth * kIndentSpaces, ' ')); 80 if (line.find(base::ASCIIToUTF16(kSkipString)) != base::string16::npos) 81 return; 82 83 *contents += line; 84 const base::ListValue* children; 85 dict.GetList(kChildrenDictAttr, &children); 86 const base::DictionaryValue* child_dict; 87 for (size_t i = 0; i < children->GetSize(); i++) { 88 children->GetDictionary(i, &child_dict); 89 RecursiveFormatAccessibilityTree(*child_dict, contents, depth + 1); 90 } 91 } 92 93 #if (!defined(OS_WIN) && !defined(OS_MACOSX) && !defined(OS_ANDROID)) 94 void AccessibilityTreeFormatter::AddProperties(const BrowserAccessibility& node, 95 base::DictionaryValue* dict) { 96 dict->SetInteger("id", node.GetId()); 97 } 98 99 base::string16 AccessibilityTreeFormatter::ToString( 100 const base::DictionaryValue& node, 101 const base::string16& indent) { 102 int id_value; 103 node.GetInteger("id", &id_value); 104 return indent + base::IntToString16(id_value) + 105 base::ASCIIToUTF16("\n"); 106 } 107 108 void AccessibilityTreeFormatter::Initialize() {} 109 110 // static 111 const base::FilePath::StringType 112 AccessibilityTreeFormatter::GetActualFileSuffix() { 113 return base::FilePath::StringType(); 114 } 115 116 // static 117 const base::FilePath::StringType 118 AccessibilityTreeFormatter::GetExpectedFileSuffix() { 119 return base::FilePath::StringType(); 120 } 121 122 // static 123 const std::string AccessibilityTreeFormatter::GetAllowEmptyString() { 124 return std::string(); 125 } 126 127 // static 128 const std::string AccessibilityTreeFormatter::GetAllowString() { 129 return std::string(); 130 } 131 132 // static 133 const std::string AccessibilityTreeFormatter::GetDenyString() { 134 return std::string(); 135 } 136 #endif 137 138 void AccessibilityTreeFormatter::SetFilters( 139 const std::vector<Filter>& filters) { 140 filters_ = filters; 141 } 142 143 bool AccessibilityTreeFormatter::MatchesFilters( 144 const base::string16& text, bool default_result) const { 145 std::vector<Filter>::const_iterator iter = filters_.begin(); 146 bool allow = default_result; 147 for (iter = filters_.begin(); iter != filters_.end(); ++iter) { 148 if (MatchPattern(text, iter->match_str)) { 149 if (iter->type == Filter::ALLOW_EMPTY) 150 allow = true; 151 else if (iter->type == Filter::ALLOW) 152 allow = (!MatchPattern(text, base::UTF8ToUTF16("*=''"))); 153 else 154 allow = false; 155 } 156 } 157 return allow; 158 } 159 160 base::string16 AccessibilityTreeFormatter::FormatCoordinates( 161 const char* name, const char* x_name, const char* y_name, 162 const base::DictionaryValue& value) { 163 int x, y; 164 value.GetInteger(x_name, &x); 165 value.GetInteger(y_name, &y); 166 std::string xy_str(base::StringPrintf("%s=(%d, %d)", name, x, y)); 167 168 return base::UTF8ToUTF16(xy_str); 169 } 170 171 void AccessibilityTreeFormatter::WriteAttribute( 172 bool include_by_default, const std::string& attr, base::string16* line) { 173 WriteAttribute(include_by_default, base::UTF8ToUTF16(attr), line); 174 } 175 176 void AccessibilityTreeFormatter::WriteAttribute( 177 bool include_by_default, const base::string16& attr, base::string16* line) { 178 if (attr.empty()) 179 return; 180 if (!MatchesFilters(attr, include_by_default)) 181 return; 182 if (!line->empty()) 183 *line += base::ASCIIToUTF16(" "); 184 *line += attr; 185 } 186 187 } // namespace content 188