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.
5 #include "ui/accessibility/ax_node_data.h"
9 #include "base/containers/hash_tables.h"
10 #include "base/strings/string_number_conversions.h"
11 #include "base/strings/string_util.h"
12 #include "base/strings/utf_string_conversions.h"
14 using base::DoubleToString
;
15 using base::IntToString
;
21 std::string
IntVectorToString(const std::vector
<int>& items
) {
23 for (size_t i
= 0; i
< items
.size(); ++i
) {
26 str
+= IntToString(items
[i
]);
31 } // Anonymous namespace
33 AXNodeData::AXNodeData()
35 role(AX_ROLE_UNKNOWN
),
39 AXNodeData::~AXNodeData() {
42 void AXNodeData::AddStringAttribute(
43 AXStringAttribute attribute
, const std::string
& value
) {
44 string_attributes
.push_back(std::make_pair(attribute
, value
));
47 void AXNodeData::AddIntAttribute(
48 AXIntAttribute attribute
, int value
) {
49 int_attributes
.push_back(std::make_pair(attribute
, value
));
52 void AXNodeData::AddFloatAttribute(
53 AXFloatAttribute attribute
, float value
) {
54 float_attributes
.push_back(std::make_pair(attribute
, value
));
57 void AXNodeData::AddBoolAttribute(
58 AXBoolAttribute attribute
, bool value
) {
59 bool_attributes
.push_back(std::make_pair(attribute
, value
));
62 void AXNodeData::AddIntListAttribute(
63 AXIntListAttribute attribute
, const std::vector
<int32
>& value
) {
64 intlist_attributes
.push_back(std::make_pair(attribute
, value
));
67 void AXNodeData::SetName(std::string name
) {
68 string_attributes
.push_back(std::make_pair(AX_ATTR_NAME
, name
));
71 void AXNodeData::SetValue(std::string value
) {
72 string_attributes
.push_back(std::make_pair(AX_ATTR_VALUE
, value
));
75 std::string
AXNodeData::ToString() const {
78 result
+= "id=" + IntToString(id
);
81 case ui::AX_ROLE_ALERT
: result
+= " ALERT"; break;
82 case ui::AX_ROLE_ALERT_DIALOG
: result
+= " ALERT_DIALOG"; break;
83 case ui::AX_ROLE_ANNOTATION
: result
+= " ANNOTATION"; break;
84 case ui::AX_ROLE_APPLICATION
: result
+= " APPLICATION"; break;
85 case ui::AX_ROLE_ARTICLE
: result
+= " ARTICLE"; break;
86 case ui::AX_ROLE_BANNER
: result
+= " BANNER"; break;
87 case ui::AX_ROLE_BROWSER
: result
+= " BROWSER"; break;
88 case ui::AX_ROLE_BUSY_INDICATOR
: result
+= " BUSY_INDICATOR"; break;
89 case ui::AX_ROLE_BUTTON
: result
+= " BUTTON"; break;
90 case ui::AX_ROLE_CANVAS
: result
+= " CANVAS"; break;
91 case ui::AX_ROLE_CELL
: result
+= " CELL"; break;
92 case ui::AX_ROLE_CHECK_BOX
: result
+= " CHECKBOX"; break;
93 case ui::AX_ROLE_COLOR_WELL
: result
+= " COLOR_WELL"; break;
94 case ui::AX_ROLE_COLUMN
: result
+= " COLUMN"; break;
95 case ui::AX_ROLE_COLUMN_HEADER
: result
+= " COLUMN_HEADER"; break;
96 case ui::AX_ROLE_COMBO_BOX
: result
+= " COMBO_BOX"; break;
97 case ui::AX_ROLE_COMPLEMENTARY
: result
+= " COMPLEMENTARY"; break;
98 case ui::AX_ROLE_CONTENT_INFO
: result
+= " CONTENTINFO"; break;
99 case ui::AX_ROLE_DEFINITION
: result
+= " DEFINITION"; break;
100 case ui::AX_ROLE_DESCRIPTION_LIST_DETAIL
: result
+= " DD"; break;
101 case ui::AX_ROLE_DESCRIPTION_LIST_TERM
: result
+= " DT"; break;
102 case ui::AX_ROLE_DIALOG
: result
+= " DIALOG"; break;
103 case ui::AX_ROLE_DIRECTORY
: result
+= " DIRECTORY"; break;
104 case ui::AX_ROLE_DISCLOSURE_TRIANGLE
:
105 result
+= " DISCLOSURE_TRIANGLE"; break;
106 case ui::AX_ROLE_DIV
: result
+= " DIV"; break;
107 case ui::AX_ROLE_DOCUMENT
: result
+= " DOCUMENT"; break;
108 case ui::AX_ROLE_DRAWER
: result
+= " DRAWER"; break;
109 case ui::AX_ROLE_EDITABLE_TEXT
: result
+= " EDITABLE_TEXT"; break;
110 case ui::AX_ROLE_FOOTER
: result
+= " FOOTER"; break;
111 case ui::AX_ROLE_FORM
: result
+= " FORM"; break;
112 case ui::AX_ROLE_GRID
: result
+= " GRID"; break;
113 case ui::AX_ROLE_GROUP
: result
+= " GROUP"; break;
114 case ui::AX_ROLE_GROW_AREA
: result
+= " GROW_AREA"; break;
115 case ui::AX_ROLE_HEADING
: result
+= " HEADING"; break;
116 case ui::AX_ROLE_HELP_TAG
: result
+= " HELP_TAG"; break;
117 case ui::AX_ROLE_HORIZONTAL_RULE
: result
+= " HORIZONTAL_RULE"; break;
118 case ui::AX_ROLE_IGNORED
: result
+= " IGNORED"; break;
119 case ui::AX_ROLE_IMAGE
: result
+= " IMAGE"; break;
120 case ui::AX_ROLE_IMAGE_MAP
: result
+= " IMAGE_MAP"; break;
121 case ui::AX_ROLE_IMAGE_MAP_LINK
: result
+= " IMAGE_MAP_LINK"; break;
122 case ui::AX_ROLE_INCREMENTOR
: result
+= " INCREMENTOR"; break;
123 case ui::AX_ROLE_INLINE_TEXT_BOX
: result
+= " INLINE_TEXT_BOX"; break;
124 case ui::AX_ROLE_LABEL
: result
+= " LABEL"; break;
125 case ui::AX_ROLE_LINK
: result
+= " LINK"; break;
126 case ui::AX_ROLE_LIST
: result
+= " LIST"; break;
127 case ui::AX_ROLE_LIST_BOX
: result
+= " LISTBOX"; break;
128 case ui::AX_ROLE_LIST_BOX_OPTION
: result
+= " LISTBOX_OPTION"; break;
129 case ui::AX_ROLE_LIST_ITEM
: result
+= " LIST_ITEM"; break;
130 case ui::AX_ROLE_LIST_MARKER
: result
+= " LIST_MARKER"; break;
131 case ui::AX_ROLE_LOG
: result
+= " LOG"; break;
132 case ui::AX_ROLE_MAIN
: result
+= " MAIN"; break;
133 case ui::AX_ROLE_MARQUEE
: result
+= " MARQUEE"; break;
134 case ui::AX_ROLE_MATH
: result
+= " MATH"; break;
135 case ui::AX_ROLE_MATTE
: result
+= " MATTE"; break;
136 case ui::AX_ROLE_MENU
: result
+= " MENU"; break;
137 case ui::AX_ROLE_MENU_BAR
: result
+= " MENU_BAR"; break;
138 case ui::AX_ROLE_MENU_BUTTON
: result
+= " MENU_BUTTON"; break;
139 case ui::AX_ROLE_MENU_ITEM
: result
+= " MENU_ITEM"; break;
140 case ui::AX_ROLE_MENU_LIST_OPTION
: result
+= " MENU_LIST_OPTION"; break;
141 case ui::AX_ROLE_MENU_LIST_POPUP
: result
+= " MENU_LIST_POPUP"; break;
142 case ui::AX_ROLE_NAVIGATION
: result
+= " NAVIGATION"; break;
143 case ui::AX_ROLE_NOTE
: result
+= " NOTE"; break;
144 case ui::AX_ROLE_OUTLINE
: result
+= " OUTLINE"; break;
145 case ui::AX_ROLE_PARAGRAPH
: result
+= " PARAGRAPH"; break;
146 case ui::AX_ROLE_POP_UP_BUTTON
: result
+= " POPUP_BUTTON"; break;
147 case ui::AX_ROLE_PRESENTATIONAL
: result
+= " PRESENTATIONAL"; break;
148 case ui::AX_ROLE_PROGRESS_INDICATOR
:
149 result
+= " PROGRESS_INDICATOR"; break;
150 case ui::AX_ROLE_RADIO_BUTTON
: result
+= " RADIO_BUTTON"; break;
151 case ui::AX_ROLE_RADIO_GROUP
: result
+= " RADIO_GROUP"; break;
152 case ui::AX_ROLE_REGION
: result
+= " REGION"; break;
153 case ui::AX_ROLE_ROOT_WEB_AREA
: result
+= " ROOT_WEB_AREA"; break;
154 case ui::AX_ROLE_ROW
: result
+= " ROW"; break;
155 case ui::AX_ROLE_ROW_HEADER
: result
+= " ROW_HEADER"; break;
156 case ui::AX_ROLE_RULER
: result
+= " RULER"; break;
157 case ui::AX_ROLE_RULER_MARKER
: result
+= " RULER_MARKER"; break;
158 case ui::AX_ROLE_SVG_ROOT
: result
+= " SVG_ROOT"; break;
159 case ui::AX_ROLE_SCROLL_AREA
: result
+= " SCROLLAREA"; break;
160 case ui::AX_ROLE_SCROLL_BAR
: result
+= " SCROLLBAR"; break;
161 case ui::AX_ROLE_SEARCH
: result
+= " SEARCH"; break;
162 case ui::AX_ROLE_SHEET
: result
+= " SHEET"; break;
163 case ui::AX_ROLE_SLIDER
: result
+= " SLIDER"; break;
164 case ui::AX_ROLE_SLIDER_THUMB
: result
+= " SLIDER_THUMB"; break;
165 case ui::AX_ROLE_SPIN_BUTTON
: result
+= " SPIN_BUTTON"; break;
166 case ui::AX_ROLE_SPIN_BUTTON_PART
: result
+= " SPIN_BUTTON_PART"; break;
167 case ui::AX_ROLE_SPLIT_GROUP
: result
+= " SPLIT_GROUP"; break;
168 case ui::AX_ROLE_SPLITTER
: result
+= " SPLITTER"; break;
169 case ui::AX_ROLE_STATIC_TEXT
: result
+= " STATIC_TEXT"; break;
170 case ui::AX_ROLE_STATUS
: result
+= " STATUS"; break;
171 case ui::AX_ROLE_SYSTEM_WIDE
: result
+= " SYSTEM_WIDE"; break;
172 case ui::AX_ROLE_TAB
: result
+= " TAB"; break;
173 case ui::AX_ROLE_TAB_LIST
: result
+= " TAB_LIST"; break;
174 case ui::AX_ROLE_TAB_PANEL
: result
+= " TAB_PANEL"; break;
175 case ui::AX_ROLE_TABLE
: result
+= " TABLE"; break;
176 case ui::AX_ROLE_TABLE_HEADER_CONTAINER
:
177 result
+= " TABLE_HDR_CONTAINER"; break;
178 case ui::AX_ROLE_TEXT_AREA
: result
+= " TEXTAREA"; break;
179 case ui::AX_ROLE_TEXT_FIELD
: result
+= " TEXT_FIELD"; break;
180 case ui::AX_ROLE_TIMER
: result
+= " TIMER"; break;
181 case ui::AX_ROLE_TOGGLE_BUTTON
: result
+= " TOGGLE_BUTTON"; break;
182 case ui::AX_ROLE_TOOLBAR
: result
+= " TOOLBAR"; break;
183 case ui::AX_ROLE_TREE
: result
+= " TREE"; break;
184 case ui::AX_ROLE_TREE_GRID
: result
+= " TREE_GRID"; break;
185 case ui::AX_ROLE_TREE_ITEM
: result
+= " TREE_ITEM"; break;
186 case ui::AX_ROLE_UNKNOWN
: result
+= " UNKNOWN"; break;
187 case ui::AX_ROLE_TOOLTIP
: result
+= " TOOLTIP"; break;
188 case ui::AX_ROLE_VALUE_INDICATOR
: result
+= " VALUE_INDICATOR"; break;
189 case ui::AX_ROLE_WEB_AREA
: result
+= " WEB_AREA"; break;
190 case ui::AX_ROLE_WINDOW
: result
+= " WINDOW"; break;
195 if (state
& (1 << ui::AX_STATE_BUSY
))
197 if (state
& (1 << ui::AX_STATE_CHECKED
))
198 result
+= " CHECKED";
199 if (state
& (1 << ui::AX_STATE_COLLAPSED
))
200 result
+= " COLLAPSED";
201 if (state
& (1 << ui::AX_STATE_EXPANDED
))
202 result
+= " EXPANDED";
203 if (state
& (1 << ui::AX_STATE_FOCUSABLE
))
204 result
+= " FOCUSABLE";
205 if (state
& (1 << ui::AX_STATE_FOCUSED
))
206 result
+= " FOCUSED";
207 if (state
& (1 << ui::AX_STATE_HASPOPUP
))
208 result
+= " HASPOPUP";
209 if (state
& (1 << ui::AX_STATE_HOVERED
))
210 result
+= " HOVERED";
211 if (state
& (1 << ui::AX_STATE_INDETERMINATE
))
212 result
+= " INDETERMINATE";
213 if (state
& (1 << ui::AX_STATE_INVISIBLE
))
214 result
+= " INVISIBLE";
215 if (state
& (1 << ui::AX_STATE_LINKED
))
217 if (state
& (1 << ui::AX_STATE_MULTISELECTABLE
))
218 result
+= " MULTISELECTABLE";
219 if (state
& (1 << ui::AX_STATE_OFFSCREEN
))
220 result
+= " OFFSCREEN";
221 if (state
& (1 << ui::AX_STATE_PRESSED
))
222 result
+= " PRESSED";
223 if (state
& (1 << ui::AX_STATE_PROTECTED
))
224 result
+= " PROTECTED";
225 if (state
& (1 << ui::AX_STATE_READONLY
))
226 result
+= " READONLY";
227 if (state
& (1 << ui::AX_STATE_REQUIRED
))
228 result
+= " REQUIRED";
229 if (state
& (1 << ui::AX_STATE_SELECTABLE
))
230 result
+= " SELECTABLE";
231 if (state
& (1 << ui::AX_STATE_SELECTED
))
232 result
+= " SELECTED";
233 if (state
& (1 << ui::AX_STATE_VERTICAL
))
234 result
+= " VERTICAL";
235 if (state
& (1 << ui::AX_STATE_VISITED
))
236 result
+= " VISITED";
238 result
+= " (" + IntToString(location
.x()) + ", " +
239 IntToString(location
.y()) + ")-(" +
240 IntToString(location
.width()) + ", " +
241 IntToString(location
.height()) + ")";
243 for (size_t i
= 0; i
< int_attributes
.size(); ++i
) {
244 std::string value
= IntToString(int_attributes
[i
].second
);
245 switch (int_attributes
[i
].first
) {
246 case AX_ATTR_SCROLL_X
:
247 result
+= " scroll_x=" + value
;
249 case AX_ATTR_SCROLL_X_MIN
:
250 result
+= " scroll_x_min=" + value
;
252 case AX_ATTR_SCROLL_X_MAX
:
253 result
+= " scroll_x_max=" + value
;
255 case AX_ATTR_SCROLL_Y
:
256 result
+= " scroll_y=" + value
;
258 case AX_ATTR_SCROLL_Y_MIN
:
259 result
+= " scroll_y_min=" + value
;
261 case AX_ATTR_SCROLL_Y_MAX
:
262 result
+= " scroll_y_max=" + value
;
264 case AX_ATTR_HIERARCHICAL_LEVEL
:
265 result
+= " level=" + value
;
267 case AX_ATTR_TEXT_SEL_START
:
268 result
+= " sel_start=" + value
;
270 case AX_ATTR_TEXT_SEL_END
:
271 result
+= " sel_end=" + value
;
273 case AX_ATTR_TABLE_ROW_COUNT
:
274 result
+= " rows=" + value
;
276 case AX_ATTR_TABLE_COLUMN_COUNT
:
277 result
+= " cols=" + value
;
279 case AX_ATTR_TABLE_CELL_COLUMN_INDEX
:
280 result
+= " col=" + value
;
282 case AX_ATTR_TABLE_CELL_ROW_INDEX
:
283 result
+= " row=" + value
;
285 case AX_ATTR_TABLE_CELL_COLUMN_SPAN
:
286 result
+= " colspan=" + value
;
288 case AX_ATTR_TABLE_CELL_ROW_SPAN
:
289 result
+= " rowspan=" + value
;
291 case AX_ATTR_TABLE_COLUMN_HEADER_ID
:
292 result
+= " column_header_id=" + value
;
294 case AX_ATTR_TABLE_COLUMN_INDEX
:
295 result
+= " column_index=" + value
;
297 case AX_ATTR_TABLE_HEADER_ID
:
298 result
+= " header_id=" + value
;
300 case AX_ATTR_TABLE_ROW_HEADER_ID
:
301 result
+= " row_header_id=" + value
;
303 case AX_ATTR_TABLE_ROW_INDEX
:
304 result
+= " row_index=" + value
;
306 case AX_ATTR_TITLE_UI_ELEMENT
:
307 result
+= " title_elem=" + value
;
309 case AX_ATTR_COLOR_VALUE_RED
:
310 result
+= " color_value_red=" + value
;
312 case AX_ATTR_COLOR_VALUE_GREEN
:
313 result
+= " color_value_green=" + value
;
315 case AX_ATTR_COLOR_VALUE_BLUE
:
316 result
+= " color_value_blue=" + value
;
318 case AX_ATTR_TEXT_DIRECTION
:
319 switch (int_attributes
[i
].second
) {
320 case AX_TEXT_DIRECTION_LR
:
322 result
+= " text_direction=lr";
324 case AX_TEXT_DIRECTION_RL
:
325 result
+= " text_direction=rl";
327 case AX_TEXT_DIRECTION_TB
:
328 result
+= " text_direction=tb";
330 case AX_TEXT_DIRECTION_BT
:
331 result
+= " text_direction=bt";
338 for (size_t i
= 0; i
< string_attributes
.size(); ++i
) {
339 std::string value
= string_attributes
[i
].second
;
340 switch (string_attributes
[i
].first
) {
341 case AX_ATTR_DOC_URL
:
342 result
+= " doc_url=" + value
;
344 case AX_ATTR_DOC_TITLE
:
345 result
+= " doc_title=" + value
;
347 case AX_ATTR_DOC_MIMETYPE
:
348 result
+= " doc_mimetype=" + value
;
350 case AX_ATTR_DOC_DOCTYPE
:
351 result
+= " doc_doctype=" + value
;
353 case AX_ATTR_ACCESS_KEY
:
354 result
+= " access_key=" + value
;
357 result
+= " action=" + value
;
359 case AX_ATTR_DESCRIPTION
:
360 result
+= " description=" + value
;
362 case AX_ATTR_DISPLAY
:
363 result
+= " display=" + value
;
366 result
+= " help=" + value
;
368 case AX_ATTR_HTML_TAG
:
369 result
+= " html_tag=" + value
;
371 case AX_ATTR_LIVE_RELEVANT
:
372 result
+= " relevant=" + value
;
374 case AX_ATTR_LIVE_STATUS
:
375 result
+= " live=" + value
;
377 case AX_ATTR_CONTAINER_LIVE_RELEVANT
:
378 result
+= " container_relevant=" + value
;
380 case AX_ATTR_CONTAINER_LIVE_STATUS
:
381 result
+= " container_live=" + value
;
384 result
+= " role=" + value
;
386 case AX_ATTR_SHORTCUT
:
387 result
+= " shortcut=" + value
;
390 result
+= " url=" + value
;
393 result
+= " name=" + value
;
396 result
+= " value=" + value
;
401 for (size_t i
= 0; i
< float_attributes
.size(); ++i
) {
402 std::string value
= DoubleToString(float_attributes
[i
].second
);
403 switch (float_attributes
[i
].first
) {
404 case AX_ATTR_DOC_LOADING_PROGRESS
:
405 result
+= " doc_progress=" + value
;
407 case AX_ATTR_VALUE_FOR_RANGE
:
408 result
+= " value_for_range=" + value
;
410 case AX_ATTR_MAX_VALUE_FOR_RANGE
:
411 result
+= " max_value=" + value
;
413 case AX_ATTR_MIN_VALUE_FOR_RANGE
:
414 result
+= " min_value=" + value
;
419 for (size_t i
= 0; i
< bool_attributes
.size(); ++i
) {
420 std::string value
= bool_attributes
[i
].second
? "true" : "false";
421 switch (bool_attributes
[i
].first
) {
422 case AX_ATTR_DOC_LOADED
:
423 result
+= " doc_loaded=" + value
;
425 case AX_ATTR_BUTTON_MIXED
:
426 result
+= " mixed=" + value
;
428 case AX_ATTR_LIVE_ATOMIC
:
429 result
+= " atomic=" + value
;
431 case AX_ATTR_LIVE_BUSY
:
432 result
+= " busy=" + value
;
434 case AX_ATTR_CONTAINER_LIVE_ATOMIC
:
435 result
+= " container_atomic=" + value
;
437 case AX_ATTR_CONTAINER_LIVE_BUSY
:
438 result
+= " container_busy=" + value
;
440 case AX_ATTR_ARIA_READONLY
:
441 result
+= " aria_readonly=" + value
;
443 case AX_ATTR_CAN_SET_VALUE
:
444 result
+= " can_set_value=" + value
;
446 case AX_ATTR_UPDATE_LOCATION_ONLY
:
447 result
+= " update_location_only=" + value
;
449 case AX_ATTR_CANVAS_HAS_FALLBACK
:
450 result
+= " has_fallback=" + value
;
455 for (size_t i
= 0; i
< intlist_attributes
.size(); ++i
) {
456 const std::vector
<int32
>& values
= intlist_attributes
[i
].second
;
457 switch (intlist_attributes
[i
].first
) {
458 case AX_ATTR_INDIRECT_CHILD_IDS
:
459 result
+= " indirect_child_ids=" + IntVectorToString(values
);
461 case AX_ATTR_LINE_BREAKS
:
462 result
+= " line_breaks=" + IntVectorToString(values
);
464 case AX_ATTR_CELL_IDS
:
465 result
+= " cell_ids=" + IntVectorToString(values
);
467 case AX_ATTR_UNIQUE_CELL_IDS
:
468 result
+= " unique_cell_ids=" + IntVectorToString(values
);
470 case AX_ATTR_CHARACTER_OFFSETS
:
471 result
+= " character_offsets=" + IntVectorToString(values
);
473 case AX_ATTR_WORD_STARTS
:
474 result
+= " word_starts=" + IntVectorToString(values
);
476 case AX_ATTR_WORD_ENDS
:
477 result
+= " word_ends=" + IntVectorToString(values
);
482 if (!child_ids
.empty())
483 result
+= " child_ids=" + IntVectorToString(child_ids
);