blob: cde55e63f601d23a2a642d3f7d87978eabdf44c4 [file] [log] [blame]
Avi Drissman3e1a26c2022-09-15 20:26:031// Copyright 2013 The Chromium Authors
[email protected]4b02bbca2013-11-22 08:59:032// 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
Lei Zhanga06144782020-03-13 09:28:4710#include <map>
Chris Hall34208182019-03-13 02:26:1811#include <memory>
Arthur Sonzogni3eb9fd512024-02-09 12:20:4312#include <optional>
[email protected]d4e273462013-12-04 04:37:5813#include <set>
Lei Zhanga06144782020-03-13 09:28:4714#include <string>
Bruce Dawson9d565ec2022-10-31 17:42:3415#include <unordered_map>
Lei Zhanga06144782020-03-13 09:28:4716#include <vector>
[email protected]4b02bbca2013-11-22 08:59:0317
Aaron leventhaleab7a132025-05-01 13:28:1118#include "base/dcheck_is_on.h"
Aaron Leventhalbc649ff2022-08-11 18:53:2319#include "base/debug/crash_logging.h"
Keishi Hattori0e45c022021-11-27 09:25:5220#include "base/memory/raw_ptr.h"
Dominic Mazzoni8549eb682018-12-11 23:48:3221#include "base/observer_list.h"
Aaron Leventhal25ccd512024-12-04 00:57:4822#include "ui/accessibility/ax_common.h"
James Cook36cab7c2019-10-29 23:26:4023#include "ui/accessibility/ax_enums.mojom-forward.h"
[email protected]4b02bbca2013-11-22 08:59:0324#include "ui/accessibility/ax_export.h"
dmazzoni329fd012015-10-22 20:05:3525#include "ui/accessibility/ax_tree_data.h"
[email protected]4b02bbca2013-11-22 08:59:0326#include "ui/accessibility/ax_tree_update.h"
27
28namespace ui {
29
David Tseng41f13cbd2021-11-06 18:39:0330struct AXEvent;
Alexander Surkov4ab64cf2022-09-01 20:07:4631class AXLanguageDetectionManager;
32class AXNode;
33struct AXNodeData;
Dominic Mazzoni3d9b5b92018-04-18 21:36:3834class AXTableInfo;
Dominic Mazzoni8549eb682018-12-11 23:48:3235class AXTreeObserver;
[email protected]e736e81b2014-02-24 07:15:5836struct AXTreeUpdateState;
Alexander Surkov253235e2022-08-23 01:52:1237class AXSelection;
[email protected]e736e81b2014-02-24 07:15:5838
Jacques Newman5846e622021-01-15 02:15:5939// These values are persisted to logs. Entries should not be renumbered and
40// numeric values should never be reused.
Mark Schillaci99be8c92024-08-16 21:24:3341//
42// LINT.IfChange(AXTreeUnserializeError)
Jacques Newman5846e622021-01-15 02:15:5943enum class AXTreeUnserializeError {
44 // Tree has no root.
45 kNoRoot = 0,
46 // Node will not be in the tree and is not the new root.
47 kNotInTree = 1,
48 // Node is already pending for creation, cannot be the new root
49 kCreationPending = 2,
50 // Node has duplicate child.
51 kDuplicateChild = 3,
52 // Node is already pending for creation, cannot be a new child.
53 kCreationPendingForChild = 4,
54 // Node is not marked for destruction, would be reparented.
55 kReparent = 5,
56 // Nodes are left pending by the update.
57 kPendingNodes = 6,
58 // Changes left pending by the update;
59 kPendingChanges = 7,
60 // This must always be the last enum. It's okay for its value to
61 // increase, but none of the other enum values may change.
62 kMaxValue = kPendingChanges
63};
Mark Schillaci99be8c92024-08-16 21:24:3364// LINT.ThenChange(/tools/metrics/histograms/metadata/accessibility/enums.xml:AccessibilityTreeUnserializeError)
Jacques Newman5846e622021-01-15 02:15:5965
Evelynn Kaplan6cd535ce2025-03-20 23:58:1866#if BUILDFLAG(IS_LINUX)
67// To support AriaNotify on older versions of ATK, we need to use the ATK
68// signal "Text::text-insert". This signal requires a node that is a
69// text type, and it needs to have aria-live properties set in order for
70// Orca to make announcements. We create 2 extra "dummy" nodes that can be
71// used for firing these signals when there is an AriaNotify event. One node
72// will have `aria-live: assertive` and the other will have `aria-live:
73// polite`.
74class ExtraAnnouncementNodes {
75 public:
76 explicit ExtraAnnouncementNodes(AXNode* root);
77 ~ExtraAnnouncementNodes();
78
79 AXNode& AssertiveNode() const { return *assertive_node_; }
80 AXNode& PoliteNode() const { return *polite_node_; }
81 int Count() const {
82 return (assertive_node_ ? 1 : 0) + (polite_node_ ? 1 : 0);
83 }
84
85 static constexpr int kHighPriorityIndex = 0;
86 static constexpr int kNormalPriorityIndex = 1;
87
88 private:
89 std::unique_ptr<AXNode> CreateNode(const std::string& live_status,
90 AXNode* root);
91
92 std::unique_ptr<AXNode> assertive_node_;
93 std::unique_ptr<AXNode> polite_node_;
94};
95#endif // BUILDFLAG(IS_LINUX)
96
[email protected]4b02bbca2013-11-22 08:59:0397// AXTree is a live, managed tree of AXNode objects that can receive
98// updates from another AXTreeSource via AXTreeUpdates, and it can be
99// used as a source for sending updates to another client tree.
100// It's designed to be subclassed to implement support for native
101// accessibility APIs on a specific platform.
Alexander Surkov4ab64cf2022-09-01 20:07:46102class AX_EXPORT AXTree {
[email protected]4b02bbca2013-11-22 08:59:03103 public:
Lei Zhanga06144782020-03-13 09:28:47104 using IntReverseRelationMap =
Nektarios Paisios527d33fb52021-02-23 19:23:28105 std::map<ax::mojom::IntAttribute, std::map<AXNodeID, std::set<AXNodeID>>>;
Lei Zhanga06144782020-03-13 09:28:47106 using IntListReverseRelationMap =
107 std::map<ax::mojom::IntListAttribute,
Nektarios Paisios527d33fb52021-02-23 19:23:28108 std::map<AXNodeID, std::set<AXNodeID>>>;
David Tsengef6b480d2018-02-19 12:48:42109
Nektarios Paisios77c422a2021-10-19 10:37:00110 // If called, the focused node in this tree will never be ignored, even if it
111 // has the ignored state set. For now, this boolean will be set to false for
112 // all trees except in test scenarios, in order to thoroughly test the
113 // relevant code without causing any potential regressions. Ultimately, we
114 // want to expose all focused nodes so that a user of an assistive technology
115 // will be able to interact with the application / website, even if there is
116 // an authoring error, e.g. the aria-hidden attribute has been applied to the
117 // focused element.
118 // TODO(nektar): Removed once the feature has been fully tested.
119 static void SetFocusedNodeShouldNeverBeIgnored();
120
121 // Determines the ignored state of a node, given information about the node
122 // and the tree.
123 static bool ComputeNodeIsIgnored(const AXTreeData* optional_tree_data,
124 const AXNodeData& node_data);
125
126 // Determines whether a node has flipped its ignored state, given information
127 // about the previous and current state of the node / tree.
128 static bool ComputeNodeIsIgnoredChanged(
129 const AXTreeData* optional_old_tree_data,
130 const AXNodeData& old_node_data,
131 const AXTreeData* optional_new_tree_data,
132 const AXNodeData& new_node_data);
133
[email protected]4b02bbca2013-11-22 08:59:03134 AXTree();
dmazzoni329fd012015-10-22 20:05:35135 explicit AXTree(const AXTreeUpdate& initial_state);
[email protected]4b02bbca2013-11-22 08:59:03136 virtual ~AXTree();
137
Lei Zhanga06144782020-03-13 09:28:47138 // AXTree owns pointers so copying is non-trivial.
139 AXTree(const AXTree&) = delete;
140 AXTree& operator=(const AXTree&) = delete;
141
Dominic Mazzoni8549eb682018-12-11 23:48:32142 void AddObserver(AXTreeObserver* observer);
143 bool HasObserver(AXTreeObserver* observer);
Nektarios Paisiosdb7b5ee2020-02-18 21:28:11144 void RemoveObserver(AXTreeObserver* observer);
Dominic Mazzoni8549eb682018-12-11 23:48:32145
146 base::ObserverList<AXTreeObserver>& observers() { return observers_; }
[email protected]e736e81b2014-02-24 07:15:58147
tfarina6b1c1e082015-02-20 23:47:07148 AXNode* root() const { return root_; }
149
Alexander Surkov4ab64cf2022-09-01 20:07:46150 const AXTreeData& data() const;
dmazzoni329fd012015-10-22 20:05:35151
Nektarios Paisiosdb7b5ee2020-02-18 21:28:11152 // Destroys the tree and notifies all observers.
153 void Destroy();
154
Adam Ettenberger86af2532019-09-17 20:04:46155 // Returns the globally unique ID of this accessibility tree.
Alexander Surkov4ab64cf2022-09-01 20:07:46156 const AXTreeID& GetAXTreeID() const;
Adam Ettenberger86af2532019-09-17 20:04:46157
Alexander Surkov4ab64cf2022-09-01 20:07:46158 // Given a node in this accessibility tree that corresponds to a table
159 // or grid, return an object containing information about the
160 // table structure. This object is computed lazily on-demand and
161 // cached until the next time the tree is updated. Clients should
162 // not retain this pointer, they should just request it every time
163 // it's needed.
164 //
165 // Returns nullptr if the node is not a valid table.
166 AXTableInfo* GetTableInfo(const AXNode* table_node) const;
167
tfarina6b1c1e082015-02-20 23:47:07168 // Returns the AXNode with the given |id| if it is part of this AXTree.
Alexander Surkov4ab64cf2022-09-01 20:07:46169 AXNode* GetFromId(AXNodeID id) const;
[email protected]4b02bbca2013-11-22 08:59:03170
[email protected]d4e273462013-12-04 04:37:58171 // Returns true on success. If it returns false, it's a fatal error
172 // and this tree should be destroyed, and the source of the tree update
173 // should not be trusted any longer.
dmazzoni329fd012015-10-22 20:05:35174 virtual bool Unserialize(const AXTreeUpdate& update);
175
Nektarios Paisios26ac2b42021-06-02 18:24:19176 // Used by tests to update the tree data without changing any of the nodes in
177 // the tree, notifying all tree observers in the process.
178 virtual void UpdateDataForTesting(const AXTreeData& data);
[email protected]4b02bbca2013-11-22 08:59:03179
Dominic Mazzoni2410fc62017-06-09 22:19:18180 // Convert any rectangle from the local coordinate space of one node in
181 // the tree, to bounds in the coordinate space of the tree.
Katie Dektar2c6052d2017-09-27 00:32:32182 // If set, updates |offscreen| boolean to be true if the node is offscreen
183 // relative to its rootWebArea. Callers should initialize |offscreen|
184 // to false: this method may get called multiple times in a row and
185 // |offscreen| will be propagated.
Katie Dektardb71ad942017-11-29 20:07:48186 // If |clip_bounds| is true, result bounds will be clipped.
Dominic Mazzoni2410fc62017-06-09 22:19:18187 gfx::RectF RelativeToTreeBounds(const AXNode* node,
Katie Dektar2c6052d2017-09-27 00:32:32188 gfx::RectF node_bounds,
Katie Dektardb71ad942017-11-29 20:07:48189 bool* offscreen = nullptr,
David Tseng7bf30c3c2022-07-22 15:13:37190 bool clip_bounds = true,
191 bool skip_container_offset = false) const;
Dominic Mazzoni2410fc62017-06-09 22:19:18192
193 // Get the bounds of a node in the coordinate space of the tree.
Katie Dektar2c6052d2017-09-27 00:32:32194 // If set, updates |offscreen| boolean to be true if the node is offscreen
195 // relative to its rootWebArea. Callers should initialize |offscreen|
196 // to false: this method may get called multiple times in a row and
197 // |offscreen| will be propagated.
Katie Dektardb71ad942017-11-29 20:07:48198 // If |clip_bounds| is true, result bounds will be clipped.
199 gfx::RectF GetTreeBounds(const AXNode* node,
200 bool* offscreen = nullptr,
201 bool clip_bounds = true) const;
Dominic Mazzoni2410fc62017-06-09 22:19:18202
Dominic Mazzoni35f2a5252017-09-26 00:56:04203 // Given a node ID attribute (one where IsNodeIdIntAttribute is true),
204 // and a destination node ID, return a set of all source node IDs that
205 // have that relationship attribute between them and the destination.
Nektarios Paisios527d33fb52021-02-23 19:23:28206 std::set<AXNodeID> GetReverseRelations(ax::mojom::IntAttribute attr,
207 AXNodeID dst_id) const;
Dominic Mazzoni35f2a5252017-09-26 00:56:04208
209 // Given a node ID list attribute (one where
210 // IsNodeIdIntListAttribute is true), and a destination node ID,
211 // return a set of all source node IDs that have that relationship
212 // attribute between them and the destination.
Nektarios Paisios527d33fb52021-02-23 19:23:28213 std::set<AXNodeID> GetReverseRelations(ax::mojom::IntListAttribute attr,
214 AXNodeID dst_id) const;
Dominic Mazzoni35f2a5252017-09-26 00:56:04215
Dominic Mazzoniaa774822018-08-29 20:33:58216 // Given a child tree ID, return the node IDs of all nodes in the tree who
217 // have a kChildTreeId int attribute with that value.
Nektarios Paisios50e579f12022-05-19 19:22:39218 //
219 // TODO(accessibility): There should really be only one host node per child
220 // tree, so the return value should not be a set but a single node ID or
221 // `kInvalidAXNodeID`.
Nektarios Paisios527d33fb52021-02-23 19:23:28222 std::set<AXNodeID> GetNodeIdsForChildTreeId(AXTreeID child_tree_id) const;
Dominic Mazzoniaa774822018-08-29 20:33:58223
Dominic Mazzoni748888c2018-11-01 22:34:59224 // Get all of the child tree IDs referenced by any node in this tree.
225 const std::set<AXTreeID> GetAllChildTreeIds() const;
226
David Tsengef6b480d2018-02-19 12:48:42227 // Map from a relation attribute to a map from a target id to source ids.
228 const IntReverseRelationMap& int_reverse_relations() {
229 return int_reverse_relations_;
230 }
231 const IntListReverseRelationMap& intlist_reverse_relations() {
232 return intlist_reverse_relations_;
233 }
Dominic Mazzoni3d9b5b92018-04-18 21:36:38234
[email protected]5eec2f52014-01-06 22:30:54235 // Return a multi-line indented string representation, for logging.
Aaron Leventhal763d46a2022-12-21 19:16:22236 std::string ToString(bool verbose = true) const;
[email protected]5eec2f52014-01-06 22:30:54237
[email protected]d4e273462013-12-04 04:37:58238 // A string describing the error from an unsuccessful Unserialize,
239 // for testing and debugging.
tfarinad0bfb4b62015-02-18 17:20:32240 const std::string& error() const { return error_; }
[email protected]d4e273462013-12-04 04:37:58241
dmazzoniee2eaca2015-03-18 18:13:07242 int size() { return static_cast<int>(id_map_.size()); }
243
Dominic Mazzonid42e00a2018-06-27 23:14:23244 // Return a negative number that's suitable to use for a node ID for
245 // internal nodes created automatically by an AXTree, so as not to
246 // conflict with positive-numbered node IDs from tree sources.
Nektarios Paisios527d33fb52021-02-23 19:23:28247 AXNodeID GetNextNegativeInternalNodeId();
Dominic Mazzonid42e00a2018-06-27 23:14:23248
Akihiro Otaf42a7d02020-06-12 19:07:56249 // Returns the PosInSet of |node|. Looks in node_set_size_pos_in_set_info_map_
250 // for cached value. Calls |ComputeSetSizePosInSetAndCache|if no value is
251 // present in the cache.
Arthur Sonzogni3eb9fd512024-02-09 12:20:43252 std::optional<int> GetPosInSet(const AXNode& node);
Alexander Surkov4ab64cf2022-09-01 20:07:46253
Akihiro Otaf42a7d02020-06-12 19:07:56254 // Returns the SetSize of |node|. Looks in node_set_size_pos_in_set_info_map_
255 // for cached value. Calls |ComputeSetSizePosInSetAndCache|if no value is
256 // present in the cache.
Arthur Sonzogni3eb9fd512024-02-09 12:20:43257 std::optional<int> GetSetSize(const AXNode& node);
Akihiro Ota413ca722018-12-03 23:29:00258
Nektarios Paisiosd3e82c6d2022-08-12 19:06:55259 // Returns the part of the current selection that falls within this
260 // accessibility tree, if any.
Alexander Surkov4ab64cf2022-09-01 20:07:46261 AXSelection GetSelection() const;
Nektarios Paisiosd3e82c6d2022-08-12 19:06:55262
263 // Returns the part of the current selection that falls within this
264 // accessibility tree, if any, adjusting its endpoints to be within unignored
265 // nodes. (An "ignored" node is a node that is not exposed to platform APIs:
266 // See `AXNode::IsIgnored`.)
Aaron leventhalebac41bf2025-04-17 22:40:29267 AXSelection GetUnignoredSelection() const;
Jacques Newman339afc62019-08-14 00:49:22268
Alexander Surkov4ab64cf2022-09-01 20:07:46269 bool GetTreeUpdateInProgressState() const;
Akihiro Otae3e420e2019-04-17 19:57:40270
Kurt Catti-Schmidtc8445a12019-08-07 18:52:58271 // Returns true if the tree represents a paginated document
Alexander Surkov4ab64cf2022-09-01 20:07:46272 bool HasPaginationSupport() const;
Kurt Catti-Schmidtc8445a12019-08-07 18:52:58273
Chris Hall697d99b2019-07-09 02:36:11274 // Language detection manager, entry point to language detection features.
275 // TODO(chrishall): Should this be stored by pointer or value?
276 // When should we initialize this?
277 std::unique_ptr<AXLanguageDetectionManager> language_detection_manager;
Chris Hall34208182019-03-13 02:26:18278
David Tseng41f13cbd2021-11-06 18:39:03279 // Event metadata while applying a tree update during unserialization.
280 AXEvent* event_data() const { return event_data_.get(); }
David Tsengb0d43662020-05-20 20:47:28281
Benjamin Beaudry710df4d2023-02-08 23:47:56282 // Notify the delegate that the tree manager for |previous_tree_id| will be
283 // removed from the AXTreeManagerMap. Because we sometimes remove the tree
284 // manager after the tree's id has been modified, we need to pass the (old)
285 // tree id associated with the manager we are removing even though it is the
286 // same tree.
287 void NotifyTreeManagerWillBeRemoved(AXTreeID previous_tree_id);
Benjamin Beaudrye8f23a22020-12-17 20:08:02288
Stefan Zager3a5aabb2023-03-28 22:53:20289 void NotifyChildTreeConnectionChanged(AXNode* node, AXTree* child_tree);
290
Evelynn Kaplan6cd535ce2025-03-20 23:58:18291#if BUILDFLAG(IS_LINUX)
292 void ClearExtraAnnouncementNodes();
293 void CreateExtraAnnouncementNodes();
294 ExtraAnnouncementNodes* extra_announcement_nodes() const {
295 return extra_announcement_nodes_.get();
296 }
297#endif // BUILDFLAG(IS_LINUX)
298
[email protected]e736e81b2014-02-24 07:15:58299 private:
Nektarios Paisios8eb31fc2022-02-18 16:37:58300 friend class ScopedTreeUpdateInProgressStateSetter;
Dominic Mazzoniecfb4fd2018-10-23 07:34:20301 friend class AXTableInfoTest;
302
Nektarios Paisios77c422a2021-10-19 10:37:00303 // Indicates if the node with the focus should never be ignored, (see
304 // `SetFocusedNodeShouldNeverBeIgnored` above).
305 static bool is_focused_node_always_unignored_;
306
Aaron Leventhalf92d9972024-12-05 20:58:38307#if AX_FAIL_FAST_BUILD()
Aaron Leventhalc0bc6e92024-02-02 01:09:13308 void CheckTreeConsistency(const AXTreeUpdate& update);
309#endif
310
Aaron Leventhala674d632020-09-30 07:05:36311 // Accumulate errors as there can be more than one before Chrome is crashed
Aaron Leventhal6ceb5882024-04-17 15:19:38312 // via UnrecoverableAccessibilityError();
Aaron Leventhale12416e2022-12-23 16:08:17313 // In an AX_FAIL_FAST_BUILD or if |is_fatal|, will assert/crash immediately.
Aaron Leventhalbc649ff2022-08-11 18:53:23314 void RecordError(const AXTreeUpdateState& update_state,
Aaron Leventhale12416e2022-12-23 16:08:17315 std::string new_error,
316 bool is_fatal = false);
Aaron Leventhala674d632020-09-30 07:05:36317
dtseng5a7b3d92016-09-08 06:35:58318 AXNode* CreateNode(AXNode* parent,
Dominic Mazzoni9ccdedb22021-01-30 17:59:42319 AXNodeID id,
Peter Kasting94a07a12019-05-22 19:26:28320 size_t index_in_parent,
dtseng5a7b3d92016-09-08 06:35:58321 AXTreeUpdateState* update_state);
[email protected]4b02bbca2013-11-22 08:59:03322
Adam Ettenbergerd9d8d58a2019-08-06 16:54:08323 // Accumulates the work that will be required to update the AXTree.
324 // This allows us to notify observers of structure changes when the
325 // tree is still in a stable and unchanged state.
326 bool ComputePendingChanges(const AXTreeUpdate& update,
Aaron Leventhal051c14312023-09-01 00:17:01327 AXTreeUpdateState* update_state);
Adam Ettenbergerd9d8d58a2019-08-06 16:54:08328
329 // Populates |update_state| with information about actions that will
330 // be performed on the tree during the update, such as adding or
331 // removing nodes in the tree. Returns true on success.
332 // Nothing within this call should modify tree structure or node data.
333 bool ComputePendingChangesToNode(const AXNodeData& new_data,
334 bool is_new_root,
Aaron Leventhal051c14312023-09-01 00:17:01335 AXTreeUpdateState* update_state);
Adam Ettenbergerd9d8d58a2019-08-06 16:54:08336
[email protected]4b02bbca2013-11-22 08:59:03337 // This is called from within Unserialize(), it returns true on success.
dmazzoni67b4db22016-04-23 00:40:04338 bool UpdateNode(const AXNodeData& src,
339 bool is_new_root,
340 AXTreeUpdateState* update_state);
[email protected]4b02bbca2013-11-22 08:59:03341
Adam Ettenbergerd9d8d58a2019-08-06 16:54:08342 // Notify the delegate that the subtree rooted at |node| will be
343 // destroyed or reparented.
344 void NotifySubtreeWillBeReparentedOrDeleted(
345 AXNode* node,
346 const AXTreeUpdateState* update_state);
347
348 // Notify the delegate that |node| will be destroyed or reparented.
349 void NotifyNodeWillBeReparentedOrDeleted(
Lucas Radaelli36b18752024-09-17 18:37:54350 AXNode& node,
351 const AXTreeUpdateState& update_state);
Adam Ettenbergerd9d8d58a2019-08-06 16:54:08352
353 // Notify the delegate that |node| and all of its descendants will be
Victor Feie3cce4c2019-11-14 18:35:41354 // destroyed. This function is called during AXTree teardown.
Lucas Radaelli36b18752024-09-17 18:37:54355 void RecursivelyNotifyNodeWillBeDeletedForTreeTeardown(
356 AXNode& node,
David Tsengd87e7632024-10-09 17:17:51357 std::set<AXNodeID>& deleted_nodes);
Victor Feie3cce4c2019-11-14 18:35:41358
359 // Notify the delegate that the node marked by |node_id| has been deleted.
360 // We are passing the node id instead of ax node is because by the time this
361 // function is called, the ax node in the tree will already have been
Adam Ettenbergerd9d8d58a2019-08-06 16:54:08362 // destroyed.
Dominic Mazzoni9ccdedb22021-01-30 17:59:42363 void NotifyNodeHasBeenDeleted(AXNodeID node_id);
Adam Ettenbergerd9d8d58a2019-08-06 16:54:08364
365 // Notify the delegate that |node| has been created or reparented.
366 void NotifyNodeHasBeenReparentedOrCreated(
367 AXNode* node,
368 const AXTreeUpdateState* update_state);
369
Nektarios Paisios77c422a2021-10-19 10:37:00370 // Notify the delegate that `node` will change its data attributes, including
371 // its ignored state.
372 void NotifyNodeAttributesWillChange(AXNode* node,
Aaron Leventhal06f376bf2022-12-01 02:15:07373 AXTreeUpdateState& update_state,
Nektarios Paisios77c422a2021-10-19 10:37:00374 const AXTreeData* optional_old_tree_data,
375 const AXNodeData& old_data,
376 const AXTreeData* new_tree_data,
377 const AXNodeData& new_data);
Adam Ettenberger05afcec2019-08-06 17:11:29378
Aaron Leventhal06f376bf2022-12-01 02:15:07379 // Notify the delegate that `node` will change its its ignored state.
380 void NotifyNodeIgnoredStateWillChange(
381 AXNode* node,
382 const AXTreeData* optional_old_tree_data,
383 const AXNodeData& old_data,
384 const AXTreeData* new_tree_data,
385 const AXNodeData& new_data);
386
Nektarios Paisios77c422a2021-10-19 10:37:00387 // Notify the delegate that `node` has changed its data attributes, including
388 // its ignored state.
389 void NotifyNodeAttributesHaveBeenChanged(
390 AXNode* node,
Aaron Leventhal06f376bf2022-12-01 02:15:07391 AXTreeUpdateState& update_state,
Nektarios Paisios77c422a2021-10-19 10:37:00392 const AXTreeData* optional_old_tree_data,
393 const AXNodeData& old_data,
394 const AXTreeData* new_tree_data,
395 const AXNodeData& new_data);
dmazzoni3ab5385c2017-03-13 18:07:03396
Aaron Leventhal32de9b92024-03-12 15:55:38397 // Update maps that track which relations are pointing to |node|.
398 void UpdateReverseRelations(AXNode* node,
399 const AXNodeData& new_data,
400 bool is_new_node = false);
Dominic Mazzoni35f2a5252017-09-26 00:56:04401
Nektarios Paisios8eb31fc2022-02-18 16:37:58402 // Sets a flag indicating whether the tree is currently being updated or not.
403 // If the tree is being updated, then its internal pointers might be invalid
404 // and the tree should not be traversed.
405 void SetTreeUpdateInProgressState(bool set_tree_update_value);
406
Adam Ettenbergerd9d8d58a2019-08-06 16:54:08407 // Returns true if all pending changes in the |update_state| have been
408 // handled. If this returns false, the |error_| message will be populated.
409 // It's a fatal error to have pending changes after exhausting
410 // the AXTreeUpdate.
411 bool ValidatePendingChangesComplete(const AXTreeUpdateState& update_state);
[email protected]4b02bbca2013-11-22 08:59:03412
Adam Ettenbergerd9d8d58a2019-08-06 16:54:08413 // Modifies |update_state| so that it knows what subtree and nodes are
414 // going to be destroyed for the subtree rooted at |node|.
Dominic Mazzoni9ccdedb22021-01-30 17:59:42415 void MarkSubtreeForDestruction(AXNodeID node_id,
Adam Ettenbergerd9d8d58a2019-08-06 16:54:08416 AXTreeUpdateState* update_state);
417
418 // Modifies |update_state| so that it knows what nodes are
419 // going to be destroyed for the subtree rooted at |node|.
Dominic Mazzoni9ccdedb22021-01-30 17:59:42420 void MarkNodesForDestructionRecursive(AXNodeID node_id,
Adam Ettenbergerd9d8d58a2019-08-06 16:54:08421 AXTreeUpdateState* update_state);
422
423 // Validates that destroying the subtree rooted at |node| has required
424 // information in |update_state|, then calls DestroyNodeAndSubtree on it.
dmazzonie3b7faf2015-06-01 17:56:36425 void DestroySubtree(AXNode* node, AXTreeUpdateState* update_state);
dmazzonia4b48912015-01-24 00:08:56426
[email protected]4b02bbca2013-11-22 08:59:03427 // Call Destroy() on |node|, and delete it from the id map, and then
428 // call recursively on all nodes in its subtree.
dmazzonie3b7faf2015-06-01 17:56:36429 void DestroyNodeAndSubtree(AXNode* node, AXTreeUpdateState* update_state);
[email protected]4b02bbca2013-11-22 08:59:03430
431 // Iterate over the children of |node| and for each child, destroy the
Adam Ettenbergerd9d8d58a2019-08-06 16:54:08432 // child and its subtree if its id is not in |new_child_ids|.
433 void DeleteOldChildren(AXNode* node,
Nektarios Paisios527d33fb52021-02-23 19:23:28434 const std::vector<AXNodeID>& new_child_ids,
dmazzonie3b7faf2015-06-01 17:56:36435 AXTreeUpdateState* update_state);
[email protected]4b02bbca2013-11-22 08:59:03436
437 // Iterate over |new_child_ids| and populate |new_children| with
438 // pointers to child nodes, reusing existing nodes already in the tree
439 // if they exist, and creating otherwise. Reparenting is disallowed, so
440 // if the id already exists as the child of another node, that's an
[email protected]e736e81b2014-02-24 07:15:58441 // error. Returns true on success, false on fatal error.
Ali Hijazie63cbaf62023-12-20 19:29:35442 bool CreateNewChildVector(
443 AXNode* node,
444 const std::vector<AXNodeID>& new_child_ids,
445 std::vector<raw_ptr<AXNode, VectorExperimental>>* new_children,
446 AXTreeUpdateState* update_state);
[email protected]4b02bbca2013-11-22 08:59:03447
Nektarios Paisios77c422a2021-10-19 10:37:00448 // Returns the lowest unignored ancestor of the node with the given ID. If the
449 // node is not ignored, it returns the node.
450 AXNode* GetUnignoredAncestorFromId(AXNodeID node_id) const;
451
Dominic Mazzonia1bb0d122019-09-26 20:19:59452 // Internal implementation of RelativeToTreeBounds. It calls itself
453 // recursively but ensures that it can only do so exactly once!
454 gfx::RectF RelativeToTreeBoundsInternal(const AXNode* node,
455 gfx::RectF node_bounds,
456 bool* offscreen,
457 bool clip_bounds,
David Tseng7bf30c3c2022-07-22 15:13:37458 bool skip_container_offset,
Dominic Mazzonia1bb0d122019-09-26 20:19:59459 bool allow_recursion) const;
460
Dominic Mazzoni8549eb682018-12-11 23:48:32461 base::ObserverList<AXTreeObserver> observers_;
Ali Hijazi2fe3e402022-08-05 16:09:31462 raw_ptr<AXNode> root_ = nullptr;
Bruce Dawson9d565ec2022-10-31 17:42:34463 std::unordered_map<AXNodeID, std::unique_ptr<AXNode>> id_map_;
[email protected]d4e273462013-12-04 04:37:58464 std::string error_;
dmazzoni329fd012015-10-22 20:05:35465 AXTreeData data_;
Dominic Mazzoni35f2a5252017-09-26 00:56:04466
467 // Map from an int attribute (if IsNodeIdIntAttribute is true) to
468 // a reverse mapping from target nodes to source nodes.
David Tsengef6b480d2018-02-19 12:48:42469 IntReverseRelationMap int_reverse_relations_;
Dominic Mazzoni35f2a5252017-09-26 00:56:04470 // Map from an int list attribute (if IsNodeIdIntListAttribute is true) to
471 // a reverse mapping from target nodes to source nodes.
David Tsengef6b480d2018-02-19 12:48:42472 IntListReverseRelationMap intlist_reverse_relations_;
Dominic Mazzoniaa774822018-08-29 20:33:58473 // Map from child tree ID to the set of node IDs that contain that attribute.
Nektarios Paisios527d33fb52021-02-23 19:23:28474 std::map<AXTreeID, std::set<AXNodeID>> child_tree_id_reverse_map_;
Dominic Mazzoni3d9b5b92018-04-18 21:36:38475
476 // Map from node ID to cached table info, if the given node is a table.
Dominic Mazzonid42e00a2018-06-27 23:14:23477 // Invalidated every time the tree is updated.
Bruce Dawson9d565ec2022-10-31 17:42:34478 mutable std::unordered_map<AXNodeID, std::unique_ptr<AXTableInfo>>
Aaron Leventhal80797182020-02-25 18:50:31479 table_info_map_;
Dominic Mazzonid42e00a2018-06-27 23:14:23480
481 // The next negative node ID to use for internal nodes.
Nektarios Paisios527d33fb52021-02-23 19:23:28482 AXNodeID next_negative_internal_node_id_ = -1;
Dominic Mazzonid42e00a2018-06-27 23:14:23483
Akihiro Ota413ca722018-12-03 23:29:00484 // Contains pos_in_set and set_size data for an AXNode.
Stephan Hartmannaeef6882020-04-20 18:21:43485 struct NodeSetSizePosInSetInfo {
486 NodeSetSizePosInSetInfo();
487 ~NodeSetSizePosInSetInfo();
488
Arthur Sonzogni3eb9fd512024-02-09 12:20:43489 std::optional<int> pos_in_set;
490 std::optional<int> set_size;
491 std::optional<int> lowest_hierarchical_level;
Stephan Hartmannaeef6882020-04-20 18:21:43492 };
Akihiro Ota413ca722018-12-03 23:29:00493
Victor Fei5eea952e2020-02-28 01:43:09494 // Represents the content of an ordered set which includes the ordered set
495 // items and the ordered set container if it exists.
496 struct OrderedSetContent;
497
498 // Maps a particular hierarchical level to a list of OrderedSetContents.
499 // Represents all ordered set items/container on a particular hierarchical
500 // level.
501 struct OrderedSetItemsMap;
502
503 // Populates |items_map_to_be_populated| with all items associated with
Victor Feid95130c2020-02-03 21:42:54504 // |original_node| and within |ordered_set|. Only items whose roles match the
505 // role of the |ordered_set| will be added.
Victor Fei5eea952e2020-02-28 01:43:09506 void PopulateOrderedSetItemsMap(
Victor Feid95130c2020-02-03 21:42:54507 const AXNode& original_node,
508 const AXNode* ordered_set,
Lei Zhanga06144782020-03-13 09:28:47509 OrderedSetItemsMap* items_map_to_be_populated) const;
Victor Feid95130c2020-02-03 21:42:54510
Victor Fei5eea952e2020-02-28 01:43:09511 // Helper function for recursively populating ordered sets items map with
Victor Feid95130c2020-02-03 21:42:54512 // all items associated with |original_node| and |ordered_set|. |local_parent|
513 // tracks the recursively passed in child nodes of |ordered_set|.
Victor Fei5eea952e2020-02-28 01:43:09514 void RecursivelyPopulateOrderedSetItemsMap(
Victor Feid95130c2020-02-03 21:42:54515 const AXNode& original_node,
516 const AXNode* ordered_set,
517 const AXNode* local_parent,
Arthur Sonzogni3eb9fd512024-02-09 12:20:43518 std::optional<int> ordered_set_min_level,
519 std::optional<int> prev_level,
Lei Zhanga06144782020-03-13 09:28:47520 OrderedSetItemsMap* items_map_to_be_populated) const;
Akihiro Ota886a96d62018-12-18 00:11:48521
Victor Fei5eea952e2020-02-28 01:43:09522 // Computes the pos_in_set and set_size values of all items in ordered_set and
523 // caches those values. Called by GetPosInSet and GetSetSize.
Akihiro Ota886a96d62018-12-18 00:11:48524 void ComputeSetSizePosInSetAndCache(const AXNode& node,