1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
|
// Copyright 2019 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef UI_ACCESSIBILITY_AX_TREE_MANAGER_H_
#define UI_ACCESSIBILITY_AX_TREE_MANAGER_H_
#include "base/scoped_observation.h"
#include "ui/accessibility/ax_event_generator.h"
#include "ui/accessibility/ax_export.h"
#include "ui/accessibility/ax_tree.h"
#include "ui/accessibility/ax_tree_observer.h"
namespace ui {
class AXNode;
class AXTreeManagerMap;
// Abstract interface for a class that owns an AXTree and manages its
// connections to other AXTrees in the same page or desktop (parent and child
// trees).
class AX_EXPORT AXTreeManager : public AXTreeObserver {
public:
static AXTreeManager* FromID(const AXTreeID& ax_tree_id);
// If the child of `parent_node` exists in a separate child tree, return the
// tree manager for that child tree. Otherwise, return nullptr.
static AXTreeManager* ForChildTree(const AXNode& parent_node);
// For testing only, register a function to be called when focus changes
// in any AXTreeManager.
static void SetFocusChangeCallbackForTesting(base::RepeatingClosure callback);
AXTreeManager(const AXTreeManager&) = delete;
AXTreeManager& operator=(const AXTreeManager&) = delete;
~AXTreeManager() override;
enum class RetargetEventType {
RetargetEventTypeGenerated = 0,
RetargetEventTypeBlinkGeneral,
RetargetEventTypeBlinkHover,
};
// Subclasses override these methods to send native event notifications.
virtual void FireFocusEvent(AXNode* node);
// Return |node| by default, but some platforms want to update the target node
// based on the event type.
virtual AXNode* RetargetForEvents(AXNode* node, RetargetEventType type) const;
virtual void FireGeneratedEvent(ui::AXEventGenerator::Event event_type,
const ui::AXNode* node) {}
// Returns the AXNode with the given |node_id| from the tree that has the
// given |tree_id|. This allows for callers to access nodes outside of their
// own tree. Returns nullptr if |tree_id| or |node_id| is not found.
// TODO(kschmi): Remove |tree_id| parameter, as it's unnecessary.
virtual AXNode* GetNodeFromTree(const AXTreeID& tree_id,
const AXNodeID node_id) const = 0;
// Returns the AXNode in the current tree that has the given |node_id|.
// Returns nullptr if |node_id| is not found.
virtual AXNode* GetNode(const AXNodeID node_id) const;
// Returns the tree id of the tree managed by this AXTreeManager.
AXTreeID GetTreeID() const;
// Returns the AXTreeData for the tree managed by this AXTreeManager.
const AXTreeData& GetTreeData() const;
// Returns the tree id of the parent tree.
// Returns AXTreeIDUnknown if this tree doesn't have a parent tree.
virtual AXTreeID GetParentTreeID() const;
// Returns the AXNode that is at the root of the current tree.
AXNode* GetRoot() const;
bool IsRoot() const;
// Returns the root AXTreeManager by walking up the tree to any parent trees.
// If there is a parent tree that is not yet connected, returns nullptr.
AXTreeManager* GetRootManager() const;
// If this tree has a parent tree, returns the node in the parent tree that
// hosts the current tree. Returns nullptr if this tree doesn't have a parent
// tree.
virtual AXNode* GetParentNodeFromParentTreeAsAXNode() const = 0;
void Initialize(const AXTreeUpdate& initial_tree);
// Called when the tree manager is about to be removed from the tree map,
// `AXTreeManagerMap`.
void WillBeRemovedFromMap();
const AXTreeID& ax_tree_id() const { return ax_tree_id_; }
AXTree* ax_tree() const { return ax_tree_.get(); }
const AXEventGenerator& event_generator() const { return event_generator_; }
AXEventGenerator& event_generator() { return event_generator_; }
// AXTreeObserver implementation.
void OnTreeDataChanged(AXTree* tree,
const AXTreeData& old_data,
const AXTreeData& new_data) override;
void OnNodeWillBeDeleted(AXTree* tree, AXNode* node) override;
void OnSubtreeWillBeDeleted(AXTree* tree, AXNode* node) override {}
void OnNodeCreated(AXTree* tree, AXNode* node) override {}
void OnNodeDeleted(AXTree* tree, int32_t node_id) override {}
void OnNodeReparented(AXTree* tree, AXNode* node) override {}
void OnRoleChanged(AXTree* tree,
AXNode* node,
ax::mojom::Role old_role,
ax::mojom::Role new_role) override {}
void OnAtomicUpdateFinished(
AXTree* tree,
bool root_changed,
const std::vector<AXTreeObserver::Change>& changes) override {}
protected:
AXTreeManager();
explicit AXTreeManager(std::unique_ptr<AXTree> tree);
explicit AXTreeManager(const AXTreeID& tree_id, std::unique_ptr<AXTree> tree);
// TODO(benjamin.beaudry): Remove this helper once we move the logic related
// to the parent connection from `BrowserAccessibilityManager` to this class.
// `BrowserAccessibilityManager` needs to remove the manager from the map
// before calling `BrowserAccessibilityManager::ParentConnectionChanged`, so
// the default removal of the manager in `~AXTreeManager` occurs too late.
void RemoveFromMap();
virtual AXTreeManager* GetParentManager() const;
// Return the last node that had focus, no searching.
static AXNode* GetLastFocusedNode();
static void SetLastFocusedNode(AXNode* node);
AXTreeID ax_tree_id_;
std::unique_ptr<AXTree> ax_tree_;
AXEventGenerator event_generator_;
// Stores the id of the last focused node, as well as the id
// of the tree that contains it, so that when focus might have changed we can
// figure out whether we need to fire a focus event.
//
// NOTE: Don't use or modify these properties directly, use the
// SetLastFocusedNode and GetLastFocusedNode methods instead.
static absl::optional<AXNodeID> last_focused_node_id_;
static absl::optional<AXTreeID> last_focused_node_tree_id_;
private:
friend class AXDummyTreeManager;
friend class TestAXTreeManager;
static AXTreeManagerMap& GetMap();
// Automatically stops observing notifications from the AXTree when this class
// is destructed.
//
// This member needs to be destructed before any observed AXTrees. Since
// destructors for non-static member fields are called in the reverse order of
// declaration, do not move this member above other members.
base::ScopedObservation<AXTree, AXTreeObserver> tree_observation_{this};
};
} // namespace ui
#endif // UI_ACCESSIBILITY_AX_TREE_MANAGER_H_
|