Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(104)

Unified Diff: ui/accessibility/ax_tree.cc

Issue 1151393006: An accessibility tree update with two roots should be rejected. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « ui/accessibility/ax_tree.h ('k') | ui/accessibility/ax_tree_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: ui/accessibility/ax_tree.cc
diff --git a/ui/accessibility/ax_tree.cc b/ui/accessibility/ax_tree.cc
index 73b5c6d69765bcb9c3af06e673ec2d8e242fbc49..0ca9f597e2785a08ebca6fb6648e7aa69d5b1789 100644
--- a/ui/accessibility/ax_tree.cc
+++ b/ui/accessibility/ax_tree.cc
@@ -26,6 +26,8 @@ std::string TreeToStringHelper(AXNode* node, int indent) {
// Intermediate state to keep track of during a tree update.
struct AXTreeUpdateState {
+ AXTreeUpdateState() : new_root(nullptr) {}
+
// During an update, this keeps track of all nodes that have been
// implicitly referenced as part of this update, but haven't been
// updated yet. It's an error if there are any pending nodes at the
@@ -34,6 +36,9 @@ struct AXTreeUpdateState {
// Keeps track of new nodes created during this update.
std::set<AXNode*> new_nodes;
+
+ // The new root in this update, if any.
+ AXNode* new_root;
};
AXTreeDelegate::AXTreeDelegate() {
@@ -60,7 +65,7 @@ AXTree::AXTree(const AXTreeUpdate& initial_state)
AXTree::~AXTree() {
if (root_)
- DestroyNodeAndSubtree(root_);
+ DestroyNodeAndSubtree(root_, nullptr);
}
void AXTree::SetDelegate(AXTreeDelegate* delegate) {
@@ -84,11 +89,11 @@ bool AXTree::Unserialize(const AXTreeUpdate& update) {
return false;
}
if (node == root_) {
- DestroySubtree(root_);
+ DestroySubtree(root_, &update_state);
root_ = NULL;
} else {
for (int i = 0; i < node->child_count(); ++i)
- DestroySubtree(node->ChildAtIndex(i));
+ DestroySubtree(node->ChildAtIndex(i), &update_state);
std::vector<AXNode*> children;
node->SwapChildren(children);
update_state.pending_nodes.insert(node);
@@ -156,7 +161,6 @@ bool AXTree::UpdateNode(const AXNodeData& src,
// of the tree is being swapped, or we're out of sync with the source
// and this is a serious error.
AXNode* node = GetFromId(src.id);
- AXNode* new_root = NULL;
if (node) {
update_state->pending_nodes.erase(node);
node->SetData(src);
@@ -166,8 +170,13 @@ bool AXTree::UpdateNode(const AXNodeData& src,
"%d is not in the tree and not the new root", src.id);
return false;
}
- new_root = CreateNode(NULL, src.id, 0);
- node = new_root;
+ if (update_state->new_root) {
+ error_ = "Tree update contains two new roots";
+ return false;
+ }
+
+ update_state->new_root = CreateNode(NULL, src.id, 0);
+ node = update_state->new_root;
update_state->new_nodes.insert(node);
node->SetData(src);
}
@@ -177,9 +186,9 @@ bool AXTree::UpdateNode(const AXNodeData& src,
// First, delete nodes that used to be children of this node but aren't
// anymore.
- if (!DeleteOldChildren(node, src.child_ids)) {
- if (new_root)
- DestroySubtree(new_root);
+ if (!DeleteOldChildren(node, src.child_ids, update_state)) {
+ if (update_state->new_root)
+ DestroySubtree(update_state->new_root, update_state);
return false;
}
@@ -194,30 +203,36 @@ bool AXTree::UpdateNode(const AXNodeData& src,
if (src.role == AX_ROLE_ROOT_WEB_AREA &&
(!root_ || root_->id() != src.id)) {
if (root_)
- DestroySubtree(root_);
+ DestroySubtree(root_, update_state);
root_ = node;
}
return success;
}
-void AXTree::DestroySubtree(AXNode* node) {
+void AXTree::DestroySubtree(AXNode* node,
+ AXTreeUpdateState* update_state) {
if (delegate_)
delegate_->OnSubtreeWillBeDeleted(node);
- DestroyNodeAndSubtree(node);
+ DestroyNodeAndSubtree(node, update_state);
}
-void AXTree::DestroyNodeAndSubtree(AXNode* node) {
+void AXTree::DestroyNodeAndSubtree(AXNode* node,
+ AXTreeUpdateState* update_state) {
id_map_.erase(node->id());
for (int i = 0; i < node->child_count(); ++i)
- DestroyNodeAndSubtree(node->ChildAtIndex(i));
+ DestroyNodeAndSubtree(node->ChildAtIndex(i), update_state);
if (delegate_)
delegate_->OnNodeWillBeDeleted(node);
+ if (update_state) {
+ update_state->pending_nodes.erase(node);
+ }
node->Destroy();
}
bool AXTree::DeleteOldChildren(AXNode* node,
- const std::vector<int32>& new_child_ids) {
+ const std::vector<int32>& new_child_ids,
+ AXTreeUpdateState* update_state) {
// Create a set of child ids in |src| for fast lookup, and return false
// if a duplicate is found;
std::set<int32> new_child_id_set;
@@ -235,7 +250,7 @@ bool AXTree::DeleteOldChildren(AXNode* node,
for (size_t i = 0; i < old_children.size(); ++i) {
int old_id = old_children[i]->id();
if (new_child_id_set.find(old_id) == new_child_id_set.end())
- DestroySubtree(old_children[i]);
+ DestroySubtree(old_children[i], update_state);
}
return true;
« no previous file with comments | « ui/accessibility/ax_tree.h ('k') | ui/accessibility/ax_tree_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698