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();
860 float points = font_size * 72.0 / 96.0;
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)) {
1219 GetData().GetHtmlAttribute(
"src", &src)) {
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) {
1410 std::string* output) {
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());
2136 max_items = std::numeric_limits<int>::max();
static const int points[]
ax::mojom::Event event_type
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
@ 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)
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()