| Index: ui/accessibility/ax_tree.cc
|
| diff --git a/ui/accessibility/ax_tree.cc b/ui/accessibility/ax_tree.cc
|
| index d07f239b79d9a292b1221239067b71ee2b715e03..c2fb44dd5625ddc2a23fc85b84a8b33d9cde548b 100644
|
| --- a/ui/accessibility/ax_tree.cc
|
| +++ b/ui/accessibility/ax_tree.cc
|
| @@ -89,8 +89,11 @@ bool AXTree::Unserialize(const AXTreeUpdate& update) {
|
| return false;
|
| }
|
| if (node == root_) {
|
| - DestroySubtree(root_, &update_state);
|
| - root_ = NULL;
|
| + // Clear root_ before calling DestroySubtree so that root_ doesn't
|
| + // ever point to an invalid node.
|
| + AXNode* old_root = root_;
|
| + root_ = nullptr;
|
| + DestroySubtree(old_root, &update_state);
|
| } else {
|
| for (int i = 0; i < node->child_count(); ++i)
|
| DestroySubtree(node->ChildAtIndex(i), &update_state);
|
| @@ -204,9 +207,12 @@ bool AXTree::UpdateNode(const AXNodeData& src,
|
| // Update the root of the tree if needed.
|
| if ((src.role == AX_ROLE_ROOT_WEB_AREA || src.role == AX_ROLE_DESKTOP) &&
|
| (!root_ || root_->id() != src.id)) {
|
| - if (root_)
|
| - DestroySubtree(root_, update_state);
|
| + // Make sure root_ always points to something valid or null_, even inside
|
| + // DestroySubtree.
|
| + AXNode* old_root = root_;
|
| root_ = node;
|
| + if (old_root)
|
| + DestroySubtree(old_root, update_state);
|
| }
|
|
|
| return success;
|
| @@ -221,11 +227,11 @@ void AXTree::DestroySubtree(AXNode* node,
|
|
|
| void AXTree::DestroyNodeAndSubtree(AXNode* node,
|
| AXTreeUpdateState* update_state) {
|
| + if (delegate_)
|
| + delegate_->OnNodeWillBeDeleted(this, node);
|
| id_map_.erase(node->id());
|
| for (int i = 0; i < node->child_count(); ++i)
|
| DestroyNodeAndSubtree(node->ChildAtIndex(i), update_state);
|
| - if (delegate_)
|
| - delegate_->OnNodeWillBeDeleted(this, node);
|
| if (update_state) {
|
| update_state->pending_nodes.erase(node);
|
| }
|
|
|