12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file. 42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/browser/accessibility/accessibility_tree_formatter.h" 62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/logging.h" 82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/memory/scoped_ptr.h" 92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/strings/string_number_conversions.h" 10868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string_util.h" 11868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/stringprintf.h" 12868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h" 132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/browser/accessibility/browser_accessibility_manager.h" 14010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "content/browser/renderer_host/render_widget_host_view_base.h" 15116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "content/browser/web_contents/web_contents_impl.h" 162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/browser/web_contents.h" 172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace content { 192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace { 202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const int kIndentSpaces = 4; 212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const char* kSkipString = "@NO_DUMP"; 22c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const char* kChildrenDictAttr = "children"; 232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)AccessibilityTreeFormatter::AccessibilityTreeFormatter( 26c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) BrowserAccessibility* root) 27c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) : root_(root) { 282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Initialize(); 292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static 322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)AccessibilityTreeFormatter* AccessibilityTreeFormatter::Create( 33116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch WebContents* web_contents) { 342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) BrowserAccessibilityManager* manager = 35116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch static_cast<WebContentsImpl*>(web_contents)-> 36116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch GetRootBrowserAccessibilityManager(); 372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!manager) 382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return NULL; 392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) BrowserAccessibility* root = manager->GetRoot(); 412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return new AccessibilityTreeFormatter(root); 422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)AccessibilityTreeFormatter::~AccessibilityTreeFormatter() { 462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 487d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)scoped_ptr<base::DictionaryValue> 49c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)AccessibilityTreeFormatter::BuildAccessibilityTree() { 507d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) scoped_ptr<base::DictionaryValue> dict(new base::DictionaryValue); 51c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) RecursiveBuildAccessibilityTree(*root_, dict.get()); 52c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return dict.Pass(); 53c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 54c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void AccessibilityTreeFormatter::FormatAccessibilityTree( 56a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) base::string16* contents) { 577d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) scoped_ptr<base::DictionaryValue> dict = BuildAccessibilityTree(); 58c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) RecursiveFormatAccessibilityTree(*(dict.get()), contents); 59c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 60c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 61c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void AccessibilityTreeFormatter::RecursiveBuildAccessibilityTree( 627d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) const BrowserAccessibility& node, base::DictionaryValue* dict) { 63c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) AddProperties(node, dict); 647d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 65eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::ListValue* children = new base::ListValue; 66c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) dict->Set(kChildrenDictAttr, children); 677d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 680f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) for (size_t i = 0; i < node.PlatformChildCount(); ++i) { 691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci BrowserAccessibility* child_node = node.PlatformGetChild(i); 707d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) base::DictionaryValue* child_dict = new base::DictionaryValue; 71c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) children->Append(child_dict); 72c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) RecursiveBuildAccessibilityTree(*child_node, child_dict); 73c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void AccessibilityTreeFormatter::RecursiveFormatAccessibilityTree( 77a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const base::DictionaryValue& dict, base::string16* contents, int depth) { 78a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) base::string16 line = 79a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ToString(dict, base::string16(depth * kIndentSpaces, ' ')); 805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (line.find(base::ASCIIToUTF16(kSkipString)) != base::string16::npos) 812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *contents += line; 847d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) const base::ListValue* children; 85c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) dict.GetList(kChildrenDictAttr, &children); 867d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) const base::DictionaryValue* child_dict; 87c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) for (size_t i = 0; i < children->GetSize(); i++) { 88c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) children->GetDictionary(i, &child_dict); 89c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) RecursiveFormatAccessibilityTree(*child_dict, contents, depth + 1); 902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 93a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch#if (!defined(OS_WIN) && !defined(OS_MACOSX) && !defined(OS_ANDROID)) 94c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void AccessibilityTreeFormatter::AddProperties(const BrowserAccessibility& node, 957d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) base::DictionaryValue* dict) { 96a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch dict->SetInteger("id", node.GetId()); 97c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 98c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 99a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)base::string16 AccessibilityTreeFormatter::ToString( 100a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const base::DictionaryValue& node, 101a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const base::string16& indent) { 102c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) int id_value; 103c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) node.GetInteger("id", &id_value); 104c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return indent + base::IntToString16(id_value) + 1055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::ASCIIToUTF16("\n"); 1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void AccessibilityTreeFormatter::Initialize() {} 1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static 1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const base::FilePath::StringType 1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)AccessibilityTreeFormatter::GetActualFileSuffix() { 113c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return base::FilePath::StringType(); 1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static 1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const base::FilePath::StringType 1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)AccessibilityTreeFormatter::GetExpectedFileSuffix() { 119c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return base::FilePath::StringType(); 1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static 1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const std::string AccessibilityTreeFormatter::GetAllowEmptyString() { 124c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return std::string(); 1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static 1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const std::string AccessibilityTreeFormatter::GetAllowString() { 129c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return std::string(); 1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static 1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const std::string AccessibilityTreeFormatter::GetDenyString() { 134c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return std::string(); 1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif 1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void AccessibilityTreeFormatter::SetFilters( 1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::vector<Filter>& filters) { 1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) filters_ = filters; 1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool AccessibilityTreeFormatter::MatchesFilters( 144a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const base::string16& text, bool default_result) const { 1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::vector<Filter>::const_iterator iter = filters_.begin(); 1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool allow = default_result; 1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (iter = filters_.begin(); iter != filters_.end(); ++iter) { 1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (MatchPattern(text, iter->match_str)) { 1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (iter->type == Filter::ALLOW_EMPTY) 1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) allow = true; 1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) else if (iter->type == Filter::ALLOW) 1525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) allow = (!MatchPattern(text, base::UTF8ToUTF16("*=''"))); 1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) else 1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) allow = false; 1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return allow; 1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 160a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)base::string16 AccessibilityTreeFormatter::FormatCoordinates( 161c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const char* name, const char* x_name, const char* y_name, 1627d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) const base::DictionaryValue& value) { 163c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) int x, y; 164c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) value.GetInteger(x_name, &x); 165c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) value.GetInteger(y_name, &y); 166c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) std::string xy_str(base::StringPrintf("%s=(%d, %d)", name, x, y)); 167c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 1685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return base::UTF8ToUTF16(xy_str); 169c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 170c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 171c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void AccessibilityTreeFormatter::WriteAttribute( 172a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) bool include_by_default, const std::string& attr, base::string16* line) { 1735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) WriteAttribute(include_by_default, base::UTF8ToUTF16(attr), line); 1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 176c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void AccessibilityTreeFormatter::WriteAttribute( 177a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) bool include_by_default, const base::string16& attr, base::string16* line) { 1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (attr.empty()) 1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!MatchesFilters(attr, include_by_default)) 1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 182c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!line->empty()) 1835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) *line += base::ASCIIToUTF16(" "); 184c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) *line += attr; 1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} // namespace content 188