| 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 |