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 "ui/accessibility/ax_node_data.h" 6 7#include <set> 8 9#include "base/strings/string_number_conversions.h" 10#include "base/strings/string_util.h" 11#include "base/strings/utf_string_conversions.h" 12 13using base::DoubleToString; 14using base::IntToString; 15 16namespace ui { 17 18namespace { 19 20std::string IntVectorToString(const std::vector<int>& items) { 21 std::string str; 22 for (size_t i = 0; i < items.size(); ++i) { 23 if (i > 0) 24 str += ","; 25 str += IntToString(items[i]); 26 } 27 return str; 28} 29 30} // Anonymous namespace 31 32AXNodeData::AXNodeData() 33 : id(-1), 34 role(AX_ROLE_UNKNOWN), 35 state(-1) { 36} 37 38AXNodeData::~AXNodeData() { 39} 40 41void AXNodeData::AddStringAttribute( 42 AXStringAttribute attribute, const std::string& value) { 43 string_attributes.push_back(std::make_pair(attribute, value)); 44} 45 46void AXNodeData::AddIntAttribute( 47 AXIntAttribute attribute, int value) { 48 int_attributes.push_back(std::make_pair(attribute, value)); 49} 50 51void AXNodeData::AddFloatAttribute( 52 AXFloatAttribute attribute, float value) { 53 float_attributes.push_back(std::make_pair(attribute, value)); 54} 55 56void AXNodeData::AddBoolAttribute( 57 AXBoolAttribute attribute, bool value) { 58 bool_attributes.push_back(std::make_pair(attribute, value)); 59} 60 61void AXNodeData::AddIntListAttribute( 62 AXIntListAttribute attribute, const std::vector<int32>& value) { 63 intlist_attributes.push_back(std::make_pair(attribute, value)); 64} 65 66void AXNodeData::SetName(std::string name) { 67 string_attributes.push_back(std::make_pair(AX_ATTR_NAME, name)); 68} 69 70void AXNodeData::SetValue(std::string value) { 71 string_attributes.push_back(std::make_pair(AX_ATTR_VALUE, value)); 72} 73 74std::string AXNodeData::ToString() const { 75 std::string result; 76 77 result += "id=" + IntToString(id); 78 result += " " + ui::ToString(role); 79 80 if (state & (1 << ui::AX_STATE_BUSY)) 81 result += " BUSY"; 82 if (state & (1 << ui::AX_STATE_CHECKED)) 83 result += " CHECKED"; 84 if (state & (1 << ui::AX_STATE_COLLAPSED)) 85 result += " COLLAPSED"; 86 if (state & (1 << ui::AX_STATE_EXPANDED)) 87 result += " EXPANDED"; 88 if (state & (1 << ui::AX_STATE_FOCUSABLE)) 89 result += " FOCUSABLE"; 90 if (state & (1 << ui::AX_STATE_FOCUSED)) 91 result += " FOCUSED"; 92 if (state & (1 << ui::AX_STATE_HASPOPUP)) 93 result += " HASPOPUP"; 94 if (state & (1 << ui::AX_STATE_HOVERED)) 95 result += " HOVERED"; 96 if (state & (1 << ui::AX_STATE_INDETERMINATE)) 97 result += " INDETERMINATE"; 98 if (state & (1 << ui::AX_STATE_INVISIBLE)) 99 result += " INVISIBLE"; 100 if (state & (1 << ui::AX_STATE_LINKED)) 101 result += " LINKED"; 102 if (state & (1 << ui::AX_STATE_MULTISELECTABLE)) 103 result += " MULTISELECTABLE"; 104 if (state & (1 << ui::AX_STATE_OFFSCREEN)) 105 result += " OFFSCREEN"; 106 if (state & (1 << ui::AX_STATE_PRESSED)) 107 result += " PRESSED"; 108 if (state & (1 << ui::AX_STATE_PROTECTED)) 109 result += " PROTECTED"; 110 if (state & (1 << ui::AX_STATE_READ_ONLY)) 111 result += " READONLY"; 112 if (state & (1 << ui::AX_STATE_REQUIRED)) 113 result += " REQUIRED"; 114 if (state & (1 << ui::AX_STATE_SELECTABLE)) 115 result += " SELECTABLE"; 116 if (state & (1 << ui::AX_STATE_SELECTED)) 117 result += " SELECTED"; 118 if (state & (1 << ui::AX_STATE_VERTICAL)) 119 result += " VERTICAL"; 120 if (state & (1 << ui::AX_STATE_VISITED)) 121 result += " VISITED"; 122 123 result += " (" + IntToString(location.x()) + ", " + 124 IntToString(location.y()) + ")-(" + 125 IntToString(location.width()) + ", " + 126 IntToString(location.height()) + ")"; 127 128 for (size_t i = 0; i < int_attributes.size(); ++i) { 129 std::string value = IntToString(int_attributes[i].second); 130 switch (int_attributes[i].first) { 131 case AX_ATTR_SCROLL_X: 132 result += " scroll_x=" + value; 133 break; 134 case AX_ATTR_SCROLL_X_MIN: 135 result += " scroll_x_min=" + value; 136 break; 137 case AX_ATTR_SCROLL_X_MAX: 138 result += " scroll_x_max=" + value; 139 break; 140 case AX_ATTR_SCROLL_Y: 141 result += " scroll_y=" + value; 142 break; 143 case AX_ATTR_SCROLL_Y_MIN: 144 result += " scroll_y_min=" + value; 145 break; 146 case AX_ATTR_SCROLL_Y_MAX: 147 result += " scroll_y_max=" + value; 148 break; 149 case AX_ATTR_HIERARCHICAL_LEVEL: 150 result += " level=" + value; 151 break; 152 case AX_ATTR_TEXT_SEL_START: 153 result += " sel_start=" + value; 154 break; 155 case AX_ATTR_TEXT_SEL_END: 156 result += " sel_end=" + value; 157 break; 158 case AX_ATTR_TABLE_ROW_COUNT: 159 result += " rows=" + value; 160 break; 161 case AX_ATTR_TABLE_COLUMN_COUNT: 162 result += " cols=" + value; 163 break; 164 case AX_ATTR_TABLE_CELL_COLUMN_INDEX: 165 result += " col=" + value; 166 break; 167 case AX_ATTR_TABLE_CELL_ROW_INDEX: 168 result += " row=" + value; 169 break; 170 case AX_ATTR_TABLE_CELL_COLUMN_SPAN: 171 result += " colspan=" + value; 172 break; 173 case AX_ATTR_TABLE_CELL_ROW_SPAN: 174 result += " rowspan=" + value; 175 break; 176 case AX_ATTR_TABLE_COLUMN_HEADER_ID: 177 result += " column_header_id=" + value; 178 break; 179 case AX_ATTR_TABLE_COLUMN_INDEX: 180 result += " column_index=" + value; 181 break; 182 case AX_ATTR_TABLE_HEADER_ID: 183 result += " header_id=" + value; 184 break; 185 case AX_ATTR_TABLE_ROW_HEADER_ID: 186 result += " row_header_id=" + value; 187 break; 188 case AX_ATTR_TABLE_ROW_INDEX: 189 result += " row_index=" + value; 190 break; 191 case AX_ATTR_TITLE_UI_ELEMENT: 192 result += " title_elem=" + value; 193 break; 194 case AX_ATTR_ACTIVEDESCENDANT_ID: 195 result += " activedescendant=" + value; 196 break; 197 case AX_ATTR_COLOR_VALUE_RED: 198 result += " color_value_red=" + value; 199 break; 200 case AX_ATTR_COLOR_VALUE_GREEN: 201 result += " color_value_green=" + value; 202 break; 203 case AX_ATTR_COLOR_VALUE_BLUE: 204 result += " color_value_blue=" + value; 205 break; 206 case AX_ATTR_TEXT_DIRECTION: 207 switch (int_attributes[i].second) { 208 case AX_TEXT_DIRECTION_LR: 209 default: 210 result += " text_direction=lr"; 211 break; 212 case AX_TEXT_DIRECTION_RL: 213 result += " text_direction=rl"; 214 break; 215 case AX_TEXT_DIRECTION_TB: 216 result += " text_direction=tb"; 217 break; 218 case AX_TEXT_DIRECTION_BT: 219 result += " text_direction=bt"; 220 break; 221 } 222 break; 223 case AX_INT_ATTRIBUTE_NONE: 224 break; 225 } 226 } 227 228 for (size_t i = 0; i < string_attributes.size(); ++i) { 229 std::string value = string_attributes[i].second; 230 switch (string_attributes[i].first) { 231 case AX_ATTR_DOC_URL: 232 result += " doc_url=" + value; 233 break; 234 case AX_ATTR_DOC_TITLE: 235 result += " doc_title=" + value; 236 break; 237 case AX_ATTR_DOC_MIMETYPE: 238 result += " doc_mimetype=" + value; 239 break; 240 case AX_ATTR_DOC_DOCTYPE: 241 result += " doc_doctype=" + value; 242 break; 243 case AX_ATTR_ACCESS_KEY: 244 result += " access_key=" + value; 245 break; 246 case AX_ATTR_ACTION: 247 result += " action=" + value; 248 break; 249 case AX_ATTR_DESCRIPTION: 250 result += " description=" + value; 251 break; 252 case AX_ATTR_DISPLAY: 253 result += " display=" + value; 254 break; 255 case AX_ATTR_HELP: 256 result += " help=" + value; 257 break; 258 case AX_ATTR_HTML_TAG: 259 result += " html_tag=" + value; 260 break; 261 case AX_ATTR_LIVE_RELEVANT: 262 result += " relevant=" + value; 263 break; 264 case AX_ATTR_LIVE_STATUS: 265 result += " live=" + value; 266 break; 267 case AX_ATTR_CONTAINER_LIVE_RELEVANT: 268 result += " container_relevant=" + value; 269 break; 270 case AX_ATTR_CONTAINER_LIVE_STATUS: 271 result += " container_live=" + value; 272 break; 273 case AX_ATTR_ROLE: 274 result += " role=" + value; 275 break; 276 case AX_ATTR_SHORTCUT: 277 result += " shortcut=" + value; 278 break; 279 case AX_ATTR_URL: 280 result += " url=" + value; 281 break; 282 case AX_ATTR_NAME: 283 result += " name=" + value; 284 break; 285 case AX_ATTR_VALUE: 286 result += " value=" + value; 287 break; 288 case AX_STRING_ATTRIBUTE_NONE: 289 break; 290 } 291 } 292 293 for (size_t i = 0; i < float_attributes.size(); ++i) { 294 std::string value = DoubleToString(float_attributes[i].second); 295 switch (float_attributes[i].first) { 296 case AX_ATTR_DOC_LOADING_PROGRESS: 297 result += " doc_progress=" + value; 298 break; 299 case AX_ATTR_VALUE_FOR_RANGE: 300 result += " value_for_range=" + value; 301 break; 302 case AX_ATTR_MAX_VALUE_FOR_RANGE: 303 result += " max_value=" + value; 304 break; 305 case AX_ATTR_MIN_VALUE_FOR_RANGE: 306 result += " min_value=" + value; 307 break; 308 case AX_FLOAT_ATTRIBUTE_NONE: 309 break; 310 } 311 } 312 313 for (size_t i = 0; i < bool_attributes.size(); ++i) { 314 std::string value = bool_attributes[i].second ? "true" : "false"; 315 switch (bool_attributes[i].first) { 316 case AX_ATTR_DOC_LOADED: 317 result += " doc_loaded=" + value; 318 break; 319 case AX_ATTR_BUTTON_MIXED: 320 result += " mixed=" + value; 321 break; 322 case AX_ATTR_LIVE_ATOMIC: 323 result += " atomic=" + value; 324 break; 325 case AX_ATTR_LIVE_BUSY: 326 result += " busy=" + value; 327 break; 328 case AX_ATTR_CONTAINER_LIVE_ATOMIC: 329 result += " container_atomic=" + value; 330 break; 331 case AX_ATTR_CONTAINER_LIVE_BUSY: 332 result += " container_busy=" + value; 333 break; 334 case AX_ATTR_ARIA_READONLY: 335 result += " aria_readonly=" + value; 336 break; 337 case AX_ATTR_CAN_SET_VALUE: 338 result += " can_set_value=" + value; 339 break; 340 case AX_ATTR_UPDATE_LOCATION_ONLY: 341 result += " update_location_only=" + value; 342 break; 343 case AX_ATTR_CANVAS_HAS_FALLBACK: 344 result += " has_fallback=" + value; 345 break; 346 case AX_BOOL_ATTRIBUTE_NONE: 347 break; 348 } 349 } 350 351 for (size_t i = 0; i < intlist_attributes.size(); ++i) { 352 const std::vector<int32>& values = intlist_attributes[i].second; 353 switch (intlist_attributes[i].first) { 354 case AX_ATTR_INDIRECT_CHILD_IDS: 355 result += " indirect_child_ids=" + IntVectorToString(values); 356 break; 357 case AX_ATTR_CONTROLS_IDS: 358 result += " controls_ids=" + IntVectorToString(values); 359 break; 360 case AX_ATTR_DESCRIBEDBY_IDS: 361 result += " describedby_ids=" + IntVectorToString(values); 362 break; 363 case AX_ATTR_FLOWTO_IDS: 364 result += " flowto_ids=" + IntVectorToString(values); 365 break; 366 case AX_ATTR_LABELLEDBY_IDS: 367 result += " labelledby_ids=" + IntVectorToString(values); 368 break; 369 case AX_ATTR_OWNS_IDS: 370 result += " owns_ids=" + IntVectorToString(values); 371 break; 372 case AX_ATTR_LINE_BREAKS: 373 result += " line_breaks=" + IntVectorToString(values); 374 break; 375 case AX_ATTR_CELL_IDS: 376 result += " cell_ids=" + IntVectorToString(values); 377 break; 378 case AX_ATTR_UNIQUE_CELL_IDS: 379 result += " unique_cell_ids=" + IntVectorToString(values); 380 break; 381 case AX_ATTR_CHARACTER_OFFSETS: 382 result += " character_offsets=" + IntVectorToString(values); 383 break; 384 case AX_ATTR_WORD_STARTS: 385 result += " word_starts=" + IntVectorToString(values); 386 break; 387 case AX_ATTR_WORD_ENDS: 388 result += " word_ends=" + IntVectorToString(values); 389 break; 390 case AX_INT_LIST_ATTRIBUTE_NONE: 391 break; 392 } 393 } 394 395 if (!child_ids.empty()) 396 result += " child_ids=" + IntVectorToString(child_ids); 397 398 return result; 399} 400 401} // namespace ui 402