Flutter Engine
The Flutter Engine
ax_node_data.cc
Go to the documentation of this file.
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 "ax_node_data.h"
6
7#include <algorithm>
8#include <cstddef>
9#include <iterator>
10#include <set>
11#include <utility>
12
13#include "ax_enum_util.h"
14#include "ax_role_properties.h"
16#include "base/logging.h"
17#include "base/no_destructor.h"
18#include "base/string_utils.h"
19
20namespace ui {
21
22namespace {
23
24bool IsFlagSet(uint32_t bitfield, uint32_t flag) {
25 return (bitfield & (1U << flag)) != 0;
26}
27
28bool IsFlagSet(uint64_t bitfield, uint32_t flag) {
29 return (bitfield & (1ULL << flag)) != 0;
30}
31
32uint32_t ModifyFlag(uint32_t bitfield, uint32_t flag, bool set) {
33 return set ? (bitfield |= (1U << flag)) : (bitfield &= ~(1U << flag));
34}
35
36uint64_t ModifyFlag(uint64_t bitfield, uint32_t flag, bool set) {
37 return set ? (bitfield |= (1ULL << flag)) : (bitfield &= ~(1ULL << flag));
38}
39
40std::string StateBitfieldToString(uint32_t state_enum) {
41 std::string str;
42 for (uint32_t i = static_cast<uint32_t>(ax::mojom::State::kNone) + 1;
43 i <= static_cast<uint32_t>(ax::mojom::State::kMaxValue); ++i) {
44 if (IsFlagSet(state_enum, i))
45 str += " " +
47 }
48 return str;
49}
50
51std::string ActionsBitfieldToString(uint64_t actions) {
52 std::string str;
53 for (uint32_t i = static_cast<uint32_t>(ax::mojom::Action::kNone) + 1;
54 i <= static_cast<uint32_t>(ax::mojom::Action::kMaxValue); ++i) {
55 if (IsFlagSet(actions, i)) {
56 str += ui::ToString(static_cast<ax::mojom::Action>(i));
57 actions = ModifyFlag(actions, i, false);
58 str += actions ? "," : "";
59 }
60 }
61 return str;
62}
63
64std::string IntVectorToString(const std::vector<int>& items) {
65 std::string str;
66 for (size_t i = 0; i < items.size(); ++i) {
67 if (i > 0)
68 str += ",";
69 str += base::NumberToString(items[i]);
70 }
71 return str;
72}
73
74// Predicate that returns true if the first value of a pair is |first|.
75template <typename FirstType, typename SecondType>
76struct FirstIs {
77 explicit FirstIs(FirstType first) : first_(first) {}
78 bool operator()(std::pair<FirstType, SecondType> const& p) {
79 return p.first == first_;
80 }
81 FirstType first_;
82};
83
84// Helper function that finds a key in a vector of pairs by matching on the
85// first value, and returns an iterator.
86template <typename FirstType, typename SecondType>
87typename std::vector<std::pair<FirstType, SecondType>>::const_iterator
88FindInVectorOfPairs(
89 FirstType first,
90 const std::vector<std::pair<FirstType, SecondType>>& vector) {
91 return std::find_if(vector.begin(), vector.end(),
92 FirstIs<FirstType, SecondType>(first));
93}
94
95} // namespace
96
97// Return true if |attr| is a node ID that would need to be mapped when
98// renumbering the ids in a combined tree.
100 switch (attr) {
113 return true;
114
115 // Note: all of the attributes are included here explicitly,
116 // rather than using "default:", so that it's a compiler error to
117 // add a new attribute without explicitly considering whether it's
118 // a node id attribute or not.
168 return false;
169 }
170
172 return false;
173}
174
175// Return true if |attr| contains a vector of node ids that would need
176// to be mapped when renumbering the ids in a combined tree.
178 switch (attr) {
186 return true;
187
188 // Note: all of the attributes are included here explicitly,
189 // rather than using "default:", so that it's a compiler error to
190 // add a new attribute without explicitly considering whether it's
191 // a node id attribute or not.
201 return false;
202 }
203
205 return false;
206}
207
209 : role(ax::mojom::Role::kUnknown), state(0U), actions(0ULL) {}
210
211AXNodeData::~AXNodeData() = default;
212
214 id = other.id;
215 role = other.role;
216 state = other.state;
217 actions = other.actions;
225 child_ids = other.child_ids;
227}
228
230 id = other.id;
231 role = other.role;
232 state = other.state;
233 actions = other.actions;
234 string_attributes.swap(other.string_attributes);
235 int_attributes.swap(other.int_attributes);
236 float_attributes.swap(other.float_attributes);
237 bool_attributes.swap(other.bool_attributes);
238 intlist_attributes.swap(other.intlist_attributes);
239 stringlist_attributes.swap(other.stringlist_attributes);
240 html_attributes.swap(other.html_attributes);
241 child_ids.swap(other.child_ids);
242 relative_bounds = other.relative_bounds;
243}
244
246 id = other.id;
247 role = other.role;
248 state = other.state;
249 actions = other.actions;
257 child_ids = other.child_ids;
259 return *this;
260}
261
263 auto iter = FindInVectorOfPairs(attribute, bool_attributes);
264 return iter != bool_attributes.end();
265}
266
268 bool result;
269 if (GetBoolAttribute(attribute, &result))
270 return result;
271 return false;
272}
273
275 bool* value) const {
276 auto iter = FindInVectorOfPairs(attribute, bool_attributes);
277 if (iter != bool_attributes.end()) {
278 *value = iter->second;
279 return true;
280 }
281
282 return false;
283}
284
286 auto iter = FindInVectorOfPairs(attribute, float_attributes);
287 return iter != float_attributes.end();
288}
289
291 float result;
292 if (GetFloatAttribute(attribute, &result))
293 return result;
294 return 0.0;
295}
296
298 float* value) const {
299 auto iter = FindInVectorOfPairs(attribute, float_attributes);
300 if (iter != float_attributes.end()) {
301 *value = iter->second;
302 return true;
303 }
304
305 return false;
306}
307
309 auto iter = FindInVectorOfPairs(attribute, int_attributes);
310 return iter != int_attributes.end();
311}
312
314 int result;
315 if (GetIntAttribute(attribute, &result))
316 return result;
317 return 0;
318}
319
321 int* value) const {
322 auto iter = FindInVectorOfPairs(attribute, int_attributes);
323 if (iter != int_attributes.end()) {
324 *value = static_cast<int>(iter->second);
325 return true;
326 }
327
328 return false;
329}
330
332 ax::mojom::StringAttribute attribute) const {
333 auto iter = FindInVectorOfPairs(attribute, string_attributes);
334 return iter != string_attributes.end();
335}
336
338 ax::mojom::StringAttribute attribute) const {
339 auto iter = FindInVectorOfPairs(attribute, string_attributes);
340 return iter != string_attributes.end() ? iter->second : base::EmptyString();
341}
342
344 std::string* value) const {
345 auto iter = FindInVectorOfPairs(attribute, string_attributes);
346 if (iter != string_attributes.end()) {
347 *value = iter->second;
348 return true;
349 }
350
351 return false;
352}
353
355 ax::mojom::StringAttribute attribute) const {
356 std::string value_utf8;
357 if (!GetStringAttribute(attribute, &value_utf8))
358 return std::u16string();
359 return base::UTF8ToUTF16(value_utf8);
360}
361
363 std::u16string* value) const {
364 std::string value_utf8;
365 if (!GetStringAttribute(attribute, &value_utf8))
366 return false;
367 *value = base::UTF8ToUTF16(value_utf8);
368 return true;
369}
370
372 ax::mojom::IntListAttribute attribute) const {
373 auto iter = FindInVectorOfPairs(attribute, intlist_attributes);
374 return iter != intlist_attributes.end();
375}
376
377const std::vector<int32_t>& AXNodeData::GetIntListAttribute(
378 ax::mojom::IntListAttribute attribute) const {
379 static const base::NoDestructor<std::vector<int32_t>> empty_vector;
380 auto iter = FindInVectorOfPairs(attribute, intlist_attributes);
381 if (iter != intlist_attributes.end())
382 return iter->second;
383 return *empty_vector;
384}
385
387 std::vector<int32_t>* value) const {
388 auto iter = FindInVectorOfPairs(attribute, intlist_attributes);
389 if (iter != intlist_attributes.end()) {
390 *value = iter->second;
391 return true;
392 }
393
394 return false;
395}
396
398 ax::mojom::StringListAttribute attribute) const {
399 auto iter = FindInVectorOfPairs(attribute, stringlist_attributes);
400 return iter != stringlist_attributes.end();
401}
402
403const std::vector<std::string>& AXNodeData::GetStringListAttribute(
404 ax::mojom::StringListAttribute attribute) const {
405 static const base::NoDestructor<std::vector<std::string>> empty_vector;
406 auto iter = FindInVectorOfPairs(attribute, stringlist_attributes);
407 if (iter != stringlist_attributes.end())
408 return iter->second;
409 return *empty_vector;
410}
411
414 std::vector<std::string>* value) const {
415 auto iter = FindInVectorOfPairs(attribute, stringlist_attributes);
416 if (iter != stringlist_attributes.end()) {
417 *value = iter->second;
418 return true;
419 }
420
421 return false;
422}
423
424bool AXNodeData::GetHtmlAttribute(const char* html_attr,
425 std::string* value) const {
426 for (const std::pair<std::string, std::string>& html_attribute :
428 const std::string& attr = html_attribute.first;
429 if (base::LowerCaseEqualsASCII(attr, html_attr)) {
430 *value = html_attribute.second;
431 return true;
432 }
433 }
434
435 return false;
436}
437
438bool AXNodeData::GetHtmlAttribute(const char* html_attr,
439 std::u16string* value) const {
440 std::string value_utf8;
441 if (!GetHtmlAttribute(html_attr, &value_utf8))
442 return false;
443 *value = base::UTF8ToUTF16(value_utf8);
444 return true;
445}
446
448 const std::string& value) {
450 if (HasStringAttribute(attribute))
451 RemoveStringAttribute(attribute);
452 string_attributes.push_back(std::make_pair(attribute, value));
453}
454
457 if (HasIntAttribute(attribute))
458 RemoveIntAttribute(attribute);
459 int_attributes.push_back(std::make_pair(attribute, value));
460}
461
463 float value) {
465 if (HasFloatAttribute(attribute))
466 RemoveFloatAttribute(attribute);
467 float_attributes.push_back(std::make_pair(attribute, value));
468}
469
471 bool value) {
473 if (HasBoolAttribute(attribute))
474 RemoveBoolAttribute(attribute);
475 bool_attributes.push_back(std::make_pair(attribute, value));
476}
477
479 const std::vector<int32_t>& value) {
481 if (HasIntListAttribute(attribute))
482 RemoveIntListAttribute(attribute);
483 intlist_attributes.push_back(std::make_pair(attribute, value));
484}
485
488 const std::vector<std::string>& value) {
490 if (HasStringListAttribute(attribute))
491 RemoveStringListAttribute(attribute);
492 stringlist_attributes.push_back(std::make_pair(attribute, value));
493}
494
497 base::EraseIf(string_attributes, [attribute](const auto& string_attribute) {
498 return string_attribute.first == attribute;
499 });
500}
501
504 base::EraseIf(int_attributes, [attribute](const auto& int_attribute) {
505 return int_attribute.first == attribute;
506 });
507}
508
511 base::EraseIf(float_attributes, [attribute](const auto& float_attribute) {
512 return float_attribute.first == attribute;
513 });
514}
515
518 base::EraseIf(bool_attributes, [attribute](const auto& bool_attribute) {
519 return bool_attribute.first == attribute;
520 });
521}
522
525 base::EraseIf(intlist_attributes, [attribute](const auto& intlist_attribute) {
526 return intlist_attribute.first == attribute;
527 });
528}
529
534 [attribute](const auto& stringlist_attribute) {
535 return stringlist_attribute.first == attribute;
536 });
537}
538
540 AXNodeTextStyles style_attributes;
541
543 &style_attributes.background_color);
546 &style_attributes.invalid_state);
548 &style_attributes.overline_style);
550 &style_attributes.text_direction);
552 &style_attributes.text_position);
554 &style_attributes.strikethrough_style);
556 &style_attributes.text_style);
558 &style_attributes.underline_style);
560 &style_attributes.font_size);
562 &style_attributes.font_weight);
564 &style_attributes.font_family);
565
566 return style_attributes;
567}
568
569void AXNodeData::SetName(const std::string& name) {
571 BASE_LOG()
572 << "A valid role is required before setting the name attribute, "
573 "because "
574 "the role is used for setting the required NameFrom attribute.";
576 }
577
578 auto iter = std::find_if(string_attributes.begin(), string_attributes.end(),
579 [](const auto& string_attribute) {
580 return string_attribute.first ==
581 ax::mojom::StringAttribute::kName;
582 });
583
584 if (iter == string_attributes.end()) {
585 string_attributes.push_back(
586 std::make_pair(ax::mojom::StringAttribute::kName, name));
587 } else {
588 iter->second = name;
589 }
590
592 return;
593 // Since this method is mostly used by tests which don't always set the
594 // "NameFrom" attribute, we need to set it here to the most likely value if
595 // not set, otherwise code that tries to calculate the node's inner text, its
596 // hypertext, or even its value, might not know whether to include the name in
597 // the result or not.
598 //
599 // For example, if there is a text field, but it is empty, i.e. it has no
600 // value, its value could be its name if "NameFrom" is set to "kPlaceholder"
601 // or to "kContents" but not if it's set to "kAttribute". Similarly, if there
602 // is a button without any unignored children, it's name can only be
603 // equivalent to its inner text if "NameFrom" is set to "kContents" or to
604 // "kValue", but not if it is set to "kAttribute".
605 if (IsText(role)) {
607 } else {
609 }
610}
611
612void AXNodeData::SetName(const std::u16string& name) {
614}
615
618}
619
620void AXNodeData::SetDescription(const std::string& description) {
622}
623
624void AXNodeData::SetDescription(const std::u16string& description) {
625 SetDescription(base::UTF16ToUTF8(description));
626}
627
628void AXNodeData::SetValue(const std::string& value) {
630}
631
632void AXNodeData::SetValue(const std::u16string& value) {
634}
635
636void AXNodeData::SetTooltip(const std::string& value) {
638}
639
640void AXNodeData::SetTooltip(const std::u16string& value) {
642}
643
645 return IsFlagSet(state, static_cast<uint32_t>(state_enum));
646}
647
649 return IsFlagSet(actions, static_cast<uint32_t>(action));
650}
651
654 return IsFlagSet(static_cast<uint32_t>(style),
655 static_cast<uint32_t>(text_style_enum));
656}
657
660 return IsFlagSet(static_cast<uint32_t>(dropeffect),
661 static_cast<uint32_t>(dropeffect_enum));
662}
663
665 BASE_DCHECK(static_cast<int>(state_enum) >
666 static_cast<int>(ax::mojom::State::kNone));
667 BASE_DCHECK(static_cast<int>(state_enum) <=
668 static_cast<int>(ax::mojom::State::kMaxValue));
669 state = ModifyFlag(state, static_cast<uint32_t>(state_enum), true);
670}
671
673 BASE_DCHECK(static_cast<int>(state_enum) >
674 static_cast<int>(ax::mojom::State::kNone));
675 BASE_DCHECK(static_cast<int>(state_enum) <=
676 static_cast<int>(ax::mojom::State::kMaxValue));
677 state = ModifyFlag(state, static_cast<uint32_t>(state_enum), false);
678}
679
681 switch (action_enum) {
684 break;
685
686 // Note: all of the attributes are included here explicitly, rather than
687 // using "default:", so that it's a compiler error to add a new action
688 // without explicitly considering whether there are mutually exclusive
689 // actions that can be performed on a UI control at the same time.
692 ax::mojom::Action excluded_action =
695 BASE_DCHECK(!HasAction(excluded_action));
696 break;
697 }
698
730 break;
731 }
732
733 actions = ModifyFlag(actions, static_cast<uint32_t>(action_enum), true);
734}
735
737 BASE_DCHECK(static_cast<int>(text_style_enum) >=
738 static_cast<int>(ax::mojom::TextStyle::kMinValue));
739 BASE_DCHECK(static_cast<int>(text_style_enum) <=
740 static_cast<int>(ax::mojom::TextStyle::kMaxValue));
742 style = ModifyFlag(static_cast<uint32_t>(style),
743 static_cast<uint32_t>(text_style_enum), true);
746}
747
749 BASE_DCHECK(static_cast<int>(dropeffect_enum) >=
750 static_cast<int>(ax::mojom::Dropeffect::kMinValue));
751 BASE_DCHECK(static_cast<int>(dropeffect_enum) <=
752 static_cast<int>(ax::mojom::Dropeffect::kMaxValue));
754 dropeffect = ModifyFlag(static_cast<uint32_t>(dropeffect),
755 static_cast<uint32_t>(dropeffect_enum), true);
758}
759
761 return static_cast<ax::mojom::CheckedState>(
763}
764
766 if (HasCheckedState())
768 if (checked_state != ax::mojom::CheckedState::kNone) {
770 static_cast<int32_t>(checked_state));
771 }
772}
773
776}
777
779 return static_cast<ax::mojom::DefaultActionVerb>(
781}
782
784 ax::mojom::DefaultActionVerb default_action_verb) {
787 if (default_action_verb != ax::mojom::DefaultActionVerb::kNone) {
789 static_cast<int32_t>(default_action_verb));
790 }
791}
792
794 return static_cast<ax::mojom::HasPopup>(
796}
797
801 if (has_popup != ax::mojom::HasPopup::kFalse) {
803 static_cast<int32_t>(has_popup));
804 }
805}
806
808 return static_cast<ax::mojom::InvalidState>(
810}
811
815 if (invalid_state != ax::mojom::InvalidState::kNone) {
817 static_cast<int32_t>(invalid_state));
818 }
819}
820
822 return static_cast<ax::mojom::NameFrom>(
824}
825
829 if (name_from != ax::mojom::NameFrom::kNone) {
831 static_cast<int32_t>(name_from));
832 }
833}
834
836 return static_cast<ax::mojom::DescriptionFrom>(
838}
839
841 ax::mojom::DescriptionFrom description_from) {
844 if (description_from != ax::mojom::DescriptionFrom::kNone) {
846 static_cast<int32_t>(description_from));
847 }
848}
849
851 return static_cast<ax::mojom::TextPosition>(
853}
854
858 if (text_position != ax::mojom::TextPosition::kNone) {
860 static_cast<int32_t>(text_position));
861 }
862}
863
865 return static_cast<ax::mojom::ImageAnnotationStatus>(
867}
868
875 static_cast<int32_t>(status));
876 }
877}
878
880 return static_cast<ax::mojom::Restriction>(
882}
883
887 if (restriction != ax::mojom::Restriction::kNone) {
889 static_cast<int32_t>(restriction));
890 }
891}
892
894 return static_cast<ax::mojom::ListStyle>(
896}
897
901 if (list_style != ax::mojom::ListStyle::kNone) {
903 static_cast<int32_t>(list_style));
904 }
905}
906
908 return static_cast<ax::mojom::TextAlign>(
910}
911
916 static_cast<int32_t>(text_align));
917}
918
920 return static_cast<ax::mojom::WritingDirection>(
922}
923
927 if (text_direction != ax::mojom::WritingDirection::kNone) {
929 static_cast<int32_t>(text_direction));
930 }
931}
932
935}
936
938 // Currently there is no internal representation for |aria-pressed|, and
939 // we map |aria-pressed="true"| to ax::mojom::CheckedState::kTrue for a native
940 // button or role="button".
941 // https://www.w3.org/TR/wai-aria-1.1/#aria-pressed
943 return true;
944 return false;
945}
946
948 // If it has a custom default action verb except for
949 // ax::mojom::DefaultActionVerb::kClickAncestor, it's definitely clickable.
950 // ax::mojom::DefaultActionVerb::kClickAncestor is used when an element with a
951 // click listener is present in its ancestry chain.
954 return true;
955
956 return ui::IsClickable(role);
957}
958
960 // It's selectable if it has the attribute, whether it's true or false.
963}
964
968}
969
972}
973
975 return IsIgnored() || IsInvisible();
976}
977
979 // A control is "invocable" if it initiates an action when activated but
980 // does not maintain any state. A control that maintains state when activated
981 // would be considered a toggle or expand-collapse element - these elements
982 // are "clickable" but not "invocable". Similarly, if the action only involves
983 // activating the control, such as when clicking a text field, the control is
984 // not considered "invocable".
985 return IsClickable() && !IsActivatable() && !SupportsExpandCollapse() &&
987}
988
990 // According to the WAI-ARIA spec, a menu button is a native button or an ARIA
991 // role="button" that opens a menu. Although ARIA does not include a role
992 // specifically for menu buttons, screen readers identify buttons that have
993 // aria-haspopup="true" or aria-haspopup="menu" as menu buttons, and Blink
994 // maps both to HasPopup::kMenu.
995 // https://www.w3.org/TR/wai-aria-practices/#menubutton
996 // https://www.w3.org/TR/wai-aria-1.1/#aria-haspopup
998 return true;
999
1000 return false;
1001}
1002
1004 return IsPlainTextField() || IsRichTextField();
1005}
1006
1009}
1010
1012 // We need to check both the role and editable state, because some ARIA text
1013 // fields may in fact not be editable, whilst some editable fields might not
1014 // have the role.
1020}
1021
1025}
1026
1028 switch (GetRestriction()) {
1031 return true;
1035 return false;
1036 }
1037
1038 // By default, when readonly is not supported, we assume the node is never
1039 // editable - then always readonly.
1042 }
1043 }
1044}
1045
1048 // According to the ARIA spec, role="separator" acts as a splitter only
1049 // when focusable, and supports a range only in that case.
1051 }
1053}
1054
1059 return true;
1060
1062}
1063
1064std::string AXNodeData::ToString() const {
1065 std::string result;
1066
1067 result += "id=" + base::NumberToString(id);
1068 result += " ";
1070
1071 result += StateBitfieldToString(state);
1072
1073 result += " " + relative_bounds.ToString();
1074
1075 for (const std::pair<ax::mojom::IntAttribute, int32_t>& int_attribute :
1077 std::string value = base::NumberToString(int_attribute.second);
1078 switch (int_attribute.first) {
1080 result += std::string(" action=") +
1082 int_attribute.second));
1083 break;
1085 result += " scroll_x=" + value;
1086 break;
1088 result += " scroll_x_min=" + value;
1089 break;
1091 result += " scroll_x_max=" + value;
1092 break;
1094 result += " scroll_y=" + value;
1095 break;
1097 result += " scroll_y_min=" + value;
1098 break;
1100 result += " scroll_y_max=" + value;
1101 break;
1103 result += " level=" + value;
1104 break;
1106 result += " sel_start=" + value;
1107 break;
1109 result += " sel_end=" + value;
1110 break;
1112 result += " aria_column_count=" + value;
1113 break;
1115 result += " aria_cell_column_index=" + value;
1116 break;
1118 result += " aria_cell_column_span=" + value;
1119 break;
1121 result += " aria_row_count=" + value;
1122 break;
1124 result += " aria_cell_row_index=" + value;
1125 break;
1127 result += " aria_cell_row_span=" + value;
1128 break;
1130 result += " rows=" + value;
1131 break;
1133 result += " cols=" + value;
1134 break;
1136 result += " col=" + value;
1137 break;
1139 result += " row=" + value;
1140 break;
1142 result += " colspan=" + value;
1143 break;
1145 result += " rowspan=" + value;
1146 break;
1148 result += " column_header_id=" + value;
1149 break;
1151 result += " column_index=" + value;
1152 break;
1154 result += " header_id=" + value;
1155 break;
1157 result += " row_header_id=" + value;
1158 break;
1160 result += " row_index=" + value;
1161 break;
1163 switch (static_cast<ax::mojom::SortDirection>(int_attribute.second)) {
1165 result += " sort_direction=none";
1166 break;
1168 result += " sort_direction=ascending";
1169 break;
1171 result += " sort_direction=descending";
1172 break;
1174 result += " sort_direction=other";
1175 break;
1176 default:
1177 break;
1178 }
1179 break;
1181 result += " name_from=";
1183 static_cast<ax::mojom::NameFrom>(int_attribute.second));
1184 break;
1186 result += " description_from=";
1188 static_cast<ax::mojom::DescriptionFrom>(int_attribute.second));
1189 break;
1191 result += " activedescendant=" + value;
1192 break;
1194 result += " errormessage=" + value;
1195 break;
1197 result += " in_page_link_target_id=" + value;
1198 break;
1200 result += " member_of_id=" + value;
1201 break;
1203 result += " next_on_line_id=" + value;
1204 break;
1206 result += " popup_for_id=" + value;
1207 break;
1209 result += " previous_on_line_id=" + value;
1210 break;
1212 result += base::StringPrintf(" color_value=&%X", int_attribute.second);
1213 break;
1215 switch (
1216 static_cast<ax::mojom::AriaCurrentState>(int_attribute.second)) {
1218 result += " aria_current_state=false";
1219 break;
1221 result += " aria_current_state=true";
1222 break;
1224 result += " aria_current_state=page";
1225 break;
1227 result += " aria_current_state=step";
1228 break;
1230 result += " aria_current_state=location";
1231 break;
1233 result += " aria_current_state=date";
1234 break;
1236 result += " aria_current_state=time";
1237 break;
1238 default:
1239 break;
1240 }
1241 break;
1243 result +=
1244 base::StringPrintf(" background_color=&%X", int_attribute.second);
1245 break;
1247 result += base::StringPrintf(" color=&%X", int_attribute.second);
1248 break;
1250 switch (static_cast<ax::mojom::ListStyle>(int_attribute.second)) {
1252 result += " list_style=circle";
1253 break;
1255 result += " list_style=disc";
1256 break;
1258 result += " list_style=image";
1259 break;
1261 result += " list_style=numeric";
1262 break;
1264 result += " list_style=other";
1265 break;
1267 result += " list_style=square";
1268 break;
1269 default:
1270 break;
1271 }
1272 break;
1274 result += " text_align=";
1276 static_cast<ax::mojom::TextAlign>(int_attribute.second));
1277 break;
1279 switch (
1280 static_cast<ax::mojom::WritingDirection>(int_attribute.second)) {
1282 result += " text_direction=ltr";
1283 break;
1285 result += " text_direction=rtl";
1286 break;
1288 result += " text_direction=ttb";
1289 break;
1291 result += " text_direction=btt";
1292 break;
1293 default:
1294 break;
1295 }
1296 break;
1298 switch (static_cast<ax::mojom::TextPosition>(int_attribute.second)) {
1300 result += " text_position=none";
1301 break;
1303 result += " text_position=subscript";
1304 break;
1306 result += " text_position=superscript";
1307 break;
1308 default:
1309 break;
1310 }
1311 break;
1313 std::string text_style_value;
1315 text_style_value += "bold,";
1317 text_style_value += "italic,";
1319 text_style_value += "underline,";
1321 text_style_value += "line-through,";
1323 text_style_value += "overline,";
1324 result += text_style_value.substr(0, text_style_value.size() - 1);
1325 break;
1326 }
1328 result += std::string(" text_overline_style=") +
1330 int_attribute.second));
1331 break;
1333 result += std::string(" text_strikethrough_style=") +
1335 int_attribute.second));
1336 break;
1338 result += std::string(" text_underline_style=") +
1340 int_attribute.second));
1341 break;
1343 result += " setsize=" + value;
1344 break;
1346 result += " posinset=" + value;
1347 break;
1349 switch (static_cast<ax::mojom::HasPopup>(int_attribute.second)) {
1351 result += " haspopup=true";
1352 break;
1354 result += " haspopup=menu";
1355 break;
1357 result += " haspopup=listbox";
1358 break;
1360 result += " haspopup=tree";
1361 break;
1363 result += " haspopup=grid";
1364 break;
1366 result += " haspopup=dialog";
1367 break;
1369 default:
1370 break;
1371 }
1372 break;
1374 switch (static_cast<ax::mojom::InvalidState>(int_attribute.second)) {
1376 result += " invalid_state=false";
1377 break;
1379 result += " invalid_state=true";
1380 break;
1382 result += " invalid_state=other";
1383 break;
1384 default:
1385 break;
1386 }
1387 break;
1389 switch (static_cast<ax::mojom::CheckedState>(int_attribute.second)) {
1391 result += " checked_state=false";
1392 break;
1394 result += " checked_state=true";
1395 break;
1397 result += " checked_state=mixed";
1398 break;
1399 default:
1400 break;
1401 }
1402 break;
1404 switch (static_cast<ax::mojom::Restriction>(int_attribute.second)) {
1406 result += " restriction=readonly";
1407 break;
1409 result += " restriction=disabled";
1410 break;
1411 default:
1412 break;
1413 }
1414 break;
1416 result += " next_focus_id=" + value;
1417 break;
1419 result += " previous_focus_id=" + value;
1420 break;
1422 result += std::string(" image_annotation_status=") +
1424 int_attribute.second));
1425 break;
1427 result += " dropeffect=" + value;
1428 break;
1430 result += " dom_node_id=" + value;
1431 break;
1433 break;
1434 }
1435 }
1436
1437 for (const std::pair<ax::mojom::StringAttribute, std::string>&
1438 string_attribute : string_attributes) {
1439 std::string value = string_attribute.second;
1440 switch (string_attribute.first) {
1442 result += " access_key=" + value;
1443 break;
1445 result += " aria_invalid_value=" + value;
1446 break;
1448 result += " autocomplete=" + value;
1449 break;
1451 result += " child_tree_id=" + value.substr(0, 8);
1452 break;
1454 result += " class_name=" + value;
1455 break;
1457 result += " description=" + value;
1458 break;
1460 result += " display=" + value;
1461 break;
1463 result += " font-family=" + value;
1464 break;
1466 result += " html_tag=" + value;
1467 break;
1469 result += " image_annotation=" + value;
1470 break;
1472 result += " image_data_url=(" +
1473 base::NumberToString(static_cast<int>(value.size())) +
1474 " bytes)";
1475 break;
1477 result += " inner_html=" + value;
1478 break;
1480 result += " input_type=" + value;
1481 break;
1483 result += " key_shortcuts=" + value;
1484 break;
1486 result += " language=" + value;
1487 break;
1489 result += " relevant=" + value;
1490 break;
1492 result += " live=" + value;
1493 break;
1495 result += " container_relevant=" + value;
1496 break;
1498 result += " container_live=" + value;
1499 break;
1501 result += " placeholder=" + value;
1502 break;
1504 result += " role=" + value;
1505 break;
1507 result += " role_description=" + value;
1508 break;
1510 result += " tooltip=" + value;
1511 break;
1513 result += " url=" + value;
1514 break;
1516 result += " name=" + value;
1517 break;
1519 result += " value=" + value;
1520 break;
1522 break;
1523 }
1524 }
1525
1526 for (const std::pair<ax::mojom::FloatAttribute, float>& float_attribute :
1528 std::string value = base::NumberToString(float_attribute.second);
1529 switch (float_attribute.first) {
1531 result += " value_for_range=" + value;
1532 break;
1534 result += " max_value=" + value;
1535 break;
1537 result += " min_value=" + value;
1538 break;
1540 result += " step_value=" + value;
1541 break;
1543 result += " font_size=" + value;
1544 break;
1546 result += " font_weight=" + value;
1547 break;
1549 result += " text_indent=" + value;
1550 break;
1552 break;
1553 }
1554 }
1555
1556 for (const std::pair<ax::mojom::BoolAttribute, bool>& bool_attribute :
1558 std::string value = bool_attribute.second ? "true" : "false";
1559 switch (bool_attribute.first) {
1561 result += " editable_root=" + value;
1562 break;
1564 result += " atomic=" + value;
1565 break;
1567 result += " busy=" + value;
1568 break;
1570 result += " container_atomic=" + value;
1571 break;
1573 result += " container_busy=" + value;
1574 break;
1576 result += " update_location_only=" + value;
1577 break;
1579 result += " has_fallback=" + value;
1580 break;
1582 result += " modal=" + value;
1583 break;
1585 result += " scrollable=" + value;
1586 break;
1588 result += " clickable=" + value;
1589 break;
1591 result += " clips_children=" + value;
1592 break;
1594 result += " not_user_selectable=" + value;
1595 break;
1597 result += " selected=" + value;
1598 break;
1600 result += " selected_from_focus=" + value;
1601 break;
1603 result += " supports_text_location=" + value;
1604 break;
1606 result += " grabbed=" + value;
1607 break;
1609 result += " is_line_breaking_object=" + value;
1610 break;
1612 result += " is_page_breaking_object=" + value;
1613 break;
1615 result += " has_aria_attribute=" + value;
1616 break;
1618 break;
1619 }
1620 }
1621
1622 for (const std::pair<ax::mojom::IntListAttribute, std::vector<int32_t>>&
1623 intlist_attribute : intlist_attributes) {
1624 const std::vector<int32_t>& values = intlist_attribute.second;
1625 switch (intlist_attribute.first) {
1627 result += " indirect_child_ids=" + IntVectorToString(values);
1628 break;
1630 result += " controls_ids=" + IntVectorToString(values);
1631 break;
1633 result += " describedby_ids=" + IntVectorToString(values);
1634 break;
1636 result += " details_ids=" + IntVectorToString(values);
1637 break;
1639 result += " flowto_ids=" + IntVectorToString(values);
1640 break;
1642 result += " labelledby_ids=" + IntVectorToString(values);
1643 break;
1645 result += " radio_group_ids=" + IntVectorToString(values);
1646 break;
1648 std::string types_str;
1649 for (size_t i = 0; i < values.size(); ++i) {
1650 int32_t type = values[i];
1651 if (type == static_cast<int32_t>(ax::mojom::MarkerType::kNone))
1652 continue;
1653
1654 if (i > 0)
1655 types_str += ',';
1656
1657 if (type & static_cast<int32_t>(ax::mojom::MarkerType::kSpelling))
1658 types_str += "spelling&";
1659 if (type & static_cast<int32_t>(ax::mojom::MarkerType::kGrammar))
1660 types_str += "grammar&";
1661 if (type & static_cast<int32_t>(ax::mojom::MarkerType::kTextMatch))
1662 types_str += "text_match&";
1663 if (type &
1664 static_cast<int32_t>(ax::mojom::MarkerType::kActiveSuggestion))
1665 types_str += "active_suggestion&";
1666 if (type & static_cast<int32_t>(ax::mojom::MarkerType::kSuggestion))
1667 types_str += "suggestion&";
1668
1669 if (!types_str.empty())
1670 types_str = types_str.substr(0, types_str.size() - 1);
1671 }
1672
1673 if (!types_str.empty())
1674 result += " marker_types=" + types_str;
1675 break;
1676 }
1678 result += " marker_starts=" + IntVectorToString(values);
1679 break;
1681 result += " marker_ends=" + IntVectorToString(values);
1682 break;
1684 result += " character_offsets=" + IntVectorToString(values);
1685 break;
1687 result += " cached_line_start_offsets=" + IntVectorToString(values);
1688 break;
1690 result += " word_starts=" + IntVectorToString(values);
1691 break;
1693 result += " word_ends=" + IntVectorToString(values);
1694 break;
1696 result += " custom_action_ids=" + IntVectorToString(values);
1697 break;
1699 break;
1700 }
1701 }
1702
1703 for (const std::pair<ax::mojom::StringListAttribute,
1704 std::vector<std::string>>& stringlist_attribute :
1706 const std::vector<std::string>& values = stringlist_attribute.second;
1707 switch (stringlist_attribute.first) {
1709 result +=
1710 " custom_action_descriptions: " + base::JoinString(values, ",");
1711 break;
1713 break;
1714 }
1715 }
1716
1717 if (actions)
1718 result += " actions=" + ActionsBitfieldToString(actions);
1719
1720 if (!child_ids.empty())
1721 result += " child_ids=" + IntVectorToString(child_ids);
1722
1723 return result;
1724}
1725
1728 return "";
1729
1730 std::string str;
1731 for (int dropeffect_idx = static_cast<int>(ax::mojom::Dropeffect::kMinValue);
1732 dropeffect_idx <= static_cast<int>(ax::mojom::Dropeffect::kMaxValue);
1733 ++dropeffect_idx) {
1734 ax::mojom::Dropeffect dropeffect_enum =
1735 static_cast<ax::mojom::Dropeffect>(dropeffect_idx);
1736 if (HasDropeffect(dropeffect_enum))
1737 str += " " + std::string(ui::ToString(dropeffect_enum));
1738 }
1739
1740 // Removing leading space in final string.
1741 return str.substr(1);
1742}
1743
1744} // namespace ui
GLenum type
FlutterSemanticsFlag flag
AtkStateType state
uint8_t value
GAsyncResult * result
StringListAttribute
Definition: ax_enums.h:850
StringAttribute
Definition: ax_enums.h:521
AriaCurrentState
Definition: ax_enums.h:1006
FloatAttribute
Definition: ax_enums.h:699
@ kSetSequentialFocusNavigationStartingPoint
ImageAnnotationStatus
Definition: ax_enums.h:1170
WritingDirection
Definition: ax_enums.h:964
IntListAttribute
Definition: ax_enums.h:799
DefaultActionVerb
Definition: ax_enums.h:489
TextDecorationStyle
Definition: ax_enums.h:995
std::string StringPrintf(const std::string &format, Args... args)
Definition: string_utils.h:18
std::string ToUpperASCII(std::string str)
std::string UTF16ToUTF8(std::u16string src)
Definition: string_utils.cc:71
const std::string & EmptyString()
std::u16string UTF8ToUTF16(std::string src)
Definition: string_utils.cc:67
size_t EraseIf(std::vector< T, Allocator > &container, Predicate pred)
std::string JoinString(std::vector< std::string > tokens, std::string delimiter)
bool LowerCaseEqualsASCII(std::string a, std::string b)
std::string NumberToString(int32_t number)
Definition: string_utils.cc:91
DEF_SWITCHES_START aot vmservice shared library name
Definition: switches.h:32
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir Path to the cache directory This is different from the persistent_cache_path in embedder which is used for Skia shader cache icu native lib Path to the library file that exports the ICU data vm service The hostname IP address on which the Dart VM Service should be served If not set
Definition: switches.h:76
bool IsNodeIdIntAttribute(ax::mojom::IntAttribute attr)
Definition: ax_node_data.cc:99
bool IsRangeValueSupported(const ax::mojom::Role role)
bool IsReadOnlySupported(const ax::mojom::Role role)
const char * ToString(ax::mojom::Event event)
Definition: ax_enum_util.cc:9
bool SupportsExpandCollapse(const ax::mojom::Role role)
bool IsNodeIdIntListAttribute(ax::mojom::IntListAttribute attr)
bool SupportsToggle(const ax::mojom::Role role)
bool ShouldHaveReadonlyStateByDefault(const ax::mojom::Role role)
bool IsClickable(const ax::mojom::Role role)
bool IsButton(const ax::mojom::Role role)
bool IsText(ax::mojom::Role role)
AXRelativeBounds relative_bounds
Definition: ax_node_data.h:293
bool IsInvisible() const
bool IsPlainTextField() const
void AddFloatAttribute(ax::mojom::FloatAttribute attribute, float value)
bool IsSelectable() const
void SetInvalidState(ax::mojom::InvalidState invalid_state)
ax::mojom::Restriction GetRestriction() const
ax::mojom::ImageAnnotationStatus GetImageAnnotationStatus() const
std::vector< std::pair< ax::mojom::FloatAttribute, float > > float_attributes
Definition: ax_node_data.h:283
const std::vector< std::string > & GetStringListAttribute(ax::mojom::StringListAttribute attribute) const
bool HasState(ax::mojom::State state) const
bool HasIntAttribute(ax::mojom::IntAttribute attribute) const
void SetRestriction(ax::mojom::Restriction restriction)
bool HasStringListAttribute(ax::mojom::StringListAttribute attribute) const
void SetDescriptionFrom(ax::mojom::DescriptionFrom description_from)
ax::mojom::HasPopup GetHasPopup() const
void AddIntListAttribute(ax::mojom::IntListAttribute attribute, const std::vector< int32_t > &value)
ax::mojom::TextAlign GetTextAlign() const
bool IsClickable() const
void AddState(ax::mojom::State state)
void RemoveBoolAttribute(ax::mojom::BoolAttribute attribute)
void SetDefaultActionVerb(ax::mojom::DefaultActionVerb default_action_verb)
bool IsReadOnlyOrDisabled() const
void RemoveFloatAttribute(ax::mojom::FloatAttribute attribute)
void RemoveIntAttribute(ax::mojom::IntAttribute attribute)
void AddIntAttribute(ax::mojom::IntAttribute attribute, int32_t value)
void SetTextAlign(ax::mojom::TextAlign text_align)
uint32_t state
Definition: ax_node_data.h:278
AXNodeData & operator=(AXNodeData other)
virtual ~AXNodeData()
std::vector< int32_t > child_ids
Definition: ax_node_data.h:291
bool HasCheckedState() const
bool HasIntListAttribute(ax::mojom::IntListAttribute attribute) const
bool IsActivatable() const
bool HasDropeffect(ax::mojom::Dropeffect dropeffect) const
bool GetHtmlAttribute(const char *attribute, std::u16string *value) const
uint64_t actions
Definition: ax_node_data.h:279
void SetValue(const std::string &value)
bool HasFloatAttribute(ax::mojom::FloatAttribute attribute) const
void SetHasPopup(ax::mojom::HasPopup has_popup)
ax::mojom::DefaultActionVerb GetDefaultActionVerb() const
bool HasAction(ax::mojom::Action action) const
void SetTextDirection(ax::mojom::WritingDirection text_direction)
void RemoveIntListAttribute(ax::mojom::IntListAttribute attribute)
bool HasStringAttribute(ax::mojom::StringAttribute attribute) const
std::vector< std::pair< ax::mojom::IntAttribute, int32_t > > int_attributes
Definition: ax_node_data.h:282
void AddStringListAttribute(ax::mojom::StringListAttribute attribute, const std::vector< std::string > &value)
void SetName(const std::string &name)
bool IsTextField() const
void AddDropeffect(ax::mojom::Dropeffect dropeffect)
std::string DropeffectBitfieldToString() const
void SetDescription(const std::string &description)
bool IsInvocable() const
ax::mojom::NameFrom GetNameFrom() const
ax::mojom::CheckedState GetCheckedState() const
bool IsRichTextField() const
std::vector< std::pair< ax::mojom::IntListAttribute, std::vector< int32_t > > > intlist_attributes
Definition: ax_node_data.h:286
virtual std::string ToString() const
bool IsIgnored() const
AXNodeTextStyles GetTextStyles() const
bool IsButtonPressed() const
std::vector< std::pair< ax::mojom::StringAttribute, std::string > > string_attributes
Definition: ax_node_data.h:281
void SetImageAnnotationStatus(ax::mojom::ImageAnnotationStatus status)
void RemoveState(ax::mojom::State state)
bool IsPasswordField() const
std::vector< std::pair< std::string, std::string > > html_attributes
Definition: ax_node_data.h:290
void AddStringAttribute(ax::mojom::StringAttribute attribute, const std::string &value)
void SetTooltip(const std::string &value)
ax::mojom::InvalidState GetInvalidState() const
ax::mojom::WritingDirection GetTextDirection() const
void SetNameExplicitlyEmpty()
bool HasTextStyle(ax::mojom::TextStyle text_style) const
bool IsRangeValueSupported() const
ax::mojom::ListStyle GetListStyle() const
bool GetBoolAttribute(ax::mojom::BoolAttribute attribute) const
void AddTextStyle(ax::mojom::TextStyle text_style)
void AddBoolAttribute(ax::mojom::BoolAttribute attribute, bool value)
std::vector< std::pair< ax::mojom::StringListAttribute, std::vector< std::string > > > stringlist_attributes
Definition: ax_node_data.h:289
ax::mojom::Role role
Definition: ax_node_data.h:277
ax::mojom::DescriptionFrom GetDescriptionFrom() const
const std::vector< int32_t > & GetIntListAttribute(ax::mojom::IntListAttribute attribute) const
float GetFloatAttribute(ax::mojom::FloatAttribute attribute) const
void SetTextPosition(ax::mojom::TextPosition text_position)
int GetIntAttribute(ax::mojom::IntAttribute attribute) const
bool IsInvisibleOrIgnored() const
bool HasBoolAttribute(ax::mojom::BoolAttribute attribute) const
const std::string & GetStringAttribute(ax::mojom::StringAttribute attribute) const
ax::mojom::TextPosition GetTextPosition() const
void RemoveStringAttribute(ax::mojom::StringAttribute attribute)
std::vector< std::pair< ax::mojom::BoolAttribute, bool > > bool_attributes
Definition: ax_node_data.h:284
void RemoveStringListAttribute(ax::mojom::StringListAttribute attribute)
bool SupportsExpandCollapse() const
void SetListStyle(ax::mojom::ListStyle list_style)
bool GetString16Attribute(ax::mojom::StringAttribute attribute, std::u16string *value) const
void SetCheckedState(ax::mojom::CheckedState checked_state)
void SetNameFrom(ax::mojom::NameFrom name_from)
bool IsMenuButton() const
void AddAction(ax::mojom::Action action)
std::string ToString() const
#define BASE_DCHECK(condition)
Definition: logging.h:63
#define BASE_UNREACHABLE()
Definition: logging.h:69
#define BASE_LOG()
Definition: logging.h:54