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 66 void AccessibilityTreeFormatter::Initialize() { 67 } 68 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 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 158 AccessibilityTreeFormatter::GetActualFileSuffix() { 159 return FILE_PATH_LITERAL("-actual-android.txt"); 160 } 161 162 // static 163 const base::FilePath::StringType 164 AccessibilityTreeFormatter::GetExpectedFileSuffix() { 165 return FILE_PATH_LITERAL("-expected-android.txt"); 166 } 167 168 // static 169 const std::string AccessibilityTreeFormatter::GetAllowEmptyString() { 170 return "@ANDROID-ALLOW-EMPTY:"; 171 } 172 173 // static 174 const std::string AccessibilityTreeFormatter::GetAllowString() { 175 return "@ANDROID-ALLOW:"; 176 } 177 178 // static 179 const std::string AccessibilityTreeFormatter::GetDenyString() { 180 return "@ANDROID-DENY:"; 181 } 182 183 } // namespace content 184