Flutter Engine
The Flutter Engine
ax_tree.h
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#ifndef UI_ACCESSIBILITY_AX_TREE_H_
6#define UI_ACCESSIBILITY_AX_TREE_H_
7
8#include <cstdint>
9#include <map>
10#include <memory>
11#include <set>
12#include <string>
13#include <unordered_map>
14#include <vector>
15
16#include "ax_enums.h"
17#include "ax_export.h"
18#include "ax_node.h"
19#include "ax_node_data.h"
20#include "ax_tree_data.h"
21#include "ax_tree_update.h"
22#include "gfx/geometry/rect.h"
23
24namespace ui {
25
26class AXTableInfo;
27class AXTreeObserver;
28struct AXTreeUpdateState;
29
30// AXTree is a live, managed tree of AXNode objects that can receive
31// updates from another AXTreeSource via AXTreeUpdates, and it can be
32// used as a source for sending updates to another client tree.
33// It's designed to be subclassed to implement support for native
34// accessibility APIs on a specific platform.
36 public:
38 std::map<ax::mojom::IntAttribute, std::map<int32_t, std::set<int32_t>>>;
41 std::map<int32_t, std::set<int32_t>>>;
42
43 AXTree();
44 explicit AXTree(const AXTreeUpdate& initial_state);
45 virtual ~AXTree();
46
47 // AXTree owns pointers so copying is non-trivial.
48 AXTree(const AXTree&) = delete;
49 AXTree& operator=(const AXTree&) = delete;
50
51 void AddObserver(AXTreeObserver* observer);
52 bool HasObserver(AXTreeObserver* observer);
53 void RemoveObserver(AXTreeObserver* observer);
54
55 std::vector<AXTreeObserver*>& observers() { return observers_; }
56
57 AXNode* root() const { return root_; }
58
59 const AXTreeData& data() const { return data_; }
60
61 // Destroys the tree and notifies all observers.
62 void Destroy();
63
64 // AXNode::OwnerTree override.
65 // Returns the globally unique ID of this accessibility tree.
66 AXTreeID GetAXTreeID() const override;
67
68 // AXNode::OwnerTree override.
69 // Returns the AXNode with the given |id| if it is part of this AXTree.
70 AXNode* GetFromId(int32_t id) const override;
71
72 // Returns true on success. If it returns false, it's a fatal error
73 // and this tree should be destroyed, and the source of the tree update
74 // should not be trusted any longer.
75 virtual bool Unserialize(const AXTreeUpdate& update);
76
77 virtual void UpdateData(const AXTreeData& data);
78
79 // Convert any rectangle from the local coordinate space of one node in
80 // the tree, to bounds in the coordinate space of the tree.
81 // If set, updates |offscreen| boolean to be true if the node is offscreen
82 // relative to its rootWebArea. Callers should initialize |offscreen|
83 // to false: this method may get called multiple times in a row and
84 // |offscreen| will be propagated.
85 // If |clip_bounds| is true, result bounds will be clipped.
86 gfx::RectF RelativeToTreeBounds(const AXNode* node,
87 gfx::RectF node_bounds,
88 bool* offscreen = nullptr,
89 bool clip_bounds = true) const;
90
91 // Get the bounds of a node in the coordinate space of the tree.
92 // If set, updates |offscreen| boolean to be true if the node is offscreen
93 // relative to its rootWebArea. Callers should initialize |offscreen|
94 // to false: this method may get called multiple times in a row and
95 // |offscreen| will be propagated.
96 // If |clip_bounds| is true, result bounds will be clipped.
97 gfx::RectF GetTreeBounds(const AXNode* node,
98 bool* offscreen = nullptr,
99 bool clip_bounds = true) const;
100
101 // Given a node ID attribute (one where IsNodeIdIntAttribute is true),
102 // and a destination node ID, return a set of all source node IDs that
103 // have that relationship attribute between them and the destination.
104 std::set<int32_t> GetReverseRelations(ax::mojom::IntAttribute attr,
105 int32_t dst_id) const;
106
107 // Given a node ID list attribute (one where
108 // IsNodeIdIntListAttribute is true), and a destination node ID,
109 // return a set of all source node IDs that have that relationship
110 // attribute between them and the destination.
111 std::set<int32_t> GetReverseRelations(ax::mojom::IntListAttribute attr,
112 int32_t dst_id) const;
113
114 // Given a child tree ID, return the node IDs of all nodes in the tree who
115 // have a kChildTreeId int attribute with that value.
116 std::set<int32_t> GetNodeIdsForChildTreeId(AXTreeID child_tree_id) const;
117
118 // Get all of the child tree IDs referenced by any node in this tree.
119 const std::set<AXTreeID> GetAllChildTreeIds() const;
120
121 // Map from a relation attribute to a map from a target id to source ids.
123 return int_reverse_relations_;
124 }
126 return intlist_reverse_relations_;
127 }
128
129 // Return a multi-line indented string representation, for logging.
130 std::string ToString() const;
131
132 // A string describing the error from an unsuccessful Unserialize,
133 // for testing and debugging.
134 const std::string& error() const { return error_; }
135
136 int size() { return static_cast<int>(id_map_.size()); }
137
138 // Call this to enable support for extra Mac nodes - for each table,
139 // a table column header and a node for each column.
140 void SetEnableExtraMacNodes(bool enabled);
141 bool enable_extra_mac_nodes() const { return enable_extra_mac_nodes_; }
142
143 // Return a negative number that's suitable to use for a node ID for
144 // internal nodes created automatically by an AXTree, so as not to
145 // conflict with positive-numbered node IDs from tree sources.
146 int32_t GetNextNegativeInternalNodeId();
147
148 // Returns the PosInSet of |node|. Looks in node_set_size_pos_in_set_info_map_
149 // for cached value. Calls |ComputeSetSizePosInSetAndCache|if no value is
150 // present in the cache.
151 std::optional<int> GetPosInSet(const AXNode& node) override;
152 // Returns the SetSize of |node|. Looks in node_set_size_pos_in_set_info_map_
153 // for cached value. Calls |ComputeSetSizePosInSetAndCache|if no value is
154 // present in the cache.
155 std::optional<int> GetSetSize(const AXNode& node) override;
156
157 Selection GetUnignoredSelection() const override;
158
159 bool GetTreeUpdateInProgressState() const override;
160 void SetTreeUpdateInProgressState(bool set_tree_update_value);
161
162 // AXNode::OwnerTree override.
163 // Returns true if the tree represents a paginated document
164 bool HasPaginationSupport() const override;
165
166 // A list of intents active during a tree update/unserialization.
167 const std::vector<AXEventIntent>& event_intents() const {
168 return event_intents_;
169 }
170
171 private:
172 friend class AXTableInfoTest;
173
174 // AXNode::OwnerTree override.
175 //
176 // Given a node in this accessibility tree that corresponds to a table
177 // or grid, return an object containing information about the
178 // table structure. This object is computed lazily on-demand and
179 // cached until the next time the tree is updated. Clients should
180 // not retain this pointer, they should just request it every time
181 // it's needed.
182 //
183 // Returns nullptr if the node is not a valid table.
184 AXTableInfo* GetTableInfo(const AXNode* table_node) const override;
185
186 AXNode* CreateNode(AXNode* parent,
187 AXNode::AXID id,
188 size_t index_in_parent,
189 AXTreeUpdateState* update_state);
190
191 // Accumulates the work that will be required to update the AXTree.
192 // This allows us to notify observers of structure changes when the
193 // tree is still in a stable and unchanged state.
194 bool ComputePendingChanges(const AXTreeUpdate& update,
195 AXTreeUpdateState* update_state);
196
197 // Populates |update_state| with information about actions that will
198 // be performed on the tree during the update, such as adding or
199 // removing nodes in the tree. Returns true on success.
200 // Nothing within this call should modify tree structure or node data.
201 bool ComputePendingChangesToNode(const AXNodeData& new_data,
202 bool is_new_root,
203 AXTreeUpdateState* update_state);
204
205 // This is called from within Unserialize(), it returns true on success.
206 bool UpdateNode(const AXNodeData& src,
207 bool is_new_root,
208 AXTreeUpdateState* update_state);
209
210 // Notify the delegate that the subtree rooted at |node| will be
211 // destroyed or reparented.
212 void NotifySubtreeWillBeReparentedOrDeleted(
213 AXNode* node,
214 const AXTreeUpdateState* update_state);
215
216 // Notify the delegate that |node| will be destroyed or reparented.
217 void NotifyNodeWillBeReparentedOrDeleted(
218 AXNode* node,
219 const AXTreeUpdateState* update_state);
220
221 // Notify the delegate that |node| and all of its descendants will be
222 // destroyed. This function is called during AXTree teardown.
223 void RecursivelyNotifyNodeDeletedForTreeTeardown(AXNode* node);
224
225 // Notify the delegate that the node marked by |node_id| has been deleted.
226 // We are passing the node id instead of ax node is because by the time this
227 // function is called, the ax node in the tree will already have been
228 // destroyed.
229 void NotifyNodeHasBeenDeleted(AXNode::AXID node_id);
230
231 // Notify the delegate that |node| has been created or reparented.
232 void NotifyNodeHasBeenReparentedOrCreated(
233 AXNode* node,
234 const AXTreeUpdateState* update_state);
235
236 // Notify the delegate that a node will change its data.
237 void NotifyNodeDataWillChange(const AXNodeData& old_data,
238 const AXNodeData& new_data);
239
240 // Notify the delegate that |node| has changed its data.
241 void NotifyNodeDataHasBeenChanged(AXNode* node,
242 const AXNodeData& old_data,
243 const AXNodeData& new_data);
244
245 void UpdateReverseRelations(AXNode* node, const AXNodeData& new_data);
246
247 // Returns true if all pending changes in the |update_state| have been
248 // handled. If this returns false, the |error_| message will be populated.
249 // It's a fatal error to have pending changes after exhausting
250 // the AXTreeUpdate.
251 bool ValidatePendingChangesComplete(const AXTreeUpdateState& update_state);
252
253 // Modifies |update_state| so that it knows what subtree and nodes are
254 // going to be destroyed for the subtree rooted at |node|.
255 void MarkSubtreeForDestruction(AXNode::AXID node_id,
256 AXTreeUpdateState* update_state);
257
258 // Modifies |update_state| so that it knows what nodes are
259 // going to be destroyed for the subtree rooted at |node|.
260 void MarkNodesForDestructionRecursive(AXNode::AXID node_id,
261 AXTreeUpdateState* update_state);
262
263 // Validates that destroying the subtree rooted at |node| has required
264 // information in |update_state|, then calls DestroyNodeAndSubtree on it.
265 void DestroySubtree(AXNode* node, AXTreeUpdateState* update_state);
266
267 // Call Destroy() on |node|, and delete it from the id map, and then
268 // call recursively on all nodes in its subtree.
269 void DestroyNodeAndSubtree(AXNode* node, AXTreeUpdateState* update_state);
270
271 // Iterate over the children of |node| and for each child, destroy the
272 // child and its subtree if its id is not in |new_child_ids|.
273 void DeleteOldChildren(AXNode* node,
274 const std::vector<int32_t>& new_child_ids,
275 AXTreeUpdateState* update_state);
276
277 // Iterate over |new_child_ids| and populate |new_children| with
278 // pointers to child nodes, reusing existing nodes already in the tree
279 // if they exist, and creating otherwise. Reparenting is disallowed, so
280 // if the id already exists as the child of another node, that's an
281 // error. Returns true on success, false on fatal error.
282 bool CreateNewChildVector(AXNode* node,
283 const std::vector<int32_t>& new_child_ids,
284 std::vector<AXNode*>* new_children,
285 AXTreeUpdateState* update_state);
286
287 // Internal implementation of RelativeToTreeBounds. It calls itself
288 // recursively but ensures that it can only do so exactly once!
289 gfx::RectF RelativeToTreeBoundsInternal(const AXNode* node,
290 gfx::RectF node_bounds,
291 bool* offscreen,
292 bool clip_bounds,
293 bool allow_recursion) const;
294
295 std::vector<AXTreeObserver*> observers_;
296 AXNode* root_ = nullptr;
297 std::unordered_map<int32_t, AXNode*> id_map_;
298 std::string error_;
299 AXTreeData data_;
300
301 // Map from an int attribute (if IsNodeIdIntAttribute is true) to
302 // a reverse mapping from target nodes to source nodes.
303 IntReverseRelationMap int_reverse_relations_;
304 // Map from an int list attribute (if IsNodeIdIntListAttribute is true) to
305 // a reverse mapping from target nodes to source nodes.
306 IntListReverseRelationMap intlist_reverse_relations_;
307 // Map from child tree ID to the set of node IDs that contain that attribute.
308 std::map<AXTreeID, std::set<int32_t>> child_tree_id_reverse_map_;
309
310 // Map from node ID to cached table info, if the given node is a table.
311 // Invalidated every time the tree is updated.
312 mutable std::unordered_map<int32_t, std::unique_ptr<AXTableInfo>>
313 table_info_map_;
314
315 // The next negative node ID to use for internal nodes.
316 int32_t next_negative_internal_node_id_ = -1;
317
318 // Whether we should create extra nodes that
319 // are only useful on macOS. Implemented using this flag to allow
320 // this code to be unit-tested on other platforms (for example, more
321 // code sanitizers run on Linux).
322 bool enable_extra_mac_nodes_ = false;
323
324 // Contains pos_in_set and set_size data for an AXNode.
325 struct NodeSetSizePosInSetInfo {
326 NodeSetSizePosInSetInfo();
327 ~NodeSetSizePosInSetInfo();
328
329 std::optional<int> pos_in_set;
330 std::optional<int> set_size;
331 std::optional<int> lowest_hierarchical_level;
332 };
333
334 // Represents the content of an ordered set which includes the ordered set
335 // items and the ordered set container if it exists.
336 struct OrderedSetContent;
337
338 // Maps a particular hierarchical level to a list of OrderedSetContents.
339 // Represents all ordered set items/container on a particular hierarchical
340 // level.
341 struct OrderedSetItemsMap;
342
343 // Populates |items_map_to_be_populated| with all items associated with
344 // |original_node| and within |ordered_set|. Only items whose roles match the
345 // role of the |ordered_set| will be added.
346 void PopulateOrderedSetItemsMap(
347 const AXNode& original_node,
348 const AXNode* ordered_set,
349 OrderedSetItemsMap* items_map_to_be_populated) const;
350
351 // Helper function for recursively populating ordered sets items map with
352 // all items associated with |original_node| and |ordered_set|. |local_parent|
353 // tracks the recursively passed in child nodes of |ordered_set|.
354 void RecursivelyPopulateOrderedSetItemsMap(
355 const AXNode& original_node,
356 const AXNode* ordered_set,
357 const AXNode* local_parent,
358 std::optional<int> ordered_set_min_level,
359 std::optional<int> prev_level,
360 OrderedSetItemsMap* items_map_to_be_populated) const;
361
362 // Computes the pos_in_set and set_size values of all items in ordered_set and
363 // caches those values. Called by GetPosInSet and GetSetSize.
364 void ComputeSetSizePosInSetAndCache(const AXNode& node,
365 const AXNode* ordered_set);
366
367 // Helper for ComputeSetSizePosInSetAndCache. Computes and caches the
368 // pos_in_set and set_size values for a given OrderedSetContent.
369 void ComputeSetSizePosInSetAndCacheHelper(
370 const OrderedSetContent& ordered_set_content);
371
372 // Map from node ID to OrderedSetInfo.
373 // Item-like and ordered-set-like objects will map to populated OrderedSetInfo
374 // objects.
375 // All other objects will map to default-constructed OrderedSetInfo objects.
376 // Invalidated every time the tree is updated.
377 mutable std::unordered_map<int32_t, NodeSetSizePosInSetInfo>
378 node_set_size_pos_in_set_info_map_;
379
380 // Indicates if the tree is updating.
381 bool tree_update_in_progress_ = false;
382
383 // Indicates if the tree represents a paginated document
384 bool has_pagination_support_ = false;
385
386 std::vector<AXEventIntent> event_intents_;
387};
388
389} // namespace ui
390
391#endif // UI_ACCESSIBILITY_AX_TREE_H_
#define AX_EXPORT
Definition: ax_export.h:29
int32_t AXID
Definition: ax_node.h:36
const std::string & error() const
Definition: ax_tree.h:134
const AXTreeData & data() const
Definition: ax_tree.h:59
bool enable_extra_mac_nodes() const
Definition: ax_tree.h:141
const IntReverseRelationMap & int_reverse_relations()
Definition: ax_tree.h:122
std::map< ax::mojom::IntListAttribute, std::map< int32_t, std::set< int32_t > > > IntListReverseRelationMap
Definition: ax_tree.h:41
int size()
Definition: ax_tree.h:136
std::map< ax::mojom::IntAttribute, std::map< int32_t, std::set< int32_t > > > IntReverseRelationMap
Definition: ax_tree.h:38
AXNode * root() const
Definition: ax_tree.h:57
AXTree & operator=(const AXTree &)=delete
const IntListReverseRelationMap & intlist_reverse_relations()
Definition: ax_tree.h:125
std::vector< AXTreeObserver * > & observers()
Definition: ax_tree.h:55
const std::vector< AXEventIntent > & event_intents() const
Definition: ax_tree.h:167
AXTree(const AXTree &)=delete
IntListAttribute
Definition: ax_enums.h:799
SI auto map(std::index_sequence< I... >, Fn &&fn, const Args &... args) -> skvx::Vec< sizeof...(I), decltype(fn(args[0]...))>
Definition: SkVx.h:680
const char * ToString(ax::mojom::Event event)
Definition: ax_enum_util.cc:9
Definition: update.py:1
std::shared_ptr< const fml::Mapping > data
Definition: texture_gles.cc:63