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 #ifndef UI_ACCESSIBILITY_AX_TREE_SERIALIZER_H_ | 5 #ifndef UI_ACCESSIBILITY_AX_TREE_SERIALIZER_H_ |
6 #define UI_ACCESSIBILITY_AX_TREE_SERIALIZER_H_ | 6 #define UI_ACCESSIBILITY_AX_TREE_SERIALIZER_H_ |
7 | 7 |
8 #include <set> | 8 #include <set> |
9 | 9 |
10 #include "base/containers/hash_tables.h" | 10 #include "base/containers/hash_tables.h" |
(...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
165 client_root_(NULL) { | 165 client_root_(NULL) { |
166 } | 166 } |
167 | 167 |
168 template<typename AXSourceNode> | 168 template<typename AXSourceNode> |
169 AXTreeSerializer<AXSourceNode>::~AXTreeSerializer() { | 169 AXTreeSerializer<AXSourceNode>::~AXTreeSerializer() { |
170 Reset(); | 170 Reset(); |
171 } | 171 } |
172 | 172 |
173 template<typename AXSourceNode> | 173 template<typename AXSourceNode> |
174 void AXTreeSerializer<AXSourceNode>::Reset() { | 174 void AXTreeSerializer<AXSourceNode>::Reset() { |
175 if (client_root_) { | 175 if (!client_root_) |
176 DeleteClientSubtree(client_root_); | 176 return; |
177 client_root_ = NULL; | 177 |
178 } | 178 DeleteClientSubtree(client_root_); |
| 179 client_id_map_.erase(client_root_->id); |
| 180 delete client_root_; |
| 181 client_root_ = NULL; |
179 } | 182 } |
180 | 183 |
181 template<typename AXSourceNode> | 184 template<typename AXSourceNode> |
182 void AXTreeSerializer<AXSourceNode>::ChangeTreeSourceForTesting( | 185 void AXTreeSerializer<AXSourceNode>::ChangeTreeSourceForTesting( |
183 AXTreeSource<AXSourceNode>* new_tree) { | 186 AXTreeSource<AXSourceNode>* new_tree) { |
184 tree_ = new_tree; | 187 tree_ = new_tree; |
185 } | 188 } |
186 | 189 |
187 template<typename AXSourceNode> | 190 template<typename AXSourceNode> |
188 AXSourceNode AXTreeSerializer<AXSourceNode>::LeastCommonAncestor( | 191 AXSourceNode AXTreeSerializer<AXSourceNode>::LeastCommonAncestor( |
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
298 // any, we need to delete and reserialize the whole subtree | 301 // any, we need to delete and reserialize the whole subtree |
299 // that contains the old and new parents of the reparented node. | 302 // that contains the old and new parents of the reparented node. |
300 if (AnyDescendantWasReparented(lca, &lca)) | 303 if (AnyDescendantWasReparented(lca, &lca)) |
301 need_delete = true; | 304 need_delete = true; |
302 } | 305 } |
303 | 306 |
304 if (!tree_->IsValid(lca)) { | 307 if (!tree_->IsValid(lca)) { |
305 // If there's no LCA, just tell the client to destroy the whole | 308 // If there's no LCA, just tell the client to destroy the whole |
306 // tree and then we'll serialize everything from the new root. | 309 // tree and then we'll serialize everything from the new root. |
307 out_update->node_id_to_clear = client_root_->id; | 310 out_update->node_id_to_clear = client_root_->id; |
308 DeleteClientSubtree(client_root_); | 311 Reset(); |
309 client_id_map_.erase(client_root_->id); | |
310 client_root_ = NULL; | |
311 } else if (need_delete) { | 312 } else if (need_delete) { |
312 // Otherwise, if we need to reserialize a subtree, first we need | 313 // Otherwise, if we need to reserialize a subtree, first we need |
313 // to delete those nodes in our client tree so that | 314 // to delete those nodes in our client tree so that |
314 // SerializeChangedNodes() will be sure to send them again. | 315 // SerializeChangedNodes() will be sure to send them again. |
315 out_update->node_id_to_clear = tree_->GetId(lca); | 316 out_update->node_id_to_clear = tree_->GetId(lca); |
316 ClientTreeNode* client_lca = ClientTreeNodeById(tree_->GetId(lca)); | 317 ClientTreeNode* client_lca = ClientTreeNodeById(tree_->GetId(lca)); |
317 CHECK(client_lca); | 318 CHECK(client_lca); |
318 for (size_t i = 0; i < client_lca->children.size(); ++i) { | 319 for (size_t i = 0; i < client_lca->children.size(); ++i) { |
319 client_id_map_.erase(client_lca->children[i]->id); | 320 client_id_map_.erase(client_lca->children[i]->id); |
320 DeleteClientSubtree(client_lca->children[i]); | 321 DeleteClientSubtree(client_lca->children[i]); |
| 322 delete client_lca->children[i]; |
321 } | 323 } |
322 client_lca->children.clear(); | 324 client_lca->children.clear(); |
323 } | 325 } |
324 } | 326 } |
325 | 327 |
326 // Serialize from the LCA, or from the root if there isn't one. | 328 // Serialize from the LCA, or from the root if there isn't one. |
327 if (!tree_->IsValid(lca)) | 329 if (!tree_->IsValid(lca)) |
328 lca = tree_->GetRoot(); | 330 lca = tree_->GetRoot(); |
329 SerializeChangedNodes(lca, out_update); | 331 SerializeChangedNodes(lca, out_update); |
330 } | 332 } |
331 | 333 |
332 template<typename AXSourceNode> | 334 template<typename AXSourceNode> |
333 void AXTreeSerializer<AXSourceNode>::DeleteClientSubtree(AXSourceNode node) { | 335 void AXTreeSerializer<AXSourceNode>::DeleteClientSubtree(AXSourceNode node) { |
334 ClientTreeNode* client_node = ClientTreeNodeById(tree_->GetId(node)); | 336 ClientTreeNode* client_node = ClientTreeNodeById(tree_->GetId(node)); |
335 if (client_node) | 337 if (client_node) |
336 DeleteClientSubtree(client_node); | 338 DeleteClientSubtree(client_node); |
337 } | 339 } |
338 | 340 |
339 template<typename AXSourceNode> | 341 template<typename AXSourceNode> |
340 void AXTreeSerializer<AXSourceNode>::DeleteClientSubtree( | 342 void AXTreeSerializer<AXSourceNode>::DeleteClientSubtree( |
341 ClientTreeNode* client_node) { | 343 ClientTreeNode* client_node) { |
342 for (size_t i = 0; i < client_node->children.size(); ++i) { | 344 for (size_t i = 0; i < client_node->children.size(); ++i) { |
343 client_id_map_.erase(client_node->children[i]->id); | 345 client_id_map_.erase(client_node->children[i]->id); |
344 DeleteClientSubtree(client_node->children[i]); | 346 DeleteClientSubtree(client_node->children[i]); |
| 347 delete client_node->children[i]; |
345 } | 348 } |
346 client_node->children.clear(); | 349 client_node->children.clear(); |
347 } | 350 } |
348 | 351 |
349 template<typename AXSourceNode> | 352 template<typename AXSourceNode> |
350 void AXTreeSerializer<AXSourceNode>::SerializeChangedNodes( | 353 void AXTreeSerializer<AXSourceNode>::SerializeChangedNodes( |
351 AXSourceNode node, | 354 AXSourceNode node, |
352 AXTreeUpdate* out_update) { | 355 AXTreeUpdate* out_update) { |
353 // This method has three responsibilities: | 356 // This method has three responsibilities: |
354 // 1. Serialize |node| into an AXNodeData, and append it to | 357 // 1. Serialize |node| into an AXNodeData, and append it to |
355 // the AXTreeUpdate to be sent to the client. | 358 // the AXTreeUpdate to be sent to the client. |
356 // 2. Determine if |node| has any new children that the client doesn't | 359 // 2. Determine if |node| has any new children that the client doesn't |
357 // know about yet, and call SerializeChangedNodes recursively on those. | 360 // know about yet, and call SerializeChangedNodes recursively on those. |
358 // 3. Update our internal data structure that keeps track of what nodes | 361 // 3. Update our internal data structure that keeps track of what nodes |
359 // the client knows about. | 362 // the client knows about. |
360 | 363 |
361 // First, find the ClientTreeNode for this id in our data structure where | 364 // First, find the ClientTreeNode for this id in our data structure where |
362 // we keep track of what accessibility objects the client already knows | 365 // we keep track of what accessibility objects the client already knows |
363 // about. If we don't find it, then this must be the new root of the | 366 // about. If we don't find it, then this must be the new root of the |
364 // accessibility tree. | 367 // accessibility tree. |
365 int id = tree_->GetId(node); | 368 int id = tree_->GetId(node); |
366 ClientTreeNode* client_node = ClientTreeNodeById(id); | 369 ClientTreeNode* client_node = ClientTreeNodeById(id); |
367 if (!client_node) { | 370 if (!client_node) { |
368 if (client_root_) { | 371 Reset(); |
369 client_id_map_.erase(client_root_->id); | |
370 DeleteClientSubtree(client_root_); | |
371 } | |
372 client_root_ = new ClientTreeNode(); | 372 client_root_ = new ClientTreeNode(); |
373 client_node = client_root_; | 373 client_node = client_root_; |
374 client_node->id = id; | 374 client_node->id = id; |
375 client_node->parent = NULL; | 375 client_node->parent = NULL; |
376 client_id_map_[client_node->id] = client_node; | 376 client_id_map_[client_node->id] = client_node; |
377 } | 377 } |
378 | 378 |
379 // Iterate over the ids of the children of |node|. | 379 // Iterate over the ids of the children of |node|. |
380 // Create a set of the child ids so we can quickly look | 380 // Create a set of the child ids so we can quickly look |
381 // up which children are new and which ones were there before. | 381 // up which children are new and which ones were there before. |
(...skipping 19 matching lines...) Expand all Loading... |
401 // of an update, which can lead to a double-free. | 401 // of an update, which can lead to a double-free. |
402 base::hash_map<int32, ClientTreeNode*> client_child_id_map; | 402 base::hash_map<int32, ClientTreeNode*> client_child_id_map; |
403 std::vector<ClientTreeNode*> old_children; | 403 std::vector<ClientTreeNode*> old_children; |
404 old_children.swap(client_node->children); | 404 old_children.swap(client_node->children); |
405 for (size_t i = 0; i < old_children.size(); ++i) { | 405 for (size_t i = 0; i < old_children.size(); ++i) { |
406 ClientTreeNode* old_child = old_children[i]; | 406 ClientTreeNode* old_child = old_children[i]; |
407 int old_child_id = old_child->id; | 407 int old_child_id = old_child->id; |
408 if (new_child_ids.find(old_child_id) == new_child_ids.end()) { | 408 if (new_child_ids.find(old_child_id) == new_child_ids.end()) { |
409 client_id_map_.erase(old_child_id); | 409 client_id_map_.erase(old_child_id); |
410 DeleteClientSubtree(old_child); | 410 DeleteClientSubtree(old_child); |
| 411 delete old_child; |
411 } else { | 412 } else { |
412 client_child_id_map[old_child_id] = old_child; | 413 client_child_id_map[old_child_id] = old_child; |
413 } | 414 } |
414 } | 415 } |
415 | 416 |
416 // Serialize this node. This fills in all of the fields in | 417 // Serialize this node. This fills in all of the fields in |
417 // AXNodeData except child_ids, which we handle below. | 418 // AXNodeData except child_ids, which we handle below. |
418 out_update->nodes.push_back(AXNodeData()); | 419 out_update->nodes.push_back(AXNodeData()); |
419 AXNodeData* serialized_node = &out_update->nodes.back(); | 420 AXNodeData* serialized_node = &out_update->nodes.back(); |
420 tree_->SerializeNode(node, serialized_node); | 421 tree_->SerializeNode(node, serialized_node); |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
452 } | 453 } |
453 | 454 |
454 // Serialize all of the new children, recursively. | 455 // Serialize all of the new children, recursively. |
455 for (size_t i = 0; i < children_to_serialize.size(); ++i) | 456 for (size_t i = 0; i < children_to_serialize.size(); ++i) |
456 SerializeChangedNodes(children_to_serialize[i], out_update); | 457 SerializeChangedNodes(children_to_serialize[i], out_update); |
457 } | 458 } |
458 | 459 |
459 } // namespace ui | 460 } // namespace ui |
460 | 461 |
461 #endif // UI_ACCESSIBILITY_AX_TREE_SERIALIZER_H_ | 462 #endif // UI_ACCESSIBILITY_AX_TREE_SERIALIZER_H_ |
OLD | NEW |