blob: 23c152da9195f16381c0c8638571e4d85a1e9ec0 [file] [log] [blame]
[email protected]4b02bbca2013-11-22 08:59:031// 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
avi9c81217b2015-12-24 23:40:058#include <stdint.h>
9
Chris Hall34208182019-03-13 02:26:1810#include <memory>
[email protected]d4e273462013-12-04 04:37:5811#include <set>
Takuto Ikutaadf31eb2019-01-05 00:32:4812#include <unordered_map>
[email protected]4b02bbca2013-11-22 08:59:0313
Dominic Mazzoni8549eb682018-12-11 23:48:3214#include "base/observer_list.h"
James Cook36cab7c2019-10-29 23:26:4015#include "ui/accessibility/ax_enums.mojom-forward.h"
[email protected]4b02bbca2013-11-22 08:59:0316#include "ui/accessibility/ax_export.h"
Dominic Mazzoniecfb4fd2018-10-23 07:34:2017#include "ui/accessibility/ax_node.h"
dmazzoni329fd012015-10-22 20:05:3518#include "ui/accessibility/ax_node_data.h"
19#include "ui/accessibility/ax_tree_data.h"
[email protected]4b02bbca2013-11-22 08:59:0320#include "ui/accessibility/ax_tree_update.h"
21
22namespace ui {
23
Dominic Mazzoni3d9b5b92018-04-18 21:36:3824class AXTableInfo;
dmazzoni09e75912015-06-02 23:31:5625class AXTree;
Dominic Mazzoni8549eb682018-12-11 23:48:3226class AXTreeObserver;
[email protected]e736e81b2014-02-24 07:15:5827struct AXTreeUpdateState;
Chris Hall697d99b2019-07-09 02:36:1128class AXLanguageDetectionManager;
[email protected]e736e81b2014-02-24 07:15:5829
[email protected]4b02bbca2013-11-22 08:59:0330// 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.
Dominic Mazzoniecfb4fd2018-10-23 07:34:2035class AX_EXPORT AXTree : public AXNode::OwnerTree {
[email protected]4b02bbca2013-11-22 08:59:0336 public:
David Tsengef6b480d2018-02-19 12:48:4237 typedef std::map<ax::mojom::IntAttribute,
38 std::map<int32_t, std::set<int32_t>>>
39 IntReverseRelationMap;
40 typedef std::map<ax::mojom::IntListAttribute,
41 std::map<int32_t, std::set<int32_t>>>
42 IntListReverseRelationMap;
43
[email protected]4b02bbca2013-11-22 08:59:0344 AXTree();
dmazzoni329fd012015-10-22 20:05:3545 explicit AXTree(const AXTreeUpdate& initial_state);
[email protected]4b02bbca2013-11-22 08:59:0346 virtual ~AXTree();
47
Dominic Mazzoni8549eb682018-12-11 23:48:3248 void AddObserver(AXTreeObserver* observer);
49 bool HasObserver(AXTreeObserver* observer);
50 void RemoveObserver(const AXTreeObserver* observer);
51
52 base::ObserverList<AXTreeObserver>& observers() { return observers_; }
[email protected]e736e81b2014-02-24 07:15:5853
tfarina6b1c1e082015-02-20 23:47:0754 AXNode* root() const { return root_; }
55
dmazzoni329fd012015-10-22 20:05:3556 const AXTreeData& data() const { return data_; }
57
Dominic Mazzoniecfb4fd2018-10-23 07:34:2058 // AXNode::OwnerTree override.
Adam Ettenberger86af2532019-09-17 20:04:4659 // Returns the globally unique ID of this accessibility tree.
60 AXTreeID GetAXTreeID() const override;
61
62 // AXNode::OwnerTree override.
tfarina6b1c1e082015-02-20 23:47:0763 // Returns the AXNode with the given |id| if it is part of this AXTree.
Dominic Mazzoniecfb4fd2018-10-23 07:34:2064 AXNode* GetFromId(int32_t id) const override;
[email protected]4b02bbca2013-11-22 08:59:0365
[email protected]d4e273462013-12-04 04:37:5866 // Returns true on success. If it returns false, it's a fatal error
67 // and this tree should be destroyed, and the source of the tree update
68 // should not be trusted any longer.
dmazzoni329fd012015-10-22 20:05:3569 virtual bool Unserialize(const AXTreeUpdate& update);
70
71 virtual void UpdateData(const AXTreeData& data);
[email protected]4b02bbca2013-11-22 08:59:0372
Dominic Mazzoni2410fc62017-06-09 22:19:1873 // Convert any rectangle from the local coordinate space of one node in
74 // the tree, to bounds in the coordinate space of the tree.
Katie Dektar2c6052d2017-09-27 00:32:3275 // If set, updates |offscreen| boolean to be true if the node is offscreen
76 // relative to its rootWebArea. Callers should initialize |offscreen|
77 // to false: this method may get called multiple times in a row and
78 // |offscreen| will be propagated.
Katie Dektardb71ad942017-11-29 20:07:4879 // If |clip_bounds| is true, result bounds will be clipped.
Dominic Mazzoni2410fc62017-06-09 22:19:1880 gfx::RectF RelativeToTreeBounds(const AXNode* node,
Katie Dektar2c6052d2017-09-27 00:32:3281 gfx::RectF node_bounds,
Katie Dektardb71ad942017-11-29 20:07:4882 bool* offscreen = nullptr,
83 bool clip_bounds = true) const;
Dominic Mazzoni2410fc62017-06-09 22:19:1884
85 // Get the bounds of a node in the coordinate space of the tree.
Katie Dektar2c6052d2017-09-27 00:32:3286 // If set, updates |offscreen| boolean to be true if the node is offscreen
87 // relative to its rootWebArea. Callers should initialize |offscreen|
88 // to false: this method may get called multiple times in a row and
89 // |offscreen| will be propagated.
Katie Dektardb71ad942017-11-29 20:07:4890 // If |clip_bounds| is true, result bounds will be clipped.
91 gfx::RectF GetTreeBounds(const AXNode* node,
92 bool* offscreen = nullptr,
93 bool clip_bounds = true) const;
Dominic Mazzoni2410fc62017-06-09 22:19:1894
Dominic Mazzoni35f2a5252017-09-26 00:56:0495 // Given a node ID attribute (one where IsNodeIdIntAttribute is true),
96 // and a destination node ID, return a set of all source node IDs that
97 // have that relationship attribute between them and the destination.
Dominic Mazzonidcef1b732018-01-26 17:57:0498 std::set<int32_t> GetReverseRelations(ax::mojom::IntAttribute attr,
Dominic Mazzoni94a4da62017-12-22 22:49:3899 int32_t dst_id) const;
Dominic Mazzoni35f2a5252017-09-26 00:56:04100
101 // Given a node ID list attribute (one where
102 // IsNodeIdIntListAttribute is true), and a destination node ID,
103 // return a set of all source node IDs that have that relationship
104 // attribute between them and the destination.
Dominic Mazzonidcef1b732018-01-26 17:57:04105 std::set<int32_t> GetReverseRelations(ax::mojom::IntListAttribute attr,
Dominic Mazzoni94a4da62017-12-22 22:49:38106 int32_t dst_id) const;
Dominic Mazzoni35f2a5252017-09-26 00:56:04107
Dominic Mazzoniaa774822018-08-29 20:33:58108 // Given a child tree ID, return the node IDs of all nodes in the tree who
109 // have a kChildTreeId int attribute with that value.
Dominic Mazzoni336bc0062018-09-23 16:46:43110 std::set<int32_t> GetNodeIdsForChildTreeId(AXTreeID child_tree_id) const;
Dominic Mazzoniaa774822018-08-29 20:33:58111
Dominic Mazzoni748888c2018-11-01 22:34:59112 // Get all of the child tree IDs referenced by any node in this tree.
113 const std::set<AXTreeID> GetAllChildTreeIds() const;
114
David Tsengef6b480d2018-02-19 12:48:42115 // Map from a relation attribute to a map from a target id to source ids.
116 const IntReverseRelationMap& int_reverse_relations() {
117 return int_reverse_relations_;
118 }
119 const IntListReverseRelationMap& intlist_reverse_relations() {
120 return intlist_reverse_relations_;
121 }
Dominic Mazzoni3d9b5b92018-04-18 21:36:38122
[email protected]5eec2f52014-01-06 22:30:54123 // Return a multi-line indented string representation, for logging.
124 std::string ToString() const;
125
[email protected]d4e273462013-12-04 04:37:58126 // A string describing the error from an unsuccessful Unserialize,
127 // for testing and debugging.
tfarinad0bfb4b62015-02-18 17:20:32128 const std::string& error() const { return error_; }
[email protected]d4e273462013-12-04 04:37:58129
dmazzoniee2eaca2015-03-18 18:13:07130 int size() { return static_cast<int>(id_map_.size()); }
131
Dominic Mazzonid42e00a2018-06-27 23:14:23132 // Call this to enable support for extra Mac nodes - for each table,
133 // a table column header and a node for each column.
134 void SetEnableExtraMacNodes(bool enabled);
135 bool enable_extra_mac_nodes() const { return enable_extra_mac_nodes_; }
136
137 // Return a negative number that's suitable to use for a node ID for
138 // internal nodes created automatically by an AXTree, so as not to
139 // conflict with positive-numbered node IDs from tree sources.
140 int32_t GetNextNegativeInternalNodeId();
141
Akihiro Ota886a96d62018-12-18 00:11:48142 // Returns the pos_in_set of node. Looks in ordered_set_info_map_ for cached
143 // value. Calculates pos_in_set and set_size for node (and all other nodes in
Akihiro Ota413ca722018-12-03 23:29:00144 // the same ordered set) if no value is present in the cache.
145 // This function is guaranteed to be only called on nodes that can hold
146 // pos_in_set values, minimizing the size of the cache.
Akihiro Ota886a96d62018-12-18 00:11:48147 int32_t GetPosInSet(const AXNode& node, const AXNode* ordered_set) override;
Akihiro Ota413ca722018-12-03 23:29:00148 // Returns the set_size of node. Looks in ordered_set_info_map_ for cached
149 // value. Calculates pos_inset_set and set_size for node (and all other nodes
150 // in the same ordered set) if no value is present in the cache.
151 // This function is guaranteed to be only called on nodes that can hold
152 // set_size values, minimizing the size of the cache.
Akihiro Ota886a96d62018-12-18 00:11:48153 int32_t GetSetSize(const AXNode& node, const AXNode* ordered_set) override;
Akihiro Ota413ca722018-12-03 23:29:00154
Jacques Newman339afc62019-08-14 00:49:22155 Selection GetUnignoredSelection() const override;
156
Akihiro Otae3e420e2019-04-17 19:57:40157 bool GetTreeUpdateInProgressState() const override;
158 void SetTreeUpdateInProgressState(bool set_tree_update_value);
159
Kurt Catti-Schmidtc8445a12019-08-07 18:52:58160 // AXNode::OwnerTree override.
161 // Returns true if the tree represents a paginated document
162 bool HasPaginationSupport() const override;
163
Chris Hall697d99b2019-07-09 02:36:11164 // Language detection manager, entry point to language detection features.
165 // TODO(chrishall): Should this be stored by pointer or value?
166 // When should we initialize this?
167 std::unique_ptr<AXLanguageDetectionManager> language_detection_manager;
Chris Hall34208182019-03-13 02:26:18168
[email protected]e736e81b2014-02-24 07:15:58169 private:
Dominic Mazzoniecfb4fd2018-10-23 07:34:20170 friend class AXTableInfoTest;
171
172 // AXNode::OwnerTree override.
173 //
174 // Given a node in this accessibility tree that corresponds to a table
175 // or grid, return an object containing information about the
176 // table structure. This object is computed lazily on-demand and
177 // cached until the next time the tree is updated. Clients should
178 // not retain this pointer, they should just request it every time
179 // it's needed.
180 //
181 // Returns nullptr if the node is not a valid table.
182 AXTableInfo* GetTableInfo(const AXNode* table_node) const override;
183
dtseng5a7b3d92016-09-08 06:35:58184 AXNode* CreateNode(AXNode* parent,
Adam Ettenbergerd9d8d58a2019-08-06 16:54:08185 AXNode::AXID id,
Peter Kasting94a07a12019-05-22 19:26:28186 size_t index_in_parent,
dtseng5a7b3d92016-09-08 06:35:58187 AXTreeUpdateState* update_state);
[email protected]4b02bbca2013-11-22 08:59:03188
Adam Ettenbergerd9d8d58a2019-08-06 16:54:08189 // Accumulates the work that will be required to update the AXTree.
190 // This allows us to notify observers of structure changes when the
191 // tree is still in a stable and unchanged state.
192 bool ComputePendingChanges(const AXTreeUpdate& update,
193 AXTreeUpdateState& update_state);
194
195 // Populates |update_state| with information about actions that will
196 // be performed on the tree during the update, such as adding or
197 // removing nodes in the tree. Returns true on success.
198 // Nothing within this call should modify tree structure or node data.
199 bool ComputePendingChangesToNode(const AXNodeData& new_data,
200 bool is_new_root,
201 AXTreeUpdateState* update_state);
202
[email protected]4b02bbca2013-11-22 08:59:03203 // This is called from within Unserialize(), it returns true on success.
dmazzoni67b4db22016-04-23 00:40:04204 bool UpdateNode(const AXNodeData& src,
205 bool is_new_root,
206 AXTreeUpdateState* update_state);
[email protected]4b02bbca2013-11-22 08:59:03207
Adam Ettenbergerd9d8d58a2019-08-06 16:54:08208 // Notify the delegate that the subtree rooted at |node| will be
209 // destroyed or reparented.
210 void NotifySubtreeWillBeReparentedOrDeleted(
211 AXNode* node,
212 const AXTreeUpdateState* update_state);
213
214 // Notify the delegate that |node| will be destroyed or reparented.
215 void NotifyNodeWillBeReparentedOrDeleted(
216 AXNode* node,
217 const AXTreeUpdateState* update_state);
218
219 // Notify the delegate that |node| and all of its descendants will be
Victor Feie3cce4c2019-11-14 18:35:41220 // destroyed. This function is called during AXTree teardown.
221 void RecursivelyNotifyNodeDeletedForTreeTeardown(AXNode* node);
222
223 // Notify the delegate that the node marked by |node_id| has been deleted.
224 // We are passing the node id instead of ax node is because by the time this
225 // function is called, the ax node in the tree will already have been
Adam Ettenbergerd9d8d58a2019-08-06 16:54:08226 // destroyed.
Victor Feie3cce4c2019-11-14 18:35:41227 void NotifyNodeHasBeenDeleted(AXNode::AXID node_id);
Adam Ettenbergerd9d8d58a2019-08-06 16:54:08228
229 // Notify the delegate that |node| has been created or reparented.
230 void NotifyNodeHasBeenReparentedOrCreated(
231 AXNode* node,
232 const AXTreeUpdateState* update_state);
233
Adam Ettenberger05afcec2019-08-06 17:11:29234 // Notify the delegate that a node will change its data.
235 void NotifyNodeDataWillChange(const AXNodeData& old_data,
236 const AXNodeData& new_data);
237
238 // Notify the delegate that |node| has changed its data.
239 void NotifyNodeDataHasBeenChanged(AXNode* node,
240 const AXNodeData& old_data,
241 const AXNodeData& new_data);
dmazzoni3ab5385c2017-03-13 18:07:03242
Dominic Mazzoni35f2a5252017-09-26 00:56:04243 void UpdateReverseRelations(AXNode* node, const AXNodeData& new_data);
244
Adam Ettenbergerd9d8d58a2019-08-06 16:54:08245 // Returns true if all pending changes in the |update_state| have been
246 // handled. If this returns false, the |error_| message will be populated.
247 // It's a fatal error to have pending changes after exhausting
248 // the AXTreeUpdate.
249 bool ValidatePendingChangesComplete(const AXTreeUpdateState& update_state);
[email protected]4b02bbca2013-11-22 08:59:03250
Adam Ettenbergerd9d8d58a2019-08-06 16:54:08251 // Modifies |update_state| so that it knows what subtree and nodes are
252 // going to be destroyed for the subtree rooted at |node|.
253 void MarkSubtreeForDestruction(AXNode::AXID node_id,
254 AXTreeUpdateState* update_state);
255
256 // Modifies |update_state| so that it knows what nodes are
257 // going to be destroyed for the subtree rooted at |node|.
258 void MarkNodesForDestructionRecursive(AXNode::AXID node_id,
259 AXTreeUpdateState* update_state);
260
261 // Validates that destroying the subtree rooted at |node| has required
262 // information in |update_state|, then calls DestroyNodeAndSubtree on it.
dmazzonie3b7faf2015-06-01 17:56:36263 void DestroySubtree(AXNode* node, AXTreeUpdateState* update_state);
dmazzonia4b48912015-01-24 00:08:56264
[email protected]4b02bbca2013-11-22 08:59:03265 // Call Destroy() on |node|, and delete it from the id map, and then
266 // call recursively on all nodes in its subtree.
dmazzonie3b7faf2015-06-01 17:56:36267 void DestroyNodeAndSubtree(AXNode* node, AXTreeUpdateState* update_state);
[email protected]4b02bbca2013-11-22 08:59:03268
269 // Iterate over the children of |node| and for each child, destroy the
Adam Ettenbergerd9d8d58a2019-08-06 16:54:08270 // child and its subtree if its id is not in |new_child_ids|.
271 void DeleteOldChildren(AXNode* node,
avi9c81217b2015-12-24 23:40:05272 const std::vector<int32_t>& new_child_ids,
dmazzonie3b7faf2015-06-01 17:56:36273 AXTreeUpdateState* update_state);
[email protected]4b02bbca2013-11-22 08:59:03274
275 // Iterate over |new_child_ids| and populate |new_children| with
276 // pointers to child nodes, reusing existing nodes already in the tree
277 // if they exist, and creating otherwise. Reparenting is disallowed, so
278 // if the id already exists as the child of another node, that's an
[email protected]e736e81b2014-02-24 07:15:58279 // error. Returns true on success, false on fatal error.
[email protected]4b02bbca2013-11-22 08:59:03280 bool CreateNewChildVector(AXNode* node,
avi9c81217b2015-12-24 23:40:05281 const std::vector<int32_t>& new_child_ids,
[email protected]d4e273462013-12-04 04:37:58282 std::vector<AXNode*>* new_children,
[email protected]e736e81b2014-02-24 07:15:58283 AXTreeUpdateState* update_state);
[email protected]4b02bbca2013-11-22 08:59:03284
Dominic Mazzonia1bb0d122019-09-26 20:19:59285 // Internal implementation of RelativeToTreeBounds. It calls itself
286 // recursively but ensures that it can only do so exactly once!
287 gfx::RectF RelativeToTreeBoundsInternal(const AXNode* node,
288 gfx::RectF node_bounds,
289 bool* offscreen,
290 bool clip_bounds,
291 bool allow_recursion) const;
292
Dominic Mazzoni8549eb682018-12-11 23:48:32293 base::ObserverList<AXTreeObserver> observers_;
Brett Wilson0feae3a2017-12-06 03:16:56294 AXNode* root_ = nullptr;
Takuto Ikutaadf31eb2019-01-05 00:32:48295 std::unordered_map<int32_t, AXNode*> id_map_;
[email protected]d4e273462013-12-04 04:37:58296 std::string error_;
dmazzoni329fd012015-10-22 20:05:35297 AXTreeData data_;
Dominic Mazzoni35f2a5252017-09-26 00:56:04298
299 // Map from an int attribute (if IsNodeIdIntAttribute is true) to
300 // a reverse mapping from target nodes to source nodes.
David Tsengef6b480d2018-02-19 12:48:42301 IntReverseRelationMap int_reverse_relations_;
Dominic Mazzoni35f2a5252017-09-26 00:56:04302 // Map from an int list attribute (if IsNodeIdIntListAttribute is true) to
303 // a reverse mapping from target nodes to source nodes.
David Tsengef6b480d2018-02-19 12:48:42304 IntListReverseRelationMap intlist_reverse_relations_;
Dominic Mazzoniaa774822018-08-29 20:33:58305 // Map from child tree ID to the set of node IDs that contain that attribute.
Dominic Mazzoni336bc0062018-09-23 16:46:43306 std::map<AXTreeID, std::set<int32_t>> child_tree_id_reverse_map_;
Dominic Mazzoni3d9b5b92018-04-18 21:36:38307
308 // Map from node ID to cached table info, if the given node is a table.
Dominic Mazzonid42e00a2018-06-27 23:14:23309 // Invalidated every time the tree is updated.
Takuto Ikutaadf31eb2019-01-05 00:32:48310 mutable std::unordered_map<int32_t, AXTableInfo*> table_info_map_;
Dominic Mazzonid42e00a2018-06-27 23:14:23311
312 // The next negative node ID to use for internal nodes.
313 int32_t next_negative_internal_node_id_ = -1;
314
315 // Whether we should create extra nodes that
316 // are only useful on macOS. Implemented using this flag to allow
317 // this code to be unit-tested on other platforms (for example, more
318 // code sanitizers run on Linux).
319 bool enable_extra_mac_nodes_ = false;
Akihiro Ota413ca722018-12-03 23:29:00320
321 // Contains pos_in_set and set_size data for an AXNode.
322 struct OrderedSetInfo {
323 int32_t pos_in_set;
324 int32_t set_size;
Alice Boxhallc8ffa6c2019-04-09 02:39:44325 int32_t lowest_hierarchical_level;
Akihiro Ota413ca722018-12-03 23:29:00326 OrderedSetInfo() : pos_in_set(0), set_size(0) {}
327 ~OrderedSetInfo() {}
328 };
329
Victor Feid95130c2020-02-03 21:42:54330 // Populates ordered set items vector with all items associated with
331 // |original_node| and within |ordered_set|. Only items whose roles match the
332 // role of the |ordered_set| will be added.
333 void PopulateOrderedSetItems(
334 const AXNode& original_node,
335 const AXNode* ordered_set,
336 std::vector<const AXNode*>& items_to_be_populated) const;
337
338 // Helper function for recursively populating ordered sets items vector with
339 // all items associated with |original_node| and |ordered_set|. |local_parent|
340 // tracks the recursively passed in child nodes of |ordered_set|.
341 void RecursivelyPopulateOrderedSetItems(
342 const AXNode& original_node,
343 const AXNode* ordered_set,
344 const AXNode* local_parent,
345 int32_t original_node_min_level,
346 std::vector<const AXNode*>& items_to_be_populated) const;
Akihiro Ota886a96d62018-12-18 00:11:48347
Akihiro Ota413ca722018-12-03 23:29:00348 // Helper for GetPosInSet and GetSetSize. Computes the pos_in_set and set_size
349 // values of all items in ordered_set and caches those values.
Akihiro Ota886a96d62018-12-18 00:11:48350 void ComputeSetSizePosInSetAndCache(const AXNode& node,
351 const AXNode* ordered_set);
Akihiro Ota413ca722018-12-03 23:29:00352
Akihiro Otab6a8a4d2018-12-04 01:56:39353 // Map from node ID to OrderedSetInfo.
354 // Item-like and ordered-set-like objects will map to populated OrderedSetInfo
355 // objects.
356 // All other objects will map to default-constructed OrderedSetInfo objects.
Akihiro Ota413ca722018-12-03 23:29:00357 // Invalidated every time the tree is updated.
358 mutable std::unordered_map<int32_t, OrderedSetInfo> ordered_set_info_map_;
Chris Hall9b34c2c2018-12-04 01:45:56359
360 // AXTree owns pointers so copying is non-trivial.
361 DISALLOW_COPY_AND_ASSIGN(AXTree);
Akihiro Otae3e420e2019-04-17 19:57:40362
363 // Indicates if the tree is updating.
364 bool tree_update_in_progress_ = false;
Kurt Catti-Schmidtc8445a12019-08-07 18:52:58365
366 // Indicates if the tree represents a paginated document
367 bool has_pagination_support_ = false;
[email protected]4b02bbca2013-11-22 08:59:03368};
369
370} // namespace ui
371
372#endif // UI_ACCESSIBILITY_AX_TREE_H_