Index: ui/accessibility/ax_tree.cc |
diff --git a/ui/accessibility/ax_tree.cc b/ui/accessibility/ax_tree.cc |
index f4be46059453fa219f5dc61d4491d26c04433214..761e21d3ad905ccf259a5be229e5b7d0fd2eb178 100644 |
--- a/ui/accessibility/ax_tree.cc |
+++ b/ui/accessibility/ax_tree.cc |
@@ -36,6 +36,12 @@ struct AXTreeUpdateState { |
// end of Unserialize. |
std::set<AXNode*> pending_nodes; |
+ // This is similar to above, but we store node ids here because this list gets |
+ // generated before any nodes get created or re-used. Its purpose is to allow |
+ // us to know what nodes will be updated so we can make more intelligent |
+ // decisions about when to notify delegates of removals or reparenting. |
+ std::set<int> changed_node_ids; |
+ |
// Keeps track of new nodes created during this update. |
std::set<AXNode*> new_nodes; |
@@ -92,6 +98,14 @@ bool AXTree::Unserialize(const AXTreeUpdate& update) { |
AXTreeUpdateState update_state; |
int32_t old_root_id = root_ ? root_->id() : 0; |
+ // First, make a note of any nodes we will touch as part of this update |
+ // including implicitly via parent/child relationships. |
+ for (size_t i = 0; i < update.nodes.size(); ++i) { |
+ update_state.changed_node_ids.insert(update.nodes[i].id); |
+ for (size_t j = 0; j < update.nodes[i].child_ids.size(); ++j) |
+ update_state.changed_node_ids.insert(update.nodes[i].child_ids[j]); |
+ } |
+ |
if (update.has_tree_data) |
UpdateData(update.tree_data); |
@@ -247,14 +261,18 @@ bool AXTree::UpdateNode(const AXNodeData& src, |
void AXTree::DestroySubtree(AXNode* node, |
AXTreeUpdateState* update_state) { |
- if (delegate_) |
+ if (delegate_ && (!update_state || |
dmazzoni
2016/09/06 22:49:44
I don't think we support |update_state| being null
David Tseng
2016/09/07 16:37:01
Alright, done, DestroySubtree only gets called fro
|
+ update_state->changed_node_ids.find(node->id()) == |
+ update_state->changed_node_ids.end())) |
delegate_->OnSubtreeWillBeDeleted(this, node); |
DestroyNodeAndSubtree(node, update_state); |
} |
void AXTree::DestroyNodeAndSubtree(AXNode* node, |
AXTreeUpdateState* update_state) { |
- if (delegate_) |
+ if (delegate_ && (!update_state || |
+ update_state->changed_node_ids.find(node->id()) == |
+ update_state->changed_node_ids.end())) |
delegate_->OnNodeWillBeDeleted(this, node); |
id_map_.erase(node->id()); |
for (int i = 0; i < node->child_count(); ++i) |