1 // Copyright 2013 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 <string>
8
9 #include "base/android/jni_android.h"
10 #include "base/android/jni_string.h"
11 #include "base/files/file_path.h"
12 #include "base/json/json_writer.h"
13 #include "base/strings/string_util.h"
14 #include "base/strings/stringprintf.h"
15 #include "base/strings/utf_string_conversions.h"
16 #include "content/browser/accessibility/browser_accessibility_android.h"
17
18 using base::StringPrintf;
19
20 namespace content {
21
22 namespace {
23 const char* BOOL_ATTRIBUTES[] = {
24 "checkable",
25 "checked",
26 "clickable",
27 "collection",
28 "collection_item",
29 "content_invalid",
30 "disabled",
31 "dismissable",
32 "editable_text",
33 "focusable",
34 "focused",
35 "heading",
36 "hierarchical",
37 "invisible",
38 "multiline",
39 "password",
40 "range",
41 "scrollable",
42 "selected"
43 };
44
45 const char* STRING_ATTRIBUTES[] = {
46 "name"
47 };
48
49 const char* INT_ATTRIBUTES[] = {
50 "item_index",
51 "item_count",
52 "row_count",
53 "column_count",
54 "row_index",
55 "row_span",
56 "column_index",
57 "column_span",
58 "input_type",
59 "live_region_type",
60 "range_min",
61 "range_max",
62 "range_current_value",
63 };
64 }
65
Initialize()66 void AccessibilityTreeFormatter::Initialize() {
67 }
68
AddProperties(const BrowserAccessibility & node,base::DictionaryValue * dict)69 void AccessibilityTreeFormatter::AddProperties(
70 const BrowserAccessibility& node, base::DictionaryValue* dict) {
71 const BrowserAccessibilityAndroid* android_node =
72 static_cast<const BrowserAccessibilityAndroid*>(&node);
73
74 // Class name.
75 dict->SetString("class", android_node->GetClassName());
76
77 // Bool attributes.
78 dict->SetBoolean("checkable", android_node->IsCheckable());
79 dict->SetBoolean("checked", android_node->IsChecked());
80 dict->SetBoolean("clickable", android_node->IsClickable());
81 dict->SetBoolean("collection", android_node->IsCollection());
82 dict->SetBoolean("collection_item", android_node->IsCollectionItem());
83 dict->SetBoolean("disabled", !android_node->IsEnabled());
84 dict->SetBoolean("dismissable", android_node->IsDismissable());
85 dict->SetBoolean("editable_text", android_node->IsEditableText());
86 dict->SetBoolean("focusable", android_node->IsFocusable());
87 dict->SetBoolean("focused", android_node->IsFocused());
88 dict->SetBoolean("heading", android_node->IsHeading());
89 dict->SetBoolean("hierarchical", android_node->IsHierarchical());
90 dict->SetBoolean("invisible", !android_node->IsVisibleToUser());
91 dict->SetBoolean("multiline", android_node->IsMultiLine());
92 dict->SetBoolean("range", android_node->IsRangeType());
93 dict->SetBoolean("password", android_node->IsPassword());
94 dict->SetBoolean("scrollable", android_node->IsScrollable());
95 dict->SetBoolean("selected", android_node->IsSelected());
96
97 // String attributes.
98 dict->SetString("name", android_node->GetText());
99
100 // Int attributes.
101 dict->SetInteger("item_index", android_node->GetItemIndex());
102 dict->SetInteger("item_count", android_node->GetItemCount());
103 dict->SetInteger("row_count", android_node->RowCount());
104 dict->SetInteger("column_count", android_node->ColumnCount());
105 dict->SetInteger("row_index", android_node->RowIndex());
106 dict->SetInteger("row_span", android_node->RowSpan());
107 dict->SetInteger("column_index", android_node->ColumnIndex());
108 dict->SetInteger("column_span", android_node->ColumnSpan());
109 dict->SetInteger("input_type", android_node->AndroidInputType());
110 dict->SetInteger("live_region_type", android_node->AndroidLiveRegionType());
111 dict->SetInteger("range_min", static_cast<int>(android_node->RangeMin()));
112 dict->SetInteger("range_max", static_cast<int>(android_node->RangeMax()));
113 dict->SetInteger("range_current_value",
114 static_cast<int>(android_node->RangeCurrentValue()));
115 }
116
ToString(const base::DictionaryValue & dict,const base::string16 & indent)117 base::string16 AccessibilityTreeFormatter::ToString(
118 const base::DictionaryValue& dict,
119 const base::string16& indent) {
120 base::string16 line;
121
122 base::string16 class_value;
123 dict.GetString("class", &class_value);
124 WriteAttribute(true, base::UTF16ToUTF8(class_value), &line);
125
126 for (unsigned i = 0; i < arraysize(BOOL_ATTRIBUTES); i++) {
127 const char* attribute_name = BOOL_ATTRIBUTES[i];
128 bool value;
129 if (dict.GetBoolean(attribute_name, &value) && value)
130 WriteAttribute(true, attribute_name, &line);
131 }
132
133 for (unsigned i = 0; i < arraysize(STRING_ATTRIBUTES); i++) {
134 const char* attribute_name = STRING_ATTRIBUTES[i];
135 std::string value;
136 if (!dict.GetString(attribute_name, &value) || value.empty())
137 continue;
138 WriteAttribute(true,
139 StringPrintf("%s='%s'", attribute_name, value.c_str()),
140 &line);
141 }
142
143 for (unsigned i = 0; i < arraysize(INT_ATTRIBUTES); i++) {
144 const char* attribute_name = INT_ATTRIBUTES[i];
145 int value;
146 if (!dict.GetInteger(attribute_name, &value) || value == 0)
147 continue;
148 WriteAttribute(true,
149 StringPrintf("%s=%d", attribute_name, value),
150 &line);
151 }
152
153 return indent + line + base::ASCIIToUTF16("\n");
154 }
155
156 // static
157 const base::FilePath::StringType
GetActualFileSuffix()158 AccessibilityTreeFormatter::GetActualFileSuffix() {
159 return FILE_PATH_LITERAL("-actual-android.txt");
160 }
161
162 // static
163 const base::FilePath::StringType
GetExpectedFileSuffix()164 AccessibilityTreeFormatter::GetExpectedFileSuffix() {
165 return FILE_PATH_LITERAL("-expected-android.txt");
166 }
167
168 // static
GetAllowEmptyString()169 const std::string AccessibilityTreeFormatter::GetAllowEmptyString() {
170 return "@ANDROID-ALLOW-EMPTY:";
171 }
172
173 // static
GetAllowString()174 const std::string AccessibilityTreeFormatter::GetAllowString() {
175 return "@ANDROID-ALLOW:";
176 }
177
178 // static
GetDenyString()179 const std::string AccessibilityTreeFormatter::GetDenyString() {
180 return "@ANDROID-DENY:";
181 }
182
183 } // namespace content
184