Flutter Engine
The Flutter Engine
ax_platform_node_delegate_base.cc
Go to the documentation of this file.
1// Copyright 2018 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
6
7#include <vector>
8
9#include "ax/ax_action_data.h"
10#include "ax/ax_constants.h"
11#include "ax/ax_node_data.h"
13#include "ax/ax_tree_data.h"
14#include "base/no_destructor.h"
15
16#include "ax_platform_node.h"
18
19namespace ui {
20
22
24
26 static base::NoDestructor<AXNodeData> empty_data;
27 return *empty_data;
28}
29
31 static base::NoDestructor<AXTreeData> empty_data;
32 return *empty_data;
33}
34
36 // Unlike in web content The "kValue" attribute always takes precedence,
37 // because we assume that users of this base class, such as Views controls,
38 // are carefully crafted by hand, in contrast to HTML pages, where any content
39 // that might be present in the shadow DOM (AKA in the internal accessibility
40 // tree) is actually used by the renderer when assigning the "kValue"
41 // attribute, including any redundant white space.
42 std::u16string value =
44 if (!value.empty())
45 return value;
46
47 // TODO(https://crbug.com/1030703): The check for IsInvisibleOrIgnored()
48 // should not be needed. ChildAtIndex() and GetChildCount() are already
49 // supposed to skip over nodes that are invisible or ignored, but
50 // ViewAXPlatformNodeDelegate does not currently implement this behavior.
51 if (IsLeaf() && !GetData().IsInvisibleOrIgnored())
53
54 std::u16string inner_text;
55 for (int i = 0; i < GetChildCount(); ++i) {
56 // TODO(nektar): Add const to all tree traversal methods and remove
57 // const_cast.
59 const_cast<AXPlatformNodeDelegateBase*>(this)->ChildAtIndex(i));
60 if (!child || !child->GetDelegate())
61 continue;
62 inner_text += child->GetDelegate()->GetInnerText();
63 }
64 return inner_text;
65}
66
68 const {
70}
71
75}
76
78 return nullptr;
79}
80
83 return nullptr;
84}
85
87 return nullptr;
88}
89
92 AXPlatformNodeDelegateBase* current_delegate =
93 const_cast<AXPlatformNodeDelegateBase*>(this);
94 AXPlatformNodeDelegateBase* lowest_unignored_delegate = current_delegate;
95
96 // `highest_leaf_delegate` could be nullptr.
97 AXPlatformNodeDelegateBase* highest_leaf_delegate = lowest_unignored_delegate;
98 // For the purposes of this method, a leaf node does not include leaves in the
99 // internal accessibility tree, only in the platform exposed tree.
100 for (AXPlatformNodeDelegateBase* ancestor_delegate =
101 lowest_unignored_delegate;
102 ancestor_delegate;
103 ancestor_delegate = static_cast<AXPlatformNodeDelegateBase*>(
104 ancestor_delegate->GetParentDelegate())) {
105 if (ancestor_delegate->IsLeaf())
106 highest_leaf_delegate = ancestor_delegate;
107 }
108 if (highest_leaf_delegate)
109 return highest_leaf_delegate->GetNativeViewAccessible();
110
111 if (lowest_unignored_delegate)
112 return lowest_unignored_delegate->GetNativeViewAccessible();
113 return current_delegate->GetNativeViewAccessible();
114}
115
117 return 0;
118}
119
121 return nullptr;
122}
123
125 return false;
126}
127
129 if (GetChildCount() > 0)
130 return ChildAtIndex(0);
131 return nullptr;
132}
133
135 if (GetChildCount() > 0)
136 return ChildAtIndex(GetChildCount() - 1);
137 return nullptr;
138}
139
142 if (parent && GetIndexInParent() >= 0) {
143 int next_index = GetIndexInParent() + 1;
144 if (next_index >= 0 && next_index < parent->GetChildCount())
145 return parent->ChildAtIndex(next_index);
146 }
147 return nullptr;
148}
149
152 if (parent && GetIndexInParent() >= 0) {
153 int next_index = GetIndexInParent() - 1;
154 if (next_index >= 0 && next_index < parent->GetChildCount())
155 return parent->ChildAtIndex(next_index);
156 }
157 return nullptr;
158}
159
161 // TODO(nektar): Make all tree traversal methods const and remove const_cast.
162 const AXPlatformNodeDelegate* parent =
163 const_cast<AXPlatformNodeDelegateBase*>(this)->GetParentDelegate();
164 if (!parent)
165 return false;
166 if (parent->IsLeaf())
167 return true;
168 return parent->IsChildOfLeaf();
169}
170
172 return !GetChildCount();
173}
174
176 return false;
177}
178
180 return false;
181}
182
184 const {
185 return nullptr;
186}
187
190 int index)
191 : index_(index), parent_(parent) {
192 BASE_DCHECK(parent);
193 BASE_DCHECK(0 <= index && index <= parent->GetChildCount());
194}
195
198 : index_(it.index_), parent_(it.parent_) {
199 BASE_DCHECK(parent_);
200}
201
203 const AXPlatformNodeDelegate::ChildIterator& rhs) const {
204 return rhs.GetIndexInParent() == index_;
205}
206
208 const AXPlatformNodeDelegate::ChildIterator& rhs) const {
209 return rhs.GetIndexInParent() != index_;
210}
211
213 index_++;
214}
215
217 index_++;
218}
219
221 BASE_DCHECK(index_ > 0);
222 index_--;
223}
224
226 BASE_DCHECK(index_ > 0);
227 index_--;
228}
229
232 if (index_ < parent_->GetChildCount())
233 return parent_->ChildAtIndex(index_);
234
235 return nullptr;
236}
237
239 return index_;
240}
241
244 AXPlatformNode* platform_node =
246 BASE_DCHECK(platform_node && platform_node->GetDelegate());
247 return *(platform_node->GetDelegate());
248}
249
252 AXPlatformNode* platform_node =
254 return platform_node ? platform_node->GetDelegate() : nullptr;
255}
256
257std::unique_ptr<AXPlatformNodeDelegate::ChildIterator>
259 return std::make_unique<ChildIteratorBase>(this, 0);
260}
261
262std::unique_ptr<AXPlatformNodeDelegate::ChildIterator>
264 return std::make_unique<ChildIteratorBase>(this, GetChildCount());
265}
266
269}
270
272 return std::u16string();
273}
274
276 int end_offset) {
277 AXActionData action_data;
279 action_data.anchor_node_id = action_data.focus_node_id = GetData().id;
280 action_data.anchor_offset = start_offset;
281 action_data.focus_offset = end_offset;
282 return AccessibilityPerformAction(action_data);
283}
284
286 const AXCoordinateSystem coordinate_system,
287 const AXClippingBehavior clipping_behavior,
288 AXOffscreenResult* offscreen_result) const {
289 return gfx::Rect();
290}
291
293 const int start_offset,
294 const int end_offset,
295 const AXCoordinateSystem coordinate_system,
296 const AXClippingBehavior clipping_behavior,
297 AXOffscreenResult* offscreen_result) const {
298 return gfx::Rect();
299}
300
302 const int start_offset,
303 const int end_offset,
304 const AXCoordinateSystem coordinate_system,
305 const AXClippingBehavior clipping_behavior,
306 AXOffscreenResult* offscreen_result = nullptr) const {
307 return gfx::Rect();
308}
309
311 AXOffscreenResult* offscreen_result) const {
313 AXClippingBehavior::kClipped, offscreen_result);
314}
315
317 AXOffscreenResult* offscreen_result) const {
319 AXClippingBehavior::kUnclipped, offscreen_result);
320}
321
323 int screen_physical_pixel_x,
324 int screen_physical_pixel_y) const {
325 return nullptr;
326}
327
329 return nullptr;
330}
331
333 return nullptr;
334}
335
337 const ui::AXTreeID& ax_tree_id,
338 int32_t id) {
339 return nullptr;
340}
341
344 if (!parent)
345 return -1;
346
347 for (int i = 0; i < parent->GetChildCount(); i++) {
348 AXPlatformNode* child_node =
350 if (child_node && child_node->GetDelegate() == this)
351 return i;
352 }
353 return -1;
354}
355
356gfx::AcceleratedWidget
358 return gfx::kNullAcceleratedWidget;
359}
360
362 return ui::IsTableLike(GetData().role);
363}
364
367}
368
371}
372
374 int aria_column_count;
376 &aria_column_count)) {
377 return std::nullopt;
378 }
379 return aria_column_count;
380}
381
383 int aria_row_count;
384 if (!GetData().GetIntAttribute(ax::mojom::IntAttribute::kAriaRowCount,
385 &aria_row_count)) {
386 return std::nullopt;
387 }
388 return aria_row_count;
389}
390
392 return std::nullopt;
393}
394
395std::optional<bool>
397 return std::nullopt;
398}
399
401 return {};
402}
403
405 int col_index) const {
406 return {};
407}
408
410 return {};
411}
412
414 int row_index) const {
415 return {};
416}
417
419 return nullptr;
420}
421
423 return ui::IsTableRow(GetData().role);
424}
425
428}
429
431 return ui::IsCellOrTableHeader(GetData().role);
432}
433
435 return GetData().GetIntAttribute(
437}
438
441}
442
444 return GetData().GetIntAttribute(
446}
447
450}
451
453 const {
454 return GetData().GetIntAttribute(
456}
457
459 const {
461}
462
464 int row_index,
465 int col_index) const {
466 return std::nullopt;
467}
468
470 return std::nullopt;
471}
472
474 int cell_index) const {
475 return std::nullopt;
476}
477
479 return false;
480}
481
483 return false;
484}
485
487 return false;
488}
489
491 return false;
492}
493
494std::optional<int> AXPlatformNodeDelegateBase::GetPosInSet() const {
495 return std::nullopt;
496}
497
498std::optional<int> AXPlatformNodeDelegateBase::GetSetSize() const {
499 return std::nullopt;
500}
501
503 const ui::AXActionData& data) {
504 return false;
505}
506
507std::u16string
510 return std::u16string();
511}
512
513std::u16string
515 const {
516 return std::u16string();
517}
518
520 const {
521 return std::u16string();
522}
523
524std::u16string
526 return std::u16string();
527}
528
529std::u16string
531 return std::u16string();
532}
533
535 const TextAttributeList& default_attributes) const {
536 ui::TextAttributeMap attributes_map;
537 attributes_map[0] = default_attributes;
538 return attributes_map;
539}
540
542 // We don't have access to AXNodeData here, so we cannot return
543 // an inherited font family name.
544 return std::string();
545}
546
548 return true;
549}
550
552 return false;
553}
554
556 return false;
557}
558
560 return ui::IsText(GetData().role);
561}
562
564 return false;
565}
566
568 return false;
569}
570
574
575 int target_id;
576 if (!GetData().GetIntAttribute(attr, &target_id))
577 return nullptr;
578
579 return GetFromNodeID(target_id);
580}
581
583 const std::set<int32_t>& ids) {
584 std::set<AXPlatformNode*> nodes;
585 for (int32_t node_id : ids) {
586 if (AXPlatformNode* node = GetFromNodeID(node_id)) {
587 nodes.insert(node);
588 }
589 }
590 return nodes;
591}
592
593std::vector<AXPlatformNode*>
597 std::vector<int32_t> target_ids;
598 if (!GetData().GetIntListAttribute(attr, &target_ids))
599 return std::vector<AXPlatformNode*>();
600
601 // If we use std::set to eliminate duplicates, the resulting set will be
602 // sorted by the id and we will lose the original order which may be of
603 // interest to ATs. The number of ids should be small.
604
605 std::vector<ui::AXPlatformNode*> nodes;
606 for (int32_t target_id : target_ids) {
607 if (ui::AXPlatformNode* node = GetFromNodeID(target_id)) {
608 if (std::find(nodes.begin(), nodes.end(), node) == nodes.end())
609 nodes.push_back(node);
610 }
611 }
612
613 return nodes;
614}
615
618 // TODO(accessibility) Implement these if views ever use relations more
619 // widely. The use so far has been for the Omnibox to the suggestion popup.
620 // If this is ever implemented, then the "popup for" to "controlled by"
621 // mapping in AXPlatformRelationWin can be removed, as it would be
622 // redundant with setting the controls relationship.
623 return std::set<AXPlatformNode*>();
624}
625
628 return std::set<AXPlatformNode*>();
629}
630
632 return std::u16string();
633}
634
636 static base::NoDestructor<AXUniqueId> dummy_unique_id;
637 return *dummy_unique_id;
638}
639
642 int offset,
643 ax::mojom::MoveDirection direction,
644 ax::mojom::TextAffinity affinity) const {
645 return std::nullopt;
646}
647
648const std::vector<gfx::NativeViewAccessible>
650 return {};
651}
652
654 return std::string();
655}
656
658 AXPlatformNode* parent_node =
660 if (parent_node)
661 return parent_node->GetDelegate();
662
663 return nullptr;
664}
665
667 std::string result(level * 2, '+');
668 result += ToString();
669 result += '\n';
670
671 // We can't use ChildrenBegin() and ChildrenEnd() here, because they both
672 // return an std::unique_ptr<ChildIterator> which is an abstract class.
673 //
674 // TODO(accessibility): Refactor ChildIterator into a separate base
675 // (non-abstract) class.
676 auto iter_start = ChildIteratorBase(this, 0);
677 auto iter_end = ChildIteratorBase(this, GetChildCount());
678 for (auto iter = iter_start; iter != iter_end; ++iter) {
680 static_cast<AXPlatformNodeDelegateBase&>(*iter);
681 result += child.SubtreeToStringHelper(level + 1);
682 }
683
684 return result;
685}
686
687} // namespace ui
int find(T *array, int N, T item)
Definition: rect.h:36
gfx::NativeViewAccessible GetNativeViewAccessible() const override
bool operator!=(const ChildIterator &rhs) const override
ChildIteratorBase(AXPlatformNodeDelegateBase *parent, int index)
bool operator==(const ChildIterator &rhs) const override
std::optional< int32_t > GetCellId(int row_index, int col_index) const override
std::optional< int > GetTableCellRowIndex() const override
std::optional< int > GetTableAriaColCount() const override
std::string GetInheritedFontFamilyName() const override
gfx::NativeViewAccessible GetLowestPlatformAncestor() const override
std::u16string GetLocalizedStringForImageAnnotationStatus(ax::mojom::ImageAnnotationStatus status) const override
std::unique_ptr< AXPlatformNodeDelegate::ChildIterator > ChildrenBegin() override
TextAttributeMap ComputeTextAttributeMap(const TextAttributeList &default_attributes) const override
gfx::NativeViewAccessible GetClosestPlatformObject() const override
AXPlatformNode * GetTableCaption() const override
gfx::Rect GetHypertextRangeBoundsRect(const int start_offset, const int end_offset, const AXCoordinateSystem coordinate_system, const AXClippingBehavior clipping_behavior, AXOffscreenResult *offscreen_result) const override
std::string SubtreeToStringHelper(size_t level) override
std::optional< int > FindTextBoundary(ax::mojom::TextBoundary boundary, int offset, ax::mojom::MoveDirection direction, ax::mojom::TextAffinity affinity) const override
gfx::Rect GetInnerTextRangeBoundsRect(const int start_offset, const int end_offset, const AXCoordinateSystem coordinate_system, const AXClippingBehavior clipping_behavior, AXOffscreenResult *offscreen_result) const override
const std::vector< gfx::NativeViewAccessible > GetUIADescendants() const override
std::optional< int > GetPosInSet() const override
std::u16string GetInnerText() const override
std::optional< int > GetTableCellAriaColIndex() const override
std::optional< int > GetTableRowCount() const override
gfx::NativeViewAccessible GetNativeViewAccessible() override
gfx::NativeViewAccessible GetFirstChild() override
std::optional< int > GetTableCellIndex() const override
bool AccessibilityPerformAction(const AXActionData &data) override
std::u16string GetLocalizedStringForLandmarkType() const override
std::optional< int > GetTableCellCount() const override
std::optional< int > GetTableCellAriaRowIndex() const override
std::optional< int > GetTableAriaRowCount() const override
std::optional< int > GetTableRowRowIndex() const override
gfx::NativeViewAccessible GetLastChild() override
std::vector< int32_t > GetRowHeaderNodeIds() const override
gfx::Rect GetUnclippedScreenBoundsRect(AXOffscreenResult *offscreen_result=nullptr) const
std::optional< int > GetTableCellColSpan() const override
std::u16string GetHypertext() const override
std::u16string GetAuthorUniqueId() const override
AXPlatformNode * GetFromTreeIDAndNodeID(const ui::AXTreeID &ax_tree_id, int32_t id) override
const AXTree::Selection GetUnignoredSelection() const override
std::vector< AXPlatformNode * > GetTargetNodesForRelation(ax::mojom::IntListAttribute attr) override
AXPlatformNode * GetFromNodeID(int32_t id) override
AXPlatformNode * GetTargetNodeForRelation(ax::mojom::IntAttribute attr) override
std::optional< bool > GetTableHasColumnOrRowHeaderNode() const override
gfx::Rect GetBoundsRect(const AXCoordinateSystem coordinate_system, const AXClippingBehavior clipping_behavior, AXOffscreenResult *offscreen_result) const override
gfx::NativeViewAccessible GetNextSibling() override
std::u16string GetStyleNameAttributeAsLocalizedString() const override
gfx::NativeViewAccessible GetParent() override
gfx::NativeViewAccessible HitTestSync(int screen_physical_pixel_x, int screen_physical_pixel_y) const override
const AXUniqueId & GetUniqueId() const override
gfx::NativeViewAccessible GetPreviousSibling() override
const AXTreeData & GetTreeData() const override
std::optional< int > GetSetSize() const override
bool SetHypertextSelection(int start_offset, int end_offset) override
std::optional< int > GetTableCellColIndex() const override
gfx::Rect GetClippedScreenBoundsRect(AXOffscreenResult *offscreen_result=nullptr) const override
gfx::NativeViewAccessible ChildAtIndex(int index) override
std::optional< int32_t > CellIndexToId(int cell_index) const override
std::u16string GetLocalizedRoleDescriptionForUnlabeledImage() const override
std::vector< int32_t > GetColHeaderNodeIds() const override
std::u16string GetLocalizedStringForRoleDescription() const override
std::set< ui::AXPlatformNode * > GetNodesForNodeIds(const std::set< int32_t > &ids)
gfx::NativeViewAccessible GetNSWindow() override
std::optional< int > GetTableColCount() const override
gfx::AcceleratedWidget GetTargetForNativeAccessibilityEvent() override
AXNodePosition::AXPositionInstance CreateTextPositionAt(int offset) const override
const AXNodeData & GetData() const override
std::unique_ptr< AXPlatformNodeDelegate::ChildIterator > ChildrenEnd() override
std::set< AXPlatformNode * > GetReverseRelations(ax::mojom::IntAttribute attr) override
std::optional< int > GetTableCellRowSpan() const override
gfx::NativeViewAccessible GetFocus() override
virtual std::u16string GetInnerText() const =0
virtual bool IsLeaf() const =0
virtual gfx::NativeViewAccessible ChildAtIndex(int index)=0
virtual bool IsChildOfLeaf() const =0
virtual int GetChildCount() const =0
static AXPlatformNode * FromNativeViewAccessible(gfx::NativeViewAccessible accessible)
virtual AXPlatformNodeDelegate * GetDelegate() const =0
std::unique_ptr< AXPosition< AXNodePosition, AXNode > > AXPositionInstance
Definition: ax_position.h:163
static AXPositionInstance CreateNullPosition()
Definition: ax_position.h:183
uint8_t value
GAsyncResult * result
ImageAnnotationStatus
Definition: ax_enums.h:1170
IntListAttribute
Definition: ax_enums.h:799
UnimplementedNativeViewAccessible * NativeViewAccessible
TRect< Scalar > Rect
Definition: rect.h:769
bool IsNodeIdIntAttribute(ax::mojom::IntAttribute attr)
Definition: ax_node_data.cc:99
bool IsCellOrTableHeader(const ax::mojom::Role role)
bool IsTableRow(ax::mojom::Role role)
std::vector< TextAttribute > TextAttributeList
bool IsTableLike(const ax::mojom::Role role)
bool IsNodeIdIntListAttribute(ax::mojom::IntListAttribute attr)
std::map< int, TextAttributeList > TextAttributeMap
bool IsText(ax::mojom::Role role)
SeparatedVector2 offset
ax::mojom::Action action
int GetIntAttribute(ax::mojom::IntAttribute attribute) const
const std::string & GetStringAttribute(ax::mojom::StringAttribute attribute) const
bool GetString16Attribute(ax::mojom::StringAttribute attribute, std::u16string *value) const
std::shared_ptr< const fml::Mapping > data
Definition: texture_gles.cc:63
#define BASE_DCHECK(condition)
Definition: logging.h:63