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 399 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
410 client_id_map_.erase(old_child_id); | 410 client_id_map_.erase(old_child_id); |
411 DeleteClientSubtree(old_child); | 411 DeleteClientSubtree(old_child); |
412 delete old_child; | 412 delete old_child; |
413 } else { | 413 } else { |
414 client_child_id_map[old_child_id] = old_child; | 414 client_child_id_map[old_child_id] = old_child; |
415 } | 415 } |
416 } | 416 } |
417 | 417 |
418 // Serialize this node. This fills in all of the fields in | 418 // Serialize this node. This fills in all of the fields in |
419 // AXNodeData except child_ids, which we handle below. | 419 // AXNodeData except child_ids, which we handle below. |
| 420 size_t serialized_node_index = out_update->nodes.size(); |
420 out_update->nodes.push_back(AXNodeData()); | 421 out_update->nodes.push_back(AXNodeData()); |
421 AXNodeData* serialized_node = &out_update->nodes.back(); | 422 { |
422 tree_->SerializeNode(node, serialized_node); | 423 // Take the address of an element in a vector only within a limited |
423 // TODO(dmazzoni/dtseng): Make the serializer not depend on roles to identify | 424 // scope because otherwise the pointer can become invalid if the |
424 // the root. | 425 // vector is resized. |
425 if (serialized_node->id == client_root_->id && | 426 AXNodeData* serialized_node = &out_update->nodes[serialized_node_index]; |
426 (serialized_node->role != AX_ROLE_ROOT_WEB_AREA && | 427 |
427 serialized_node->role != AX_ROLE_DESKTOP)) { | 428 tree_->SerializeNode(node, serialized_node); |
428 serialized_node->role = AX_ROLE_ROOT_WEB_AREA; | 429 // TODO(dmazzoni/dtseng): Make the serializer not depend on roles to |
| 430 // identify the root. |
| 431 if (serialized_node->id == client_root_->id && |
| 432 (serialized_node->role != AX_ROLE_ROOT_WEB_AREA && |
| 433 serialized_node->role != AX_ROLE_DESKTOP)) { |
| 434 serialized_node->role = AX_ROLE_ROOT_WEB_AREA; |
| 435 } |
429 } | 436 } |
430 serialized_node->child_ids.clear(); | |
431 | 437 |
432 // Iterate over the children, make note of the ones that are new | 438 // Iterate over the children, serialize them, and update the ClientTreeNode |
433 // and need to be serialized, and update the ClientTreeNode | |
434 // data structure to reflect the new tree. | 439 // data structure to reflect the new tree. |
435 std::vector<AXSourceNode> children_to_serialize; | 440 std::vector<int32> actual_serialized_node_child_ids; |
436 client_node->children.reserve(children.size()); | 441 client_node->children.reserve(children.size()); |
437 for (size_t i = 0; i < children.size(); ++i) { | 442 for (size_t i = 0; i < children.size(); ++i) { |
438 AXSourceNode& child = children[i]; | 443 AXSourceNode& child = children[i]; |
439 int child_id = tree_->GetId(child); | 444 int child_id = tree_->GetId(child); |
440 | 445 |
441 // No need to do anything more with children that aren't new; | 446 // Skip if the child isn't valid. |
442 // the client will reuse its existing object. | 447 if (!tree_->IsValid(child)) |
| 448 continue; |
| 449 |
| 450 // Skip if the same child is included more than once. |
443 if (new_child_ids.find(child_id) == new_child_ids.end()) | 451 if (new_child_ids.find(child_id) == new_child_ids.end()) |
444 continue; | 452 continue; |
445 | 453 |
446 new_child_ids.erase(child_id); | 454 new_child_ids.erase(child_id); |
447 serialized_node->child_ids.push_back(child_id); | 455 actual_serialized_node_child_ids.push_back(child_id); |
448 if (client_child_id_map.find(child_id) != client_child_id_map.end()) { | 456 if (client_child_id_map.find(child_id) != client_child_id_map.end()) { |
449 ClientTreeNode* reused_child = client_child_id_map[child_id]; | 457 ClientTreeNode* reused_child = client_child_id_map[child_id]; |
450 client_node->children.push_back(reused_child); | 458 client_node->children.push_back(reused_child); |
451 } else { | 459 } else { |
452 ClientTreeNode* new_child = new ClientTreeNode(); | 460 ClientTreeNode* new_child = new ClientTreeNode(); |
453 new_child->id = child_id; | 461 new_child->id = child_id; |
454 new_child->parent = client_node; | 462 new_child->parent = client_node; |
455 client_node->children.push_back(new_child); | 463 client_node->children.push_back(new_child); |
456 client_id_map_[child_id] = new_child; | 464 client_id_map_[child_id] = new_child; |
457 children_to_serialize.push_back(child); | 465 SerializeChangedNodes(child, out_update); |
458 } | 466 } |
459 } | 467 } |
460 | 468 |
461 // Serialize all of the new children, recursively. | 469 // Finally, update the child ids of this node to reflect the actual child |
462 for (size_t i = 0; i < children_to_serialize.size(); ++i) | 470 // ids that were valid during serialization. |
463 SerializeChangedNodes(children_to_serialize[i], out_update); | 471 out_update->nodes[serialized_node_index].child_ids.swap( |
| 472 actual_serialized_node_child_ids); |
464 } | 473 } |
465 | 474 |
466 } // namespace ui | 475 } // namespace ui |
467 | 476 |
468 #endif // UI_ACCESSIBILITY_AX_TREE_SERIALIZER_H_ | 477 #endif // UI_ACCESSIBILITY_AX_TREE_SERIALIZER_H_ |
OLD | NEW |