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 |