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 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217
|
// 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;
// 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)
// as well as a mapping of AXNode's by ID for supporting `GetNodeFromTree`
// and related methods.
//
// Note, the tree manager may be created for a tree which has unknown (not
// valid) tree id. A such tree is not registered with the tree map and thus
// cannot be retrieved from the map. When the tree gets data and tree id, then
// it is registered in the map automatically (see OnTreeDataChanged callback
// notification). The mechanism implements the tree id data integrirty between
// the tree map and trees, also it doesn't allow to register two different trees
// with unknown IDs.
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, get the registered focus change callback
static base::RepeatingClosure& GetFocusChangeCallbackForTesting();
// For testing only, register a function to be called when focus changes
// in any AXTreeManager.
static void SetFocusChangeCallbackForTesting(base::RepeatingClosure callback);
// This default constructor does not create an empty accessibility tree. Call
// `SetTree` if you need to manage a specific tree.
AXTreeManager();
explicit AXTreeManager(std::unique_ptr<AXTree> tree);
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) {}
virtual bool CanFireEvents() const;
// Returns whether or not this tree manager is for a view.
virtual bool IsView() const;
// 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;
// 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 true if the manager has a tree with a valid (not unknown) ID.
bool HasValidTreeID() const {
return ax_tree_ && ax_tree_->GetAXTreeID() != ui::AXTreeIDUnknown();
}
// Returns the tree id of the tree managed by this AXTreeManager.
AXTreeID GetTreeID() const {
return ax_tree_ ? ax_tree_->GetAXTreeID() : ui::AXTreeIDUnknown();
}
// 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;
// Whether this manager can access platform nodes. Defaults to false
// and is overridden in `AXPlatformTreeManager` to return true.
virtual bool IsPlatformTreeManager() const;
// Returns the AXNode that is at the root of the current tree.
virtual 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* GetParentNodeFromParentTree() const;
void Initialize(const AXTreeUpdate& initial_tree);
// Called when the tree manager is about to be removed from the tree map,
// `AXTreeManagerMap`.
void WillBeRemovedFromMap();
// Returns a pointer to the managed tree, if any.
AXTree* ax_tree() const { return ax_tree_.get(); }
// Takes ownership of a new accessibility tree and returns the one that is
// currently being managed. It is considered an error to pass an empty
// unique_ptr for `tree`. If no tree is currently being managed, returns an
// empty unique_ptr.
std::unique_ptr<AXTree> SetTree(std::unique_ptr<AXTree> tree);
std::unique_ptr<AXTree> SetTree(const AXTreeUpdate& initial_state);
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:
// This is only made protected to accommodate the `AtomicViewAXTreeManager`.
// It should be made private once that class is removed.
// TODO(crbug.com/1468416): Make private.
static AXTreeManagerMap& GetMap();
virtual AXTreeManager* GetParentManager() const;
// Return the last node that had focus, no searching.
static AXNode* GetLastFocusedNode();
static void SetLastFocusedNode(AXNode* node);
// Add parent connection if missing (!connected_to_parent_tree_node_). If the
// root's parent is in another accessibility tree but it wasn't previously
// connected, post the proper notifications on the parent.
void EnsureParentConnectionIfNotRootManager();
// Refreshes a parent node in a parent tree when it needs to be informed that
// this tree is ready or being destroyed.
void ParentConnectionChanged(AXNode* parent);
// Inheriting classes should override this method to update the `parent`
// attributes accordingly when the parent connection changes.
virtual void UpdateAttributesOnParent(AXNode* parent) {}
// Perform some additional clean up on the derived classes to be called in the
// destructor.
virtual void CleanUp() {}
// True if the root's parent is in another accessibility tree and that
// parent's child is the root. Ensures that the parent node is notified
// once when this subtree is first connected.
bool connected_to_parent_tree_node_;
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 TestSingleAXTreeManager;
// 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_
|