13#include <unordered_map>
33bool FindDescendantRoleWithMaxDepth(AXPlatformNodeBase* node,
36 int max_children_to_check) {
37 if (node->GetData().role == descendant_role)
42 int num_children_to_check =
43 std::min(node->GetChildCount(), max_children_to_check);
44 for (
int index = 0; index < num_children_to_check; index++) {
45 auto* child =
static_cast<AXPlatformNodeBase*
>(
48 FindDescendantRoleWithMaxDepth(child, descendant_role, max_depth - 1,
49 max_children_to_check)) {
62using UniqueIdMap = std::unordered_map<int32_t, AXPlatformNode*>;
124 return std::string();
130 return std::u16string();
140 if (child_count == 0) {
153 if (index >= 0 && index < child_count)
158 for (
int i = 0;
i < child_count;
i++) {
168 <<
"Unable to find the child in the list of its parent's children.";
174 std::stack<gfx::NativeViewAccessible> ancestors;
176 while (current_node) {
177 ancestors.push(current_node);
206 return std::optional<int>(0);
213 std::stack<gfx::NativeViewAccessible> our_ancestors =
GetAncestors();
214 std::stack<gfx::NativeViewAccessible> other_ancestors = other.
GetAncestors();
219 while (!our_ancestors.empty() && !other_ancestors.empty() &&
220 our_ancestors.top() == other_ancestors.top()) {
221 common_ancestor = our_ancestors.top();
223 other_ancestors.pop();
227 if (!common_ancestor)
231 auto* common_ancestor_platform_node =
233 if (common_ancestor_platform_node ==
this)
234 return std::optional<int>(-1);
235 if (common_ancestor_platform_node == &other)
236 return std::optional<int>(1);
240 if (!our_ancestors.empty() && !other_ancestors.empty()) {
241 std::optional<int> this_index_in_parent =
243 std::optional<int> other_index_in_parent =
246 if (!this_index_in_parent || !other_index_in_parent)
249 int this_uncommon_ancestor_index = this_index_in_parent.value();
250 int other_uncommon_ancestor_index = other_index_in_parent.value();
251 if (this_uncommon_ancestor_index == other_uncommon_ancestor_index) {
253 <<
"Deepest uncommon ancestors should truly be uncommon, i.e. not "
258 return std::optional<int>(this_uncommon_ancestor_index -
259 other_uncommon_ancestor_index);
288void AXPlatformNodeBase::AnnounceText(
const std::u16string&
text) {}
299 if (
this == ancestor)
394 float*
value)
const {
437 std::string*
value)
const {
446 return std::u16string();
452 std::u16string*
value)
const {
472 }
while (current_node);
490 }
while (current_node);
502 std::string*
value)
const {
515 }
while (current_node);
522 std::u16string*
value)
const {
523 std::string value_utf8;
547 std::vector<int32_t>*
value)
const {
633 return std::u16string();
648 return std::u16string();
654 std::u16string
value =
668 (
GetData().GetImageAnnotationStatus() ==
670 GetData().GetImageAnnotationStatus() ==
679 std::u16string role_description =
682 if (!role_description.empty()) {
683 return role_description;
739 std::optional<int32_t> cell_id =
table->delegate_->CellIndexToId(index);
744 table->delegate_->GetFromNodeID(*cell_id));
762 std::optional<int32_t> cell_id =
table->delegate_->GetCellId(row, column);
767 table->delegate_->GetFromNodeID(*cell_id));
791 return table->delegate_->GetTableColCount();
803 return table->delegate_->GetTableAriaColCount();
831 return table->delegate_->GetTableRowCount();
843 return table->delegate_->GetTableAriaRowCount();
882 if (unignored_selection)
942 std::u16string
value =
976 std::u16string role_description =
978 if (!role_description.empty() ||
1011 "container-live", attributes);
1013 "container-relevant", attributes);
1015 "container-atomic", attributes);
1017 "container-busy", attributes);
1056 int32_t aria_current_state;
1058 &aria_current_state)) {
1120 "colindex", attributes);
1132 if (attr ==
"aria-coltext") {
1135 if (attr ==
"aria-rowtext") {
1142 int32_t sort_direction;
1166 std::string colspan;
1167 if (
GetData().GetHtmlAttribute(
"aria-colspan", &colspan)) {
1171 std::string rowspan;
1172 if (
GetData().GetHtmlAttribute(
"aria-rowspan", &rowspan)) {
1197 std::string class_attr;
1204 std::string datetime;
1206 GetData().GetHtmlAttribute(
"datetime", &datetime)) {
1212 if (
GetData().GetHtmlAttribute(
"id", &
id)) {
1226 switch (text_align) {
1248 std::stringstream
value;
1249 value << std::fixed << std::setprecision(2) << text_indent <<
"mm";
1261 std::string details_roles = ComputeDetailsRoles();
1262 if (!details_roles.empty())
1295 if (maybe_value.has_value()) {
1302 const std::string&
value,
1328 std::u16string hypertext;
1334 if (child_iter->IsText()) {
1338 int32_t child_unique_id = child_iter->GetUniqueId();
1356 return std::nullopt;
1362 return std::nullopt;
1371 switch (scroll_type) {
1372 case ScrollType::TopLeft:
1375 case ScrollType::BottomRight:
1378 case ScrollType::TopEdge:
1381 case ScrollType::BottomEdge:
1384 case ScrollType::LeftEdge:
1387 case ScrollType::RightEdge:
1390 case ScrollType::Anywhere:
1424 std::map<int32_t, int32_t>::iterator iterator =
1429 int32_t index = iterator->second;
1454 int32_t hyperlink_index) {
1456 if (offset_index.second == hyperlink_index)
1457 return offset_index.first;
1473 int32_t hypertext_offset = 0;
1477 if (child_iter->IsText()) {
1479 static_cast<int32_t
>(child_iter->GetHypertext().size());
1484 return hypertext_offset;
1488 if (hyperlink_index < 0)
1498 while (parent_object && parent_object !=
this) {
1499 descendant = parent_object;
1511 int endpoint_offset) {
1530 if (endpoint_object->
IsLeaf()) {
1532 return endpoint_offset;
1541 return static_cast<int>(endpoint_object->
GetHypertext().size());
1553 while (common_parent && !endpoint_object->
IsDescendantOf(common_parent)) {
1568 if (common_parent ==
this) {
1569 int32_t hypertext_offset =
1573 if (parent ==
this && endpoint_object->
IsText()) {
1577 hypertext_offset += endpoint_offset;
1580 return hypertext_offset;
1588 std::optional<int> endpoint_index_in_common_parent;
1597 if (endpoint_index_in_common_parent < index_in_common_parent)
1599 if (endpoint_index_in_common_parent > index_in_common_parent)
1615 int anchor_offset =
static_cast<int>(selection->
anchor_offset);
1627 int focus_offset =
static_cast<int>(selection->
focus_offset);
1632 int* selection_end) {
1637 int* selection_start,
1638 int* selection_end) {
1652 selection = &unignored_selection;
1660 int* selection_start,
1661 int* selection_end) {
1666 if (*selection_start < 0 || *selection_end < 0)
1681 if (*selection_start == *selection_end && !
HasCaret(selection)) {
1682 *selection_start = -1;
1683 *selection_end = -1;
1693 int* largest_offset =
1694 (*selection_start <= *selection_end) ? selection_end : selection_start;
1700 int hyperlink_selection_start, hyperlink_selection_end;
1702 &hyperlink_selection_end);
1703 if (hyperlink_selection_start >= 0 && hyperlink_selection_end >= 0 &&
1704 hyperlink_selection_start != hyperlink_selection_end) {
1705 ++(*largest_offset);
1711 size_t old_char_index,
1712 size_t new_char_index) {
1713 if (old_char_index >= old_hypertext.
hypertext.size() ||
1720 char16_t old_ch = old_hypertext.
hypertext[old_char_index];
1722 if (old_ch != new_ch)
1729 const std::map<int32_t, int32_t>& old_offset_to_index =
1731 const std::vector<int32_t>& old_hyperlinks = old_hypertext.
hyperlinks;
1732 int32_t old_hyperlinkscount =
static_cast<int32_t
>(old_hyperlinks.size());
1733 auto iter = old_offset_to_index.find(
static_cast<int32_t
>(old_char_index));
1734 int old_index = (iter != old_offset_to_index.end()) ? iter->second : -1;
1735 int old_child_id = (old_index >= 0 && old_index < old_hyperlinkscount)
1736 ? old_hyperlinks[old_index]
1739 const std::map<int32_t, int32_t>& new_offset_to_index =
1742 int32_t new_hyperlinkscount =
static_cast<int32_t
>(new_hyperlinks.size());
1743 iter = new_offset_to_index.find(
static_cast<int32_t
>(new_char_index));
1744 int new_index = (iter != new_offset_to_index.end()) ? iter->second : -1;
1745 int new_child_id = (new_index >= 0 && new_index < new_hyperlinkscount)
1746 ? new_hyperlinks[new_index]
1749 return old_child_id == new_child_id;
1755 bool is_indexed_from_end) {
1756 size_t text_len =
text.size();
1757 if (index == text_len)
1759 auto ch =
text[is_indexed_from_end ? text_len - index - 1 : index];
1782 float shortest_distance;
1783 while (parent && current_descendant) {
1785 float current_distance = current_descendant->
GetDelegate()
1789 if (!nearest_descendant || current_distance < shortest_distance) {
1790 shortest_distance = current_distance;
1791 nearest_descendant = current_descendant;
1797 current_descendant = next_sibling;
1801 if (nearest_descendant) {
1802 nearest_node = nearest_descendant;
1807 parent = nearest_node;
1812 nearest_descendant =
nullptr;
1816 return nearest_node;
1824 int nearest_index = 0;
1832 0, 1, coordinate_system, clipping_behavior)
1835 float current_distance =
1840 if (current_distance < shortest_distance) {
1841 shortest_distance = current_distance;
1845 return nearest_index;
1863 std::string invalid_value(
"");
1874 invalid_value =
"true";
1877 if (!
target->GetStringAttribute(
1880 invalid_value =
"true";
1885 return invalid_value;
1895 attributes.push_back(std::make_pair(
"auto-generated",
"true"));
1904 if (alpha && (red != 255 || green != 255 || blue != 255)) {
1909 attributes.push_back(std::make_pair(
"background-color", color_value));
1918 if (red || green || blue) {
1923 attributes.push_back(std::make_pair(
"color", color_value));
1930 std::string font_family(
GetDelegate()->GetInheritedFontFamilyName());
1931 if (font_family.empty()) {
1937 if (!font_family.empty()) {
1939 attributes.push_back(std::make_pair(
"font-family", font_family));
1944 if (font_size_in_points) {
1945 attributes.push_back(std::make_pair(
1956 attributes.push_back(std::make_pair(
"font-weight",
"bold"));
1958 attributes.push_back(std::make_pair(
"font-style",
"italic"));
1961 attributes.push_back(std::make_pair(
"text-line-through-style",
"solid"));
1965 attributes.push_back(std::make_pair(
"text-underline-style",
"solid"));
1973 if (!invalid_value.empty())
1974 attributes.push_back(std::make_pair(
"invalid", invalid_value));
1977 if (!language.empty()) {
1979 attributes.push_back(std::make_pair(
"language", language));
1984 switch (text_direction) {
1988 attributes.push_back(std::make_pair(
"writing-mode",
"lr"));
1991 attributes.push_back(std::make_pair(
"writing-mode",
"rl"));
1994 attributes.push_back(std::make_pair(
"writing-mode",
"tb"));
1998 attributes.push_back(std::make_pair(
"writing-mode",
"bt"));
2004 switch (text_position) {
2008 attributes.push_back(std::make_pair(
"text-position",
"sub"));
2011 attributes.push_back(std::make_pair(
"text-position",
"super"));
2026 int selected_index)
const {
2031 if (selected_index >= max_items)
2034 std::vector<AXPlatformNodeBase*> selected_children;
2035 int requested_count = selected_index + 1;
2036 int returned_count =
GetSelectedItems(requested_count, &selected_children);
2038 if (returned_count <= selected_index)
2042 BASE_DCHECK(selected_index <
static_cast<int>(selected_children.size()));
2043 return selected_children[selected_index];
2048 std::vector<AXPlatformNodeBase*>* out_selected_items)
const {
2049 int selected_count = 0;
2053 if (!
IsItemLike(child_iter->GetData().role)) {
2054 selected_count += child_iter->GetSelectedItems(max_items - selected_count,
2055 out_selected_items);
2056 }
else if (child_iter->GetBoolAttribute(
2059 if (out_selected_items)
2060 out_selected_items->emplace_back(child_iter.get());
2063 return selected_count;
2067 std::string*
output)
const {
2071std::string AXPlatformNodeBase::ComputeDetailsRoles()
const {
2072 const std::vector<int32_t>& details_ids =
2074 if (details_ids.empty())
2075 return std::string();
2077 std::set<std::string> details_roles_set;
2079 for (
int id : details_ids) {
2086 details_roles_set.insert(
"comment");
2089 details_roles_set.insert(
"definition");
2092 details_roles_set.insert(
"doc-endnote");
2095 details_roles_set.insert(
"doc-footnote");
2100 constexpr int kMaxChildrenToCheck = 8;
2101 constexpr int kMaxDepthToCheck = 4;
2102 if (FindDescendantRoleWithMaxDepth(
2104 kMaxChildrenToCheck)) {
2105 details_roles_set.insert(
"comment");
2112 details_roles_set.insert(
"*");
2119 std::vector<std::string> details_roles_vector(details_roles_set.begin(),
2120 details_roles_set.end());
static void round(SkPoint *p)
static const int points[]
ax::mojom::Event event_type
int find(T *array, int N, T item)
constexpr int height() const
int ManhattanDistanceToPoint(const Point &point) const
constexpr int right() const
constexpr int bottom() const
Vector2d OffsetFromOrigin() const
constexpr int width() const
static float max(float r, float g, float b)
static float min(float r, float g, float b)
@ kSilentlyEligibleForAnnotation
std::string UTF16ToUTF8(std::u16string src)
void ReplaceChars(std::string in, std::string from, std::string to, std::string *out)
const std::string & EmptyString()
std::u16string UTF8ToUTF16(std::string src)
std::string JoinString(std::vector< std::string > tokens, std::string delimiter)
std::string NumberToString(int32_t number)
std::u16string NumberToString16(float number)
DEF_SWITCHES_START aot vmservice shared library name
Rect ToEnclosingRect(const RectF &r)
UnimplementedNativeViewAccessible * NativeViewAccessible
UniqueIdMap g_unique_id_map
bool IsRangeValueSupported(const ax::mojom::Role role)
bool IsContainerWithSelectableChildren(const ax::mojom::Role role)
bool IsCellOrTableHeader(const ax::mojom::Role role)
bool IsTableRow(ax::mojom::Role role)
bool IsItemLike(const ax::mojom::Role role)
std::vector< TextAttribute > TextAttributeList
bool IsTableLike(const ax::mojom::Role role)
bool IsTableHeader(ax::mojom::Role role)
std::optional< int32_t > ComputeAttribute(const ui::AXPlatformNodeDelegate *delegate, ax::mojom::IntAttribute attribute)
std::unordered_map< int32_t, AXPlatformNode * > UniqueIdMap
bool IsDocument(const ax::mojom::Role role)
ax::mojom::ScrollBehavior scroll_behavior
ax::mojom::ScrollAlignment vertical_scroll_alignment
ax::mojom::ScrollAlignment horizontal_scroll_alignment
std::vector< int32_t > hyperlinks
std::map< int32_t, int32_t > hyperlink_offset_to_index
AXHypertext & operator=(const AXHypertext &other)
bool IsPlainTextField() const
bool HasIntAttribute(ax::mojom::IntAttribute attribute) const
bool HasCheckedState() const
bool HasIntListAttribute(ax::mojom::IntListAttribute attribute) const
bool HasFloatAttribute(ax::mojom::FloatAttribute attribute) const
bool HasStringAttribute(ax::mojom::StringAttribute attribute) const
std::string DropeffectBitfieldToString() const
bool IsRichTextField() const
std::vector< std::pair< std::string, std::string > > html_attributes
bool GetBoolAttribute(ax::mojom::BoolAttribute attribute) const
const std::vector< int32_t > & GetIntListAttribute(ax::mojom::IntListAttribute attribute) const
float GetFloatAttribute(ax::mojom::FloatAttribute attribute) const
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
bool GetString16Attribute(ax::mojom::StringAttribute attribute, std::u16string *value) const
#define BASE_DCHECK(condition)
#define BASE_UNREACHABLE()