| // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "content/browser/accessibility/accessibility_tree_formatter.h" |
| |
| #include "base/logging.h" |
| #include "base/memory/scoped_ptr.h" |
| #include "base/strings/string_number_conversions.h" |
| #include "base/strings/string_util.h" |
| #include "base/strings/stringprintf.h" |
| #include "base/strings/utf_string_conversions.h" |
| #include "content/browser/accessibility/browser_accessibility_manager.h" |
| #include "content/browser/renderer_host/render_widget_host_view_base.h" |
| #include "content/browser/web_contents/web_contents_impl.h" |
| #include "content/public/browser/web_contents.h" |
| |
| namespace content { |
| namespace { |
| const int kIndentSpaces = 4; |
| const char* kSkipString = "@NO_DUMP"; |
| const char* kChildrenDictAttr = "children"; |
| } |
| |
| AccessibilityTreeFormatter::AccessibilityTreeFormatter( |
| BrowserAccessibility* root) |
| : root_(root) { |
| Initialize(); |
| } |
| |
| // static |
| AccessibilityTreeFormatter* AccessibilityTreeFormatter::Create( |
| WebContents* web_contents) { |
| BrowserAccessibilityManager* manager = |
| static_cast<WebContentsImpl*>(web_contents)-> |
| GetRootBrowserAccessibilityManager(); |
| if (!manager) |
| return NULL; |
| |
| BrowserAccessibility* root = manager->GetRoot(); |
| return new AccessibilityTreeFormatter(root); |
| } |
| |
| |
| AccessibilityTreeFormatter::~AccessibilityTreeFormatter() { |
| } |
| |
| scoped_ptr<base::DictionaryValue> |
| AccessibilityTreeFormatter::BuildAccessibilityTree() { |
| scoped_ptr<base::DictionaryValue> dict(new base::DictionaryValue); |
| RecursiveBuildAccessibilityTree(*root_, dict.get()); |
| return dict.Pass(); |
| } |
| |
| void AccessibilityTreeFormatter::FormatAccessibilityTree( |
| base::string16* contents) { |
| scoped_ptr<base::DictionaryValue> dict = BuildAccessibilityTree(); |
| RecursiveFormatAccessibilityTree(*(dict.get()), contents); |
| } |
| |
| void AccessibilityTreeFormatter::RecursiveBuildAccessibilityTree( |
| const BrowserAccessibility& node, base::DictionaryValue* dict) { |
| AddProperties(node, dict); |
| |
| base::ListValue* children = new base::ListValue; |
| dict->Set(kChildrenDictAttr, children); |
| |
| for (size_t i = 0; i < node.PlatformChildCount(); ++i) { |
| BrowserAccessibility* child_node = node.PlatformGetChild(i); |
| base::DictionaryValue* child_dict = new base::DictionaryValue; |
| children->Append(child_dict); |
| RecursiveBuildAccessibilityTree(*child_node, child_dict); |
| } |
| } |
| |
| void AccessibilityTreeFormatter::RecursiveFormatAccessibilityTree( |
| const base::DictionaryValue& dict, base::string16* contents, int depth) { |
| base::string16 line = |
| ToString(dict, base::string16(depth * kIndentSpaces, ' ')); |
| if (line.find(base::ASCIIToUTF16(kSkipString)) != base::string16::npos) |
| return; |
| |
| *contents += line; |
| const base::ListValue* children; |
| dict.GetList(kChildrenDictAttr, &children); |
| const base::DictionaryValue* child_dict; |
| for (size_t i = 0; i < children->GetSize(); i++) { |
| children->GetDictionary(i, &child_dict); |
| RecursiveFormatAccessibilityTree(*child_dict, contents, depth + 1); |
| } |
| } |
| |
| #if (!defined(OS_WIN) && !defined(OS_MACOSX) && !defined(OS_ANDROID)) |
| void AccessibilityTreeFormatter::AddProperties(const BrowserAccessibility& node, |
| base::DictionaryValue* dict) { |
| dict->SetInteger("id", node.GetId()); |
| } |
| |
| base::string16 AccessibilityTreeFormatter::ToString( |
| const base::DictionaryValue& node, |
| const base::string16& indent) { |
| int id_value; |
| node.GetInteger("id", &id_value); |
| return indent + base::IntToString16(id_value) + |
| base::ASCIIToUTF16("\n"); |
| } |
| |
| void AccessibilityTreeFormatter::Initialize() {} |
| |
| // static |
| const base::FilePath::StringType |
| AccessibilityTreeFormatter::GetActualFileSuffix() { |
| return base::FilePath::StringType(); |
| } |
| |
| // static |
| const base::FilePath::StringType |
| AccessibilityTreeFormatter::GetExpectedFileSuffix() { |
| return base::FilePath::StringType(); |
| } |
| |
| // static |
| const std::string AccessibilityTreeFormatter::GetAllowEmptyString() { |
| return std::string(); |
| } |
| |
| // static |
| const std::string AccessibilityTreeFormatter::GetAllowString() { |
| return std::string(); |
| } |
| |
| // static |
| const std::string AccessibilityTreeFormatter::GetDenyString() { |
| return std::string(); |
| } |
| #endif |
| |
| void AccessibilityTreeFormatter::SetFilters( |
| const std::vector<Filter>& filters) { |
| filters_ = filters; |
| } |
| |
| bool AccessibilityTreeFormatter::MatchesFilters( |
| const base::string16& text, bool default_result) const { |
| std::vector<Filter>::const_iterator iter = filters_.begin(); |
| bool allow = default_result; |
| for (iter = filters_.begin(); iter != filters_.end(); ++iter) { |
| if (MatchPattern(text, iter->match_str)) { |
| if (iter->type == Filter::ALLOW_EMPTY) |
| allow = true; |
| else if (iter->type == Filter::ALLOW) |
| allow = (!MatchPattern(text, base::UTF8ToUTF16("*=''"))); |
| else |
| allow = false; |
| } |
| } |
| return allow; |
| } |
| |
| base::string16 AccessibilityTreeFormatter::FormatCoordinates( |
| const char* name, const char* x_name, const char* y_name, |
| const base::DictionaryValue& value) { |
| int x, y; |
| value.GetInteger(x_name, &x); |
| value.GetInteger(y_name, &y); |
| std::string xy_str(base::StringPrintf("%s=(%d, %d)", name, x, y)); |
| |
| return base::UTF8ToUTF16(xy_str); |
| } |
| |
| void AccessibilityTreeFormatter::WriteAttribute( |
| bool include_by_default, const std::string& attr, base::string16* line) { |
| WriteAttribute(include_by_default, base::UTF8ToUTF16(attr), line); |
| } |
| |
| void AccessibilityTreeFormatter::WriteAttribute( |
| bool include_by_default, const base::string16& attr, base::string16* line) { |
| if (attr.empty()) |
| return; |
| if (!MatchesFilters(attr, include_by_default)) |
| return; |
| if (!line->empty()) |
| *line += base::ASCIIToUTF16(" "); |
| *line += attr; |
| } |
| |
| } // namespace content |