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/strings/string_number_conversions.h"
10 #include "base/strings/string_util.h"
11 #include "base/strings/stringprintf.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
);
79 result
+= " " + ui::ToString(role
);
81 if (state
& (1 << ui::AX_STATE_BUSY
))
83 if (state
& (1 << ui::AX_STATE_CHECKED
))
85 if (state
& (1 << ui::AX_STATE_COLLAPSED
))
86 result
+= " COLLAPSED";
87 if (state
& (1 << ui::AX_STATE_EXPANDED
))
88 result
+= " EXPANDED";
89 if (state
& (1 << ui::AX_STATE_FOCUSABLE
))
90 result
+= " FOCUSABLE";
91 if (state
& (1 << ui::AX_STATE_FOCUSED
))
93 if (state
& (1 << ui::AX_STATE_HASPOPUP
))
94 result
+= " HASPOPUP";
95 if (state
& (1 << ui::AX_STATE_HOVERED
))
97 if (state
& (1 << ui::AX_STATE_INDETERMINATE
))
98 result
+= " INDETERMINATE";
99 if (state
& (1 << ui::AX_STATE_INVISIBLE
))
100 result
+= " INVISIBLE";
101 if (state
& (1 << ui::AX_STATE_LINKED
))
103 if (state
& (1 << ui::AX_STATE_MULTISELECTABLE
))
104 result
+= " MULTISELECTABLE";
105 if (state
& (1 << ui::AX_STATE_OFFSCREEN
))
106 result
+= " OFFSCREEN";
107 if (state
& (1 << ui::AX_STATE_PRESSED
))
108 result
+= " PRESSED";
109 if (state
& (1 << ui::AX_STATE_PROTECTED
))
110 result
+= " PROTECTED";
111 if (state
& (1 << ui::AX_STATE_READ_ONLY
))
112 result
+= " READONLY";
113 if (state
& (1 << ui::AX_STATE_REQUIRED
))
114 result
+= " REQUIRED";
115 if (state
& (1 << ui::AX_STATE_SELECTABLE
))
116 result
+= " SELECTABLE";
117 if (state
& (1 << ui::AX_STATE_SELECTED
))
118 result
+= " SELECTED";
119 if (state
& (1 << ui::AX_STATE_VERTICAL
))
120 result
+= " VERTICAL";
121 if (state
& (1 << ui::AX_STATE_VISITED
))
122 result
+= " VISITED";
124 result
+= " (" + IntToString(location
.x()) + ", " +
125 IntToString(location
.y()) + ")-(" +
126 IntToString(location
.width()) + ", " +
127 IntToString(location
.height()) + ")";
129 for (size_t i
= 0; i
< int_attributes
.size(); ++i
) {
130 std::string value
= IntToString(int_attributes
[i
].second
);
131 switch (int_attributes
[i
].first
) {
132 case AX_ATTR_SCROLL_X
:
133 result
+= " scroll_x=" + value
;
135 case AX_ATTR_SCROLL_X_MIN
:
136 result
+= " scroll_x_min=" + value
;
138 case AX_ATTR_SCROLL_X_MAX
:
139 result
+= " scroll_x_max=" + value
;
141 case AX_ATTR_SCROLL_Y
:
142 result
+= " scroll_y=" + value
;
144 case AX_ATTR_SCROLL_Y_MIN
:
145 result
+= " scroll_y_min=" + value
;
147 case AX_ATTR_SCROLL_Y_MAX
:
148 result
+= " scroll_y_max=" + value
;
150 case AX_ATTR_HIERARCHICAL_LEVEL
:
151 result
+= " level=" + value
;
153 case AX_ATTR_TEXT_SEL_START
:
154 result
+= " sel_start=" + value
;
156 case AX_ATTR_TEXT_SEL_END
:
157 result
+= " sel_end=" + value
;
159 case AX_ATTR_TABLE_ROW_COUNT
:
160 result
+= " rows=" + value
;
162 case AX_ATTR_TABLE_COLUMN_COUNT
:
163 result
+= " cols=" + value
;
165 case AX_ATTR_TABLE_CELL_COLUMN_INDEX
:
166 result
+= " col=" + value
;
168 case AX_ATTR_TABLE_CELL_ROW_INDEX
:
169 result
+= " row=" + value
;
171 case AX_ATTR_TABLE_CELL_COLUMN_SPAN
:
172 result
+= " colspan=" + value
;
174 case AX_ATTR_TABLE_CELL_ROW_SPAN
:
175 result
+= " rowspan=" + value
;
177 case AX_ATTR_TABLE_COLUMN_HEADER_ID
:
178 result
+= " column_header_id=" + value
;
180 case AX_ATTR_TABLE_COLUMN_INDEX
:
181 result
+= " column_index=" + value
;
183 case AX_ATTR_TABLE_HEADER_ID
:
184 result
+= " header_id=" + value
;
186 case AX_ATTR_TABLE_ROW_HEADER_ID
:
187 result
+= " row_header_id=" + value
;
189 case AX_ATTR_TABLE_ROW_INDEX
:
190 result
+= " row_index=" + value
;
192 case AX_ATTR_SORT_DIRECTION
:
193 switch (int_attributes
[i
].second
) {
194 case AX_SORT_DIRECTION_UNSORTED
:
195 result
+= " sort_direction=none";
197 case AX_SORT_DIRECTION_ASCENDING
:
198 result
+= " sort_direction=ascending";
200 case AX_SORT_DIRECTION_DESCENDING
:
201 result
+= " sort_direction=descending";
203 case AX_SORT_DIRECTION_OTHER
:
204 result
+= " sort_direction=other";
208 case AX_ATTR_TITLE_UI_ELEMENT
:
209 result
+= " title_elem=" + value
;
211 case AX_ATTR_ACTIVEDESCENDANT_ID
:
212 result
+= " activedescendant=" + value
;
214 case AX_ATTR_TREE_ID
:
215 result
+= " tree_id=" + value
;
217 case AX_ATTR_CHILD_TREE_ID
:
218 result
+= " child_tree_id=" + value
;
220 case AX_ATTR_COLOR_VALUE
:
221 result
+= base::StringPrintf(" color_value=&%X",
222 int_attributes
[i
].second
);
224 case AX_ATTR_BACKGROUND_COLOR
:
225 result
+= base::StringPrintf(" background_color=&%X",
226 int_attributes
[i
].second
);
229 result
+= base::StringPrintf(" color=&%X", int_attributes
[i
].second
);
231 case AX_ATTR_TEXT_DIRECTION
:
232 switch (int_attributes
[i
].second
) {
233 case AX_TEXT_DIRECTION_LTR
:
234 result
+= " text_direction=ltr";
236 case AX_TEXT_DIRECTION_RTL
:
237 result
+= " text_direction=rtl";
239 case AX_TEXT_DIRECTION_TTB
:
240 result
+= " text_direction=ttb";
242 case AX_TEXT_DIRECTION_BTT
:
243 result
+= " text_direction=btt";
246 case AX_ATTR_TEXT_STYLE
: {
247 unsigned int text_style
= int_attributes
[i
].second
;
248 if (text_style
== AX_TEXT_STYLE_NONE
)
250 std::string
text_style_value(" text_style=");
251 if (text_style
& AX_TEXT_STYLE_BOLD
)
252 text_style_value
+= "bold,";
253 if (text_style
& AX_TEXT_STYLE_ITALIC
)
254 text_style_value
+= "italic,";
255 if (text_style
& AX_TEXT_STYLE_UNDERLINE
)
256 text_style_value
+= "underline,";
257 if (text_style
& AX_TEXT_STYLE_LINE_THROUGH
)
258 text_style_value
+= "line-through,";
259 result
+= text_style_value
.substr(0, text_style_value
.size() - 1);;
262 case AX_ATTR_SET_SIZE
:
263 result
+= " setsize=" + value
;
265 case AX_ATTR_POS_IN_SET
:
266 result
+= " posinset=" + value
;
268 case AX_ATTR_INVALID_STATE
:
269 switch (int_attributes
[i
].second
) {
270 case AX_INVALID_STATE_FALSE
:
271 result
+= " invalid_state=false";
273 case AX_INVALID_STATE_TRUE
:
274 result
+= " invalid_state=true";
276 case AX_INVALID_STATE_SPELLING
:
277 result
+= " invalid_state=spelling";
279 case AX_INVALID_STATE_GRAMMAR
:
280 result
+= " invalid_state=grammar";
282 case AX_INVALID_STATE_OTHER
:
283 result
+= " invalid_state=other";
287 case AX_INT_ATTRIBUTE_NONE
:
292 for (size_t i
= 0; i
< string_attributes
.size(); ++i
) {
293 std::string value
= string_attributes
[i
].second
;
294 switch (string_attributes
[i
].first
) {
295 case AX_ATTR_DOC_URL
:
296 result
+= " doc_url=" + value
;
298 case AX_ATTR_DOC_TITLE
:
299 result
+= " doc_title=" + value
;
301 case AX_ATTR_DOC_MIMETYPE
:
302 result
+= " doc_mimetype=" + value
;
304 case AX_ATTR_DOC_DOCTYPE
:
305 result
+= " doc_doctype=" + value
;
307 case AX_ATTR_ACCESS_KEY
:
308 result
+= " access_key=" + value
;
311 result
+= " action=" + value
;
313 case AX_ATTR_AUTO_COMPLETE
:
314 result
+= " autocomplete=" + value
;
316 case AX_ATTR_DESCRIPTION
:
317 result
+= " description=" + value
;
319 case AX_ATTR_DISPLAY
:
320 result
+= " display=" + value
;
322 case AX_ATTR_DROPEFFECT
:
323 result
+= " dropeffect=" + value
;
326 result
+= " help=" + value
;
328 case AX_ATTR_HTML_TAG
:
329 result
+= " html_tag=" + value
;
331 case AX_ATTR_ARIA_INVALID_VALUE
:
332 result
+= " aria_invalid_value=" + value
;
334 case AX_ATTR_LIVE_RELEVANT
:
335 result
+= " relevant=" + value
;
337 case AX_ATTR_LIVE_STATUS
:
338 result
+= " live=" + value
;
340 case AX_ATTR_CONTAINER_LIVE_RELEVANT
:
341 result
+= " container_relevant=" + value
;
343 case AX_ATTR_CONTAINER_LIVE_STATUS
:
344 result
+= " container_live=" + value
;
346 case AX_ATTR_PLACEHOLDER
:
347 result
+= "placeholder" + value
;
350 result
+= " role=" + value
;
352 case AX_ATTR_SHORTCUT
:
353 result
+= " shortcut=" + value
;
355 case AX_ATTR_TEXT_INPUT_TYPE
:
356 result
+= " text_input_type=" + value
;
359 result
+= " url=" + value
;
362 result
+= " name=" + value
;
365 result
+= " value=" + value
;
367 case AX_STRING_ATTRIBUTE_NONE
:
372 for (size_t i
= 0; i
< float_attributes
.size(); ++i
) {
373 std::string value
= DoubleToString(float_attributes
[i
].second
);
374 switch (float_attributes
[i
].first
) {
375 case AX_ATTR_DOC_LOADING_PROGRESS
:
376 result
+= " doc_progress=" + value
;
378 case AX_ATTR_VALUE_FOR_RANGE
:
379 result
+= " value_for_range=" + value
;
381 case AX_ATTR_MAX_VALUE_FOR_RANGE
:
382 result
+= " max_value=" + value
;
384 case AX_ATTR_MIN_VALUE_FOR_RANGE
:
385 result
+= " min_value=" + value
;
387 case AX_ATTR_FONT_SIZE
:
388 result
+= " font_size=" + value
;
390 case AX_FLOAT_ATTRIBUTE_NONE
:
395 for (size_t i
= 0; i
< bool_attributes
.size(); ++i
) {
396 std::string value
= bool_attributes
[i
].second
? "true" : "false";
397 switch (bool_attributes
[i
].first
) {
398 case AX_ATTR_DOC_LOADED
:
399 result
+= " doc_loaded=" + value
;
401 case AX_ATTR_BUTTON_MIXED
:
402 result
+= " mixed=" + value
;
404 case AX_ATTR_LIVE_ATOMIC
:
405 result
+= " atomic=" + value
;
407 case AX_ATTR_LIVE_BUSY
:
408 result
+= " busy=" + value
;
410 case AX_ATTR_CONTAINER_LIVE_ATOMIC
:
411 result
+= " container_atomic=" + value
;
413 case AX_ATTR_CONTAINER_LIVE_BUSY
:
414 result
+= " container_busy=" + value
;
416 case AX_ATTR_ARIA_READONLY
:
417 result
+= " aria_readonly=" + value
;
419 case AX_ATTR_CAN_SET_VALUE
:
420 result
+= " can_set_value=" + value
;
422 case AX_ATTR_UPDATE_LOCATION_ONLY
:
423 result
+= " update_location_only=" + value
;
425 case AX_ATTR_CANVAS_HAS_FALLBACK
:
426 result
+= " has_fallback=" + value
;
428 case AX_ATTR_IS_AX_TREE_HOST
:
429 result
+= " is_ax_tree_host=" + value
;
431 case AX_ATTR_GRABBED
:
432 result
+= " grabbed=" + value
;
434 case AX_BOOL_ATTRIBUTE_NONE
:
439 for (size_t i
= 0; i
< intlist_attributes
.size(); ++i
) {
440 const std::vector
<int32
>& values
= intlist_attributes
[i
].second
;
441 switch (intlist_attributes
[i
].first
) {
442 case AX_ATTR_INDIRECT_CHILD_IDS
:
443 result
+= " indirect_child_ids=" + IntVectorToString(values
);
445 case AX_ATTR_CONTROLS_IDS
:
446 result
+= " controls_ids=" + IntVectorToString(values
);
448 case AX_ATTR_DESCRIBEDBY_IDS
:
449 result
+= " describedby_ids=" + IntVectorToString(values
);
451 case AX_ATTR_FLOWTO_IDS
:
452 result
+= " flowto_ids=" + IntVectorToString(values
);
454 case AX_ATTR_LABELLEDBY_IDS
:
455 result
+= " labelledby_ids=" + IntVectorToString(values
);
457 case AX_ATTR_OWNS_IDS
:
458 result
+= " owns_ids=" + IntVectorToString(values
);
460 case AX_ATTR_LINE_BREAKS
:
461 result
+= " line_breaks=" + IntVectorToString(values
);
463 case AX_ATTR_CELL_IDS
:
464 result
+= " cell_ids=" + IntVectorToString(values
);
466 case AX_ATTR_UNIQUE_CELL_IDS
:
467 result
+= " unique_cell_ids=" + IntVectorToString(values
);
469 case AX_ATTR_CHARACTER_OFFSETS
:
470 result
+= " character_offsets=" + IntVectorToString(values
);
472 case AX_ATTR_WORD_STARTS
:
473 result
+= " word_starts=" + IntVectorToString(values
);
475 case AX_ATTR_WORD_ENDS
:
476 result
+= " word_ends=" + IntVectorToString(values
);
478 case AX_INT_LIST_ATTRIBUTE_NONE
:
483 if (!child_ids
.empty())
484 result
+= " child_ids=" + IntVectorToString(child_ids
);