Flutter Engine
 
Loading...
Searching...
No Matches
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#include "base/string_utils.h"
16
17#include "ax_platform_node.h"
19
20namespace ui {
21
23
25
27 static base::NoDestructor<AXNodeData> empty_data;
28 return *empty_data;
29}
30
32 static base::NoDestructor<AXTreeData> empty_data;
33 return *empty_data;
34}
35
37 // Unlike in web content The "kValue" attribute always takes precedence,
38 // because we assume that users of this base class, such as Views controls,
39 // are carefully crafted by hand, in contrast to HTML pages, where any content
40 // that might be present in the shadow DOM (AKA in the internal accessibility
41 // tree) is actually used by the renderer when assigning the "kValue"
42 // attribute, including any redundant white space.
43 std::u16string value =
45 if (!value.empty())
46 return value;
47
48 // TODO(https://crbug.com/1030703): The check for IsInvisibleOrIgnored()
49 // should not be needed. ChildAtIndex() and GetChildCount() are already
50 // supposed to skip over nodes that are invisible or ignored, but
51 // ViewAXPlatformNodeDelegate does not currently implement this behavior.
52 if (IsLeaf() && !GetData().IsInvisibleOrIgnored())
54
55 std::u16string inner_text;
56 for (int i = 0; i < GetChildCount(); ++i) {
57 // TODO(nektar): Add const to all tree traversal methods and remove
58 // const_cast.
60 const_cast<AXPlatformNodeDelegateBase*>(this)->ChildAtIndex(i));
61 if (!child || !child->GetDelegate())
62 continue;
63 inner_text += child->GetDelegate()->GetInnerText();
64 }
65 return inner_text;
66}
67
72
77
81
86
90
93 AXPlatformNodeDelegateBase* current_delegate =
94 const_cast<AXPlatformNodeDelegateBase*>(this);
95 AXPlatformNodeDelegateBase* lowest_unignored_delegate = current_delegate;
96
97 // `highest_leaf_delegate` could be nullptr.
98 AXPlatformNodeDelegateBase* highest_leaf_delegate = lowest_unignored_delegate;
99 // For the purposes of this method, a leaf node does not include leaves in the
100 // internal accessibility tree, only in the platform exposed tree.
101 for (AXPlatformNodeDelegateBase* ancestor_delegate =
102 lowest_unignored_delegate;
103 ancestor_delegate;
104 ancestor_delegate = static_cast<AXPlatformNodeDelegateBase*>(
105 ancestor_delegate->GetParentDelegate())) {
106 if (ancestor_delegate->IsLeaf())
107 highest_leaf_delegate = ancestor_delegate;
108 }
109 if (highest_leaf_delegate)
110 return highest_leaf_delegate->GetNativeViewAccessible();
111
112 if (lowest_unignored_delegate)
113 return lowest_unignored_delegate->GetNativeViewAccessible();
114 return current_delegate->GetNativeViewAccessible();
115}
116
118 return 0;
119}
120
124
126 return false;
127}
128
134
140
143 if (parent && GetIndexInParent() >= 0) {
144 int next_index = GetIndexInParent() + 1;
145 if (next_index >= 0 && next_index < parent->GetChildCount())
146 return parent->ChildAtIndex(next_index);
147 }
148 return nullptr;
149}
150
153 if (parent && GetIndexInParent() >= 0) {
154 int next_index = GetIndexInParent() - 1;
155 if (next_index >= 0 && next_index < parent->GetChildCount())
156 return parent->ChildAtIndex(next_index);
157 }
158 return nullptr;
159}
160
162 // TODO(nektar): Make all tree traversal methods const and remove const_cast.
163 const AXPlatformNodeDelegate* parent =
164 const_cast<AXPlatformNodeDelegateBase*>(this)->GetParentDelegate();
165 if (!parent)
166 return false;
167 if (parent->IsLeaf())
168 return true;
169 return parent->IsChildOfLeaf();
170}
171
173 return !GetChildCount();
174}
175
179
181 return false;
182}
183
188
191 int index)
192 : index_(index), parent_(parent) {
193 BASE_DCHECK(parent);
194 BASE_DCHECK(0 <= index && index <= parent->GetChildCount());
195}
196
199 : index_(it.index_), parent_(it.parent_) {
200 BASE_DCHECK(parent_);
201}
202
207
212
216
220
225
227 BASE_DCHECK(index_ > 0);
228 index_--;
229}
230
233 if (index_ < parent_->GetChildCount())
234 return parent_->ChildAtIndex(index_);
235
236 return nullptr;
237}
238
242
245 AXPlatformNode* platform_node =
247 BASE_DCHECK(platform_node && platform_node->GetDelegate());
248 return *(platform_node->GetDelegate());
249}
250
253 AXPlatformNode* platform_node =
255 return platform_node ? platform_node->GetDelegate() : nullptr;
256}
257
258std::unique_ptr<AXPlatformNodeDelegate::ChildIterator>
260 return std::make_unique<ChildIteratorBase>(this, 0);
261}
262
263std::unique_ptr<AXPlatformNodeDelegate::ChildIterator>
265 return std::make_unique<ChildIteratorBase>(this, GetChildCount());
266}
267
271
273 return std::u16string();
274}
275
277 int end_offset) {
278 AXActionData action_data;
280 action_data.anchor_node_id = action_data.focus_node_id = GetData().id;
281 action_data.anchor_offset = start_offset;
282 action_data.focus_offset = end_offset;
283 return AccessibilityPerformAction(action_data);
284}
285
287 const AXCoordinateSystem coordinate_system,
288 const AXClippingBehavior clipping_behavior,
289 AXOffscreenResult* offscreen_result) const {
290 return gfx::Rect();
291}
292
294 const int start_offset,
295 const int end_offset,
296 const AXCoordinateSystem coordinate_system,
297 const AXClippingBehavior clipping_behavior,
298 AXOffscreenResult* offscreen_result) const {
299 return gfx::Rect();
300}
301
303 const int start_offset,
304 const int end_offset,
305 const AXCoordinateSystem coordinate_system,
306 const AXClippingBehavior clipping_behavior,
307 AXOffscreenResult* offscreen_result = nullptr) const {
308 return gfx::Rect();
309}
310
316
322
324 int screen_physical_pixel_x,
325 int screen_physical_pixel_y) const {
326 return nullptr;
327}
328
332
334 return nullptr;
335}
336
338 const ui::AXTreeID& ax_tree_id,
339 int32_t id) {
340 return nullptr;
341}
342
345 if (!parent)
346 return -1;
347
348 for (int i = 0; i < parent->GetChildCount(); i++) {
349 AXPlatformNode* child_node =
351 if (child_node && child_node->GetDelegate() == this)
352 return i;
353 }
354 return -1;
355}
356
357gfx::AcceleratedWidget
359 return gfx::kNullAcceleratedWidget;
360}
361
363 return ui::IsTableLike(GetData().role);
364}
365
369
373
375 int aria_column_count;
377 &aria_column_count)) {
378 return std::nullopt;
379 }
380 return aria_column_count;
381}
382
384 int aria_row_count;
385 if (!GetData().GetIntAttribute(ax::mojom::IntAttribute::kAriaRowCount,
386 &aria_row_count)) {
387 return std::nullopt;
388 }
389 return aria_row_count;
390}
391
393 return std::nullopt;
394}
395
396std::optional<bool>
400
402 return {};
403}
404
406 int col_index) const {
407 return {};
408}
409
411 return {};
412}
413
415 int row_index) const {
416 return {};
417}
418
422
424 return ui::IsTableRow(GetData().role);
425}
426
430
434
439
443
448
452
458
463
465 int row_index,
466 int col_index) const {
467 return std::nullopt;
468}
469
471 return std::nullopt;
472}
473
475 int cell_index) const {
476 return std::nullopt;
477}
478
480 return false;
481}
482
484 return false;
485}
486
488 return false;
489}
490
492 return false;
493}
494
495std::optional<int> AXPlatformNodeDelegateBase::GetPosInSet() const {
496 return std::nullopt;
497}
498
499std::optional<int> AXPlatformNodeDelegateBase::GetSetSize() const {
500 return std::nullopt;
501}
502
507
508std::u16string
513
514std::u16string
519
521 const {
522 return std::u16string();
523}
524
525std::u16string
529
530std::u16string
534
536 const TextAttributeList& default_attributes) const {
537 ui::TextAttributeMap attributes_map;
538 attributes_map[0] = default_attributes;
539 return attributes_map;
540}
541
543 // We don't have access to AXNodeData here, so we cannot return
544 // an inherited font family name.
545 return std::string();
546}
547
551
553 return false;
554}
555
557 return false;
558}
559
561 return ui::IsText(GetData().role);
562}
563
565 return false;
566}
567
569 return false;
570}
571
575
576 int target_id;
577 if (!GetData().GetIntAttribute(attr, &target_id))
578 return nullptr;
579
580 return GetFromNodeID(target_id);
581}
582
584 const std::set<int32_t>& ids) {
585 std::set<AXPlatformNode*> nodes;
586 for (int32_t node_id : ids) {
587 if (AXPlatformNode* node = GetFromNodeID(node_id)) {
588 nodes.insert(node);
589 }
590 }
591 return nodes;
592}
593
594std::vector<AXPlatformNode*>
598 std::vector<int32_t> target_ids;
599 if (!GetData().GetIntListAttribute(attr, &target_ids))
600 return std::vector<AXPlatformNode*>();
601
602 // If we use std::set to eliminate duplicates, the resulting set will be
603 // sorted by the id and we will lose the original order which may be of
604 // interest to ATs. The number of ids should be small.
605
606 std::vector<ui::AXPlatformNode*> nodes;
607 for (int32_t target_id : target_ids) {
608 if (ui::AXPlatformNode* node = GetFromNodeID(target_id)) {
609 if (std::find(nodes.begin(), nodes.end(), node) == nodes.end())
610 nodes.push_back(node);
611 }
612 }
613
614 return nodes;
615}
616
619 // TODO(accessibility) Implement these if views ever use relations more
620 // widely. The use so far has been for the Omnibox to the suggestion popup.
621 // If this is ever implemented, then the "popup for" to "controlled by"
622 // mapping in AXPlatformRelationWin can be removed, as it would be
623 // redundant with setting the controls relationship.
624 return std::set<AXPlatformNode*>();
625}
626
629 return std::set<AXPlatformNode*>();
630}
631
635
637 static base::NoDestructor<AXUniqueId> dummy_unique_id;
638 return *dummy_unique_id;
639}
640
643 int offset,
644 ax::mojom::MoveDirection direction,
645 ax::mojom::TextAffinity affinity) const {
646 return std::nullopt;
647}
648
649const std::vector<gfx::NativeViewAccessible>
653
655 return std::string();
656}
657
659 AXPlatformNode* parent_node =
661 if (parent_node)
662 return parent_node->GetDelegate();
663
664 return nullptr;
665}
666
668 std::string result(level * 2, '+');
669 result += ToString();
670 result += '\n';
671
672 // We can't use ChildrenBegin() and ChildrenEnd() here, because they both
673 // return an std::unique_ptr<ChildIterator> which is an abstract class.
674 //
675 // TODO(accessibility): Refactor ChildIterator into a separate base
676 // (non-abstract) class.
677 auto iter_start = ChildIteratorBase(this, 0);
678 auto iter_end = ChildIteratorBase(this, GetChildCount());
679 for (auto iter = iter_start; iter != iter_end; ++iter) {
681 static_cast<AXPlatformNodeDelegateBase&>(*iter);
682 result += child.SubtreeToStringHelper(level + 1);
683 }
684
685 return result;
686}
687
688} // namespace ui
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
static AXPositionInstance CreateNullPosition()
int32_t value
ImageAnnotationStatus
Definition ax_enums.h:1171
std::u16string UTF8ToUTF16(std::string src)
UnimplementedNativeViewAccessible * NativeViewAccessible
bool IsNodeIdIntAttribute(ax::mojom::IntAttribute attr)
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)
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
#define BASE_DCHECK(condition)
Definition logging.h:63