diff options
author | dmazzoni@chromium.org <dmazzoni@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-04-21 10:46:20 +0000 |
---|---|---|
committer | dmazzoni@chromium.org <dmazzoni@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-04-21 10:46:20 +0000 |
commit | a91c27f77a40920fb9af5b8c1249dfe03e35d9bc (patch) | |
tree | a1316405c6adb9650c159a1c98d4668e9a49fcb0 /ui/accessibility | |
parent | c923ccc455bda766a9cf46e1feddc099933a3af9 (diff) | |
download | chromium_src-a91c27f77a40920fb9af5b8c1249dfe03e35d9bc.zip chromium_src-a91c27f77a40920fb9af5b8c1249dfe03e35d9bc.tar.gz chromium_src-a91c27f77a40920fb9af5b8c1249dfe03e35d9bc.tar.bz2 |
Make BrowserAccessibilityManager use AXTree.
This is the final step of migrating content/*/accessibility to make
full use of the new infrastructure in ui/accessibility.
Previously, BrowserAccessibilityManager owned the tree of
BrowserAccessibility objects and handled making changes to the
tree in response to messages from the renderer. Now, AXTree
handles the updates from the renderer and notifies
BrowserAccessibilityManager (via AXTreeDelegate) when it
should create or destroy BrowserAccessibility objects, and when
it should notify a BrowserAccessibility object that it's been
modified.
This makes the serialization/unserialization logic fully tested now,
and greatly clarifies the semantics of when in the update cycle
various notifications are called (e.g., PreInitialize and PostInitialize
are now OnDataChanged and OnUpdateFinished).
BUG=316726
Review URL: https://codereview.chromium.org/234723003
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@264979 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ui/accessibility')
-rw-r--r-- | ui/accessibility/ax_node.cc | 13 | ||||
-rw-r--r-- | ui/accessibility/ax_node.h | 15 | ||||
-rw-r--r-- | ui/accessibility/ax_tree.cc | 33 | ||||
-rw-r--r-- | ui/accessibility/ax_tree.h | 37 | ||||
-rw-r--r-- | ui/accessibility/ax_tree_unittest.cc | 17 |
5 files changed, 85 insertions, 30 deletions
diff --git a/ui/accessibility/ax_node.cc b/ui/accessibility/ax_node.cc index 8adb940..587f737 100644 --- a/ui/accessibility/ax_node.cc +++ b/ui/accessibility/ax_node.cc @@ -19,6 +19,10 @@ void AXNode::SetData(const AXNodeData& src) { data_ = src; } +void AXNode::SetLocation(const gfx::Rect& new_location) { + data_.location = new_location; +} + void AXNode::SetIndexInParent(int index_in_parent) { index_in_parent_ = index_in_parent; } @@ -31,4 +35,13 @@ void AXNode::Destroy() { delete this; } +bool AXNode::IsDescendantOf(AXNode* ancestor) { + if (this == ancestor) + return true; + else if (parent()) + return parent()->IsDescendantOf(ancestor); + + return false; +} + } // namespace ui diff --git a/ui/accessibility/ax_node.h b/ui/accessibility/ax_node.h index b7e3125..5da7340 100644 --- a/ui/accessibility/ax_node.h +++ b/ui/accessibility/ax_node.h @@ -24,27 +24,36 @@ class AX_EXPORT AXNode { int child_count() const { return static_cast<int>(children_.size()); } const AXNodeData& data() const { return data_; } const std::vector<AXNode*>& children() const { return children_; } + int index_in_parent() const { return index_in_parent_; } // Get the child at the given index. AXNode* ChildAtIndex(int index) const { return children_[index]; } // Set the node's accessibility data. This may be done during initial // initialization or later when the node data changes. - virtual void SetData(const AXNodeData& src); + void SetData(const AXNodeData& src); + + // Update this node's location. This is separate from SetData just because + // changing only the location is common and should be more efficient than + // re-copying all of the data. + void SetLocation(const gfx::Rect& new_location); // Set the index in parent, for example if siblings were inserted or deleted. void SetIndexInParent(int index_in_parent); // Swap the internal children vector with |children|. This instance // now owns all of the passed children. - virtual void SwapChildren(std::vector<AXNode*>& children); + void SwapChildren(std::vector<AXNode*>& children); // This is called when the AXTree no longer includes this node in the // tree. Reference counting is used on some platforms because the // operating system may hold onto a reference to an AXNode // object even after we're through with it, so this may decrement the // reference count and clear out the object's data. - virtual void Destroy(); + void Destroy(); + + // Return true if this object is equal to or a descendant of |ancestor|. + bool IsDescendantOf(AXNode* ancestor); private: int index_in_parent_; diff --git a/ui/accessibility/ax_tree.cc b/ui/accessibility/ax_tree.cc index f2ccdcb..d97b2f9 100644 --- a/ui/accessibility/ax_tree.cc +++ b/ui/accessibility/ax_tree.cc @@ -45,7 +45,7 @@ AXTreeDelegate::~AXTreeDelegate() { AXTree::AXTree() : delegate_(NULL), root_(NULL) { AXNodeData root; - root.id = 0; + root.id = -1; root.role = AX_ROLE_ROOT_WEB_AREA; AXTreeUpdate initial_state; @@ -117,10 +117,10 @@ bool AXTree::Unserialize(const AXTreeUpdate& update) { for (size_t i = 0; i < update.nodes.size(); ++i) { AXNode* node = GetFromId(update.nodes[i].id); if (update_state.new_nodes.find(node) != update_state.new_nodes.end()) { - delegate_->OnNodeCreated(node); + delegate_->OnNodeCreationFinished(node); update_state.new_nodes.erase(node); } else { - delegate_->OnNodeChanged(node); + delegate_->OnNodeChangeFinished(node); } } if (root_->id() != old_root_id) @@ -134,8 +134,13 @@ std::string AXTree::ToString() const { return TreeToStringHelper(root_, 0); } -AXNode* AXTree::CreateNode(AXNode* parent, int32 id, int32 index_in_parent) { - return new AXNode(parent, id, index_in_parent); +AXNode* AXTree::CreateNode( + AXNode* parent, int32 id, int32 index_in_parent) { + AXNode* new_node = new AXNode(parent, id, index_in_parent); + id_map_[new_node->id()] = new_node; + if (delegate_) + delegate_->OnNodeCreated(new_node); + return new_node; } bool AXTree::UpdateNode( @@ -150,19 +155,20 @@ bool AXTree::UpdateNode( AXNode* node = GetFromId(src.id); if (node) { update_state->pending_nodes.erase(node); + node->SetData(src); + if (delegate_) + delegate_->OnNodeChanged(node); } else { if (src.role != AX_ROLE_ROOT_WEB_AREA) { error_ = base::StringPrintf( "%d is not in the tree and not the new root", src.id); return false; } - node = CreateAndInitializeNode(NULL, src.id, 0); + node = CreateNode(NULL, src.id, 0); update_state->new_nodes.insert(node); + node->SetData(src); } - // Set the node's data. - node->SetData(src); - // First, delete nodes that used to be children of this node but aren't // anymore. if (!DeleteOldChildren(node, src.child_ids)) @@ -186,13 +192,6 @@ bool AXTree::UpdateNode( return success; } -AXNode* AXTree::CreateAndInitializeNode( - AXNode* parent, int32 id, int32 index_in_parent) { - AXNode* node = CreateNode(parent, id, index_in_parent); - id_map_[node->id()] = node; - return node; -} - void AXTree::DestroyNodeAndSubtree(AXNode* node) { id_map_.erase(node->id()); for (int i = 0; i < node->child_count(); ++i) @@ -251,7 +250,7 @@ bool AXTree::CreateNewChildVector(AXNode* node, } child->SetIndexInParent(index_in_parent); } else { - child = CreateAndInitializeNode(node, child_id, index_in_parent); + child = CreateNode(node, child_id, index_in_parent); update_state->pending_nodes.insert(child); update_state->new_nodes.insert(child); } diff --git a/ui/accessibility/ax_tree.h b/ui/accessibility/ax_tree.h index 6a4134c..b4baac4 100644 --- a/ui/accessibility/ax_tree.h +++ b/ui/accessibility/ax_tree.h @@ -17,6 +17,20 @@ class AXNode; struct AXTreeUpdateState; // Used when you want to be notified when changes happen to the tree. +// +// Some of the notifications are called in the middle of an update operation. +// Be careful, as the tree may be in an inconsistent state at this time; +// don't walk the parents and children at this time: +// OnNodeWillBeDeleted +// OnNodeCreated +// OnNodeChanged +// +// Other notifications are called at the end of an atomic update operation. +// From these, it's safe to walk the tree and do any initialization that +// assumes the tree is in a consistent state. +// OnNodeCreationFinished +// OnNodeChangeFinished +// OnRootChanged class AX_EXPORT AXTreeDelegate { public: AXTreeDelegate(); @@ -27,16 +41,23 @@ class AX_EXPORT AXTreeDelegate { // in the middle of an update, the tree may be in an invalid state! virtual void OnNodeWillBeDeleted(AXNode* node) = 0; - // Called after a new node is created. It's guaranteed to be called - // after it's been fully initialized, so you can rely on its data and - // links to parents and children being valid. This will be called on - // parents before it's called on their children. + // Called immediately after a new node is created. The tree may be in + // the middle of an update, don't walk the parents and children now. virtual void OnNodeCreated(AXNode* node) = 0; - // Called when a node changes its data or children. + // Called when a node changes its data or children. The tree may be in + // the middle of an update, don't walk the parents and children now. virtual void OnNodeChanged(AXNode* node) = 0; - // Called when the root node changes. + // Called for each new node at the end of an update operation, + // when the tree is in a consistent state. + virtual void OnNodeCreationFinished(AXNode* node) = 0; + + // Called for each existing node that changed at the end of an update + // operation, when the tree is in a consistent state. + virtual void OnNodeChangeFinished(AXNode* node) = 0; + + // Called at the end of an update operation when the root node changes. virtual void OnRootChanged(AXNode* new_root) = 0; }; @@ -76,10 +97,6 @@ class AX_EXPORT AXTree { void OnRootChanged(); - // Convenience function to create a node and call Initialize on it. - AXNode* CreateAndInitializeNode( - AXNode* parent, int32 id, int32 index_in_parent); - // Call Destroy() on |node|, and delete it from the id map, and then // call recursively on all nodes in its subtree. void DestroyNodeAndSubtree(AXNode* node); diff --git a/ui/accessibility/ax_tree_unittest.cc b/ui/accessibility/ax_tree_unittest.cc index 0001474..9d734f8 100644 --- a/ui/accessibility/ax_tree_unittest.cc +++ b/ui/accessibility/ax_tree_unittest.cc @@ -28,18 +28,31 @@ class FakeAXTreeDelegate : public AXTreeDelegate { changed_ids_.push_back(node->id()); } + virtual void OnNodeCreationFinished(AXNode* node) OVERRIDE { + creation_finished_ids_.push_back(node->id()); + } + + virtual void OnNodeChangeFinished(AXNode* node) OVERRIDE { + change_finished_ids_.push_back(node->id()); + } + virtual void OnRootChanged(AXNode* new_root) OVERRIDE { new_root_ids_.push_back(new_root->id()); } const std::vector<int32>& deleted_ids() { return deleted_ids_; } const std::vector<int32>& created_ids() { return created_ids_; } + const std::vector<int32>& creation_finished_ids() { + return creation_finished_ids_; + } const std::vector<int32>& new_root_ids() { return new_root_ids_; } private: std::vector<int32> deleted_ids_; std::vector<int32> created_ids_; + std::vector<int32> creation_finished_ids_; std::vector<int32> changed_ids_; + std::vector<int32> change_finished_ids_; std::vector<int32> new_root_ids_; }; @@ -272,6 +285,10 @@ TEST(AXTreeTest, TreeDelegateIsCalled) { EXPECT_EQ(2, fake_delegate.created_ids()[0]); EXPECT_EQ(3, fake_delegate.created_ids()[1]); + ASSERT_EQ(2U, fake_delegate.creation_finished_ids().size()); + EXPECT_EQ(2, fake_delegate.creation_finished_ids()[0]); + EXPECT_EQ(3, fake_delegate.creation_finished_ids()[1]); + ASSERT_EQ(1U, fake_delegate.new_root_ids().size()); EXPECT_EQ(2, fake_delegate.new_root_ids()[0]); |