Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "ui/accessibility/ax_tree.h" | 5 #include "ui/accessibility/ax_tree.h" |
| 6 | 6 |
| 7 #include <stddef.h> | 7 #include <stddef.h> |
| 8 | 8 |
| 9 #include <set> | 9 #include <set> |
| 10 | 10 |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 29 // Intermediate state to keep track of during a tree update. | 29 // Intermediate state to keep track of during a tree update. |
| 30 struct AXTreeUpdateState { | 30 struct AXTreeUpdateState { |
| 31 AXTreeUpdateState() : new_root(nullptr) {} | 31 AXTreeUpdateState() : new_root(nullptr) {} |
| 32 | 32 |
| 33 // During an update, this keeps track of all nodes that have been | 33 // During an update, this keeps track of all nodes that have been |
| 34 // implicitly referenced as part of this update, but haven't been | 34 // implicitly referenced as part of this update, but haven't been |
| 35 // updated yet. It's an error if there are any pending nodes at the | 35 // updated yet. It's an error if there are any pending nodes at the |
| 36 // end of Unserialize. | 36 // end of Unserialize. |
| 37 std::set<AXNode*> pending_nodes; | 37 std::set<AXNode*> pending_nodes; |
| 38 | 38 |
| 39 // This is similar to above, but we store node ids here because this list gets | |
| 40 // generated before any nodes get created or re-used. Its purpose is to allow | |
| 41 // us to know what nodes will be updated so we can make more intelligent | |
| 42 // decisions about when to notify delegates of removals or reparenting. | |
| 43 std::set<int> changed_node_ids; | |
| 44 | |
| 39 // Keeps track of new nodes created during this update. | 45 // Keeps track of new nodes created during this update. |
| 40 std::set<AXNode*> new_nodes; | 46 std::set<AXNode*> new_nodes; |
| 41 | 47 |
| 42 // The new root in this update, if any. | 48 // The new root in this update, if any. |
| 43 AXNode* new_root; | 49 AXNode* new_root; |
| 44 | 50 |
| 45 // Keeps track of any nodes removed. Used to identify re-parented nodes. | 51 // Keeps track of any nodes removed. Used to identify re-parented nodes. |
| 46 std::set<int> removed_node_ids; | 52 std::set<int> removed_node_ids; |
| 47 }; | 53 }; |
| 48 | 54 |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 85 void AXTree::UpdateData(const AXTreeData& data) { | 91 void AXTree::UpdateData(const AXTreeData& data) { |
| 86 data_ = data; | 92 data_ = data; |
| 87 if (delegate_) | 93 if (delegate_) |
| 88 delegate_->OnTreeDataChanged(this); | 94 delegate_->OnTreeDataChanged(this); |
| 89 } | 95 } |
| 90 | 96 |
| 91 bool AXTree::Unserialize(const AXTreeUpdate& update) { | 97 bool AXTree::Unserialize(const AXTreeUpdate& update) { |
| 92 AXTreeUpdateState update_state; | 98 AXTreeUpdateState update_state; |
| 93 int32_t old_root_id = root_ ? root_->id() : 0; | 99 int32_t old_root_id = root_ ? root_->id() : 0; |
| 94 | 100 |
| 101 // First, make a note of any nodes we will touch as part of this update | |
| 102 // including implicitly via parent/child relationships. | |
| 103 for (size_t i = 0; i < update.nodes.size(); ++i) { | |
| 104 update_state.changed_node_ids.insert(update.nodes[i].id); | |
| 105 for (size_t j = 0; j < update.nodes[i].child_ids.size(); ++j) | |
| 106 update_state.changed_node_ids.insert(update.nodes[i].child_ids[j]); | |
| 107 } | |
| 108 | |
| 95 if (update.has_tree_data) | 109 if (update.has_tree_data) |
| 96 UpdateData(update.tree_data); | 110 UpdateData(update.tree_data); |
| 97 | 111 |
| 98 if (update.node_id_to_clear != 0) { | 112 if (update.node_id_to_clear != 0) { |
| 99 AXNode* node = GetFromId(update.node_id_to_clear); | 113 AXNode* node = GetFromId(update.node_id_to_clear); |
| 100 if (!node) { | 114 if (!node) { |
| 101 error_ = base::StringPrintf("Bad node_id_to_clear: %d", | 115 error_ = base::StringPrintf("Bad node_id_to_clear: %d", |
| 102 update.node_id_to_clear); | 116 update.node_id_to_clear); |
| 103 return false; | 117 return false; |
| 104 } | 118 } |
| (...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 240 root_ = node; | 254 root_ = node; |
| 241 if (old_root) | 255 if (old_root) |
| 242 DestroySubtree(old_root, update_state); | 256 DestroySubtree(old_root, update_state); |
| 243 } | 257 } |
| 244 | 258 |
| 245 return success; | 259 return success; |
| 246 } | 260 } |
| 247 | 261 |
| 248 void AXTree::DestroySubtree(AXNode* node, | 262 void AXTree::DestroySubtree(AXNode* node, |
| 249 AXTreeUpdateState* update_state) { | 263 AXTreeUpdateState* update_state) { |
| 250 if (delegate_) | 264 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
| |
| 265 update_state->changed_node_ids.find(node->id()) == | |
| 266 update_state->changed_node_ids.end())) | |
| 251 delegate_->OnSubtreeWillBeDeleted(this, node); | 267 delegate_->OnSubtreeWillBeDeleted(this, node); |
| 252 DestroyNodeAndSubtree(node, update_state); | 268 DestroyNodeAndSubtree(node, update_state); |
| 253 } | 269 } |
| 254 | 270 |
| 255 void AXTree::DestroyNodeAndSubtree(AXNode* node, | 271 void AXTree::DestroyNodeAndSubtree(AXNode* node, |
| 256 AXTreeUpdateState* update_state) { | 272 AXTreeUpdateState* update_state) { |
| 257 if (delegate_) | 273 if (delegate_ && (!update_state || |
| 274 update_state->changed_node_ids.find(node->id()) == | |
| 275 update_state->changed_node_ids.end())) | |
| 258 delegate_->OnNodeWillBeDeleted(this, node); | 276 delegate_->OnNodeWillBeDeleted(this, node); |
| 259 id_map_.erase(node->id()); | 277 id_map_.erase(node->id()); |
| 260 for (int i = 0; i < node->child_count(); ++i) | 278 for (int i = 0; i < node->child_count(); ++i) |
| 261 DestroyNodeAndSubtree(node->ChildAtIndex(i), update_state); | 279 DestroyNodeAndSubtree(node->ChildAtIndex(i), update_state); |
| 262 if (update_state) { | 280 if (update_state) { |
| 263 update_state->pending_nodes.erase(node); | 281 update_state->pending_nodes.erase(node); |
| 264 update_state->removed_node_ids.insert(node->id()); | 282 update_state->removed_node_ids.insert(node->id()); |
| 265 } | 283 } |
| 266 node->Destroy(); | 284 node->Destroy(); |
| 267 } | 285 } |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 320 update_state->pending_nodes.insert(child); | 338 update_state->pending_nodes.insert(child); |
| 321 update_state->new_nodes.insert(child); | 339 update_state->new_nodes.insert(child); |
| 322 } | 340 } |
| 323 new_children->push_back(child); | 341 new_children->push_back(child); |
| 324 } | 342 } |
| 325 | 343 |
| 326 return success; | 344 return success; |
| 327 } | 345 } |
| 328 | 346 |
| 329 } // namespace ui | 347 } // namespace ui |
| OLD | NEW |