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 <set> | 7 #include <set> |
8 | 8 |
9 #include "base/logging.h" | 9 #include "base/logging.h" |
10 #include "base/strings/stringprintf.h" | 10 #include "base/strings/stringprintf.h" |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
81 int32 old_root_id = root_ ? root_->id() : 0; | 81 int32 old_root_id = root_ ? root_->id() : 0; |
82 | 82 |
83 if (update.node_id_to_clear != 0) { | 83 if (update.node_id_to_clear != 0) { |
84 AXNode* node = GetFromId(update.node_id_to_clear); | 84 AXNode* node = GetFromId(update.node_id_to_clear); |
85 if (!node) { | 85 if (!node) { |
86 error_ = base::StringPrintf("Bad node_id_to_clear: %d", | 86 error_ = base::StringPrintf("Bad node_id_to_clear: %d", |
87 update.node_id_to_clear); | 87 update.node_id_to_clear); |
88 return false; | 88 return false; |
89 } | 89 } |
90 if (node == root_) { | 90 if (node == root_) { |
91 DestroyNodeAndSubtree(root_); | 91 DestroySubtree(root_); |
92 root_ = NULL; | 92 root_ = NULL; |
93 } else { | 93 } else { |
94 for (int i = 0; i < node->child_count(); ++i) | 94 for (int i = 0; i < node->child_count(); ++i) |
95 DestroyNodeAndSubtree(node->ChildAtIndex(i)); | 95 DestroySubtree(node->ChildAtIndex(i)); |
96 std::vector<AXNode*> children; | 96 std::vector<AXNode*> children; |
97 node->SwapChildren(children); | 97 node->SwapChildren(children); |
98 update_state.pending_nodes.insert(node); | 98 update_state.pending_nodes.insert(node); |
99 } | 99 } |
100 } | 100 } |
101 | 101 |
102 for (size_t i = 0; i < update.nodes.size(); ++i) { | 102 for (size_t i = 0; i < update.nodes.size(); ++i) { |
103 if (!UpdateNode(update.nodes[i], &update_state)) | 103 if (!UpdateNode(update.nodes[i], &update_state)) |
104 return false; | 104 return false; |
105 } | 105 } |
106 | 106 |
107 if (!update_state.pending_nodes.empty()) { | 107 if (!update_state.pending_nodes.empty()) { |
108 error_ = "Nodes left pending by the update:"; | 108 error_ = "Nodes left pending by the update:"; |
109 for (std::set<AXNode*>::iterator iter = update_state.pending_nodes.begin(); | 109 for (std::set<AXNode*>::iterator iter = update_state.pending_nodes.begin(); |
110 iter != update_state.pending_nodes.end(); ++iter) { | 110 iter != update_state.pending_nodes.end(); ++iter) { |
111 error_ += base::StringPrintf(" %d", (*iter)->id()); | 111 error_ += base::StringPrintf(" %d", (*iter)->id()); |
112 } | 112 } |
113 return false; | 113 return false; |
114 } | 114 } |
115 | 115 |
116 if (delegate_) { | 116 if (delegate_) { |
| 117 std::set<AXNode*>& new_nodes = update_state.new_nodes; |
| 118 std::vector<AXTreeDelegate::Change> changes; |
| 119 changes.reserve(update.nodes.size()); |
117 for (size_t i = 0; i < update.nodes.size(); ++i) { | 120 for (size_t i = 0; i < update.nodes.size(); ++i) { |
118 AXNode* node = GetFromId(update.nodes[i].id); | 121 AXNode* node = GetFromId(update.nodes[i].id); |
119 if (update_state.new_nodes.find(node) != update_state.new_nodes.end()) { | 122 if (new_nodes.find(node) != new_nodes.end()) { |
120 delegate_->OnNodeCreationFinished(node); | 123 if (new_nodes.find(node->parent()) == new_nodes.end()) { |
121 update_state.new_nodes.erase(node); | 124 changes.push_back( |
| 125 AXTreeDelegate::Change(node, AXTreeDelegate::SUBTREE_CREATED)); |
| 126 } else { |
| 127 changes.push_back( |
| 128 AXTreeDelegate::Change(node, AXTreeDelegate::NODE_CREATED)); |
| 129 } |
122 } else { | 130 } else { |
123 delegate_->OnNodeChangeFinished(node); | 131 changes.push_back( |
| 132 AXTreeDelegate::Change(node, AXTreeDelegate::NODE_CHANGED)); |
124 } | 133 } |
125 } | 134 } |
126 if (root_->id() != old_root_id) | 135 delegate_->OnAtomicUpdateFinished(root_->id() != old_root_id, changes); |
127 delegate_->OnRootChanged(root_); | |
128 } | 136 } |
129 | 137 |
130 return true; | 138 return true; |
131 } | 139 } |
132 | 140 |
133 std::string AXTree::ToString() const { | 141 std::string AXTree::ToString() const { |
134 return TreeToStringHelper(root_, 0); | 142 return TreeToStringHelper(root_, 0); |
135 } | 143 } |
136 | 144 |
137 AXNode* AXTree::CreateNode( | 145 AXNode* AXTree::CreateNode( |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
169 node->SetData(src); | 177 node->SetData(src); |
170 } | 178 } |
171 | 179 |
172 if (delegate_) | 180 if (delegate_) |
173 delegate_->OnNodeChanged(node); | 181 delegate_->OnNodeChanged(node); |
174 | 182 |
175 // First, delete nodes that used to be children of this node but aren't | 183 // First, delete nodes that used to be children of this node but aren't |
176 // anymore. | 184 // anymore. |
177 if (!DeleteOldChildren(node, src.child_ids)) { | 185 if (!DeleteOldChildren(node, src.child_ids)) { |
178 if (new_root) | 186 if (new_root) |
179 DestroyNodeAndSubtree(new_root); | 187 DestroySubtree(new_root); |
180 return false; | 188 return false; |
181 } | 189 } |
182 | 190 |
183 // Now build a new children vector, reusing nodes when possible, | 191 // Now build a new children vector, reusing nodes when possible, |
184 // and swap it in. | 192 // and swap it in. |
185 std::vector<AXNode*> new_children; | 193 std::vector<AXNode*> new_children; |
186 bool success = CreateNewChildVector( | 194 bool success = CreateNewChildVector( |
187 node, src.child_ids, &new_children, update_state); | 195 node, src.child_ids, &new_children, update_state); |
188 node->SwapChildren(new_children); | 196 node->SwapChildren(new_children); |
189 | 197 |
190 // Update the root of the tree if needed. | 198 // Update the root of the tree if needed. |
191 if (src.role == AX_ROLE_ROOT_WEB_AREA && | 199 if (src.role == AX_ROLE_ROOT_WEB_AREA && |
192 (!root_ || root_->id() != src.id)) { | 200 (!root_ || root_->id() != src.id)) { |
193 if (root_) | 201 if (root_) |
194 DestroyNodeAndSubtree(root_); | 202 DestroySubtree(root_); |
195 root_ = node; | 203 root_ = node; |
196 } | 204 } |
197 | 205 |
198 return success; | 206 return success; |
199 } | 207 } |
200 | 208 |
| 209 void AXTree::DestroySubtree(AXNode* node) { |
| 210 if (delegate_) |
| 211 delegate_->OnSubtreeWillBeDeleted(node); |
| 212 DestroyNodeAndSubtree(node); |
| 213 } |
| 214 |
201 void AXTree::DestroyNodeAndSubtree(AXNode* node) { | 215 void AXTree::DestroyNodeAndSubtree(AXNode* node) { |
202 id_map_.erase(node->id()); | 216 id_map_.erase(node->id()); |
203 for (int i = 0; i < node->child_count(); ++i) | 217 for (int i = 0; i < node->child_count(); ++i) |
204 DestroyNodeAndSubtree(node->ChildAtIndex(i)); | 218 DestroyNodeAndSubtree(node->ChildAtIndex(i)); |
205 if (delegate_) | 219 if (delegate_) |
206 delegate_->OnNodeWillBeDeleted(node); | 220 delegate_->OnNodeWillBeDeleted(node); |
207 node->Destroy(); | 221 node->Destroy(); |
208 } | 222 } |
209 | 223 |
210 bool AXTree::DeleteOldChildren(AXNode* node, | 224 bool AXTree::DeleteOldChildren(AXNode* node, |
211 const std::vector<int32> new_child_ids) { | 225 const std::vector<int32> new_child_ids) { |
212 // Create a set of child ids in |src| for fast lookup, and return false | 226 // Create a set of child ids in |src| for fast lookup, and return false |
213 // if a duplicate is found; | 227 // if a duplicate is found; |
214 std::set<int32> new_child_id_set; | 228 std::set<int32> new_child_id_set; |
215 for (size_t i = 0; i < new_child_ids.size(); ++i) { | 229 for (size_t i = 0; i < new_child_ids.size(); ++i) { |
216 if (new_child_id_set.find(new_child_ids[i]) != new_child_id_set.end()) { | 230 if (new_child_id_set.find(new_child_ids[i]) != new_child_id_set.end()) { |
217 error_ = base::StringPrintf("Node %d has duplicate child id %d", | 231 error_ = base::StringPrintf("Node %d has duplicate child id %d", |
218 node->id(), new_child_ids[i]); | 232 node->id(), new_child_ids[i]); |
219 return false; | 233 return false; |
220 } | 234 } |
221 new_child_id_set.insert(new_child_ids[i]); | 235 new_child_id_set.insert(new_child_ids[i]); |
222 } | 236 } |
223 | 237 |
224 // Delete the old children. | 238 // Delete the old children. |
225 const std::vector<AXNode*>& old_children = node->children(); | 239 const std::vector<AXNode*>& old_children = node->children(); |
226 for (size_t i = 0; i < old_children.size(); ++i) { | 240 for (size_t i = 0; i < old_children.size(); ++i) { |
227 int old_id = old_children[i]->id(); | 241 int old_id = old_children[i]->id(); |
228 if (new_child_id_set.find(old_id) == new_child_id_set.end()) | 242 if (new_child_id_set.find(old_id) == new_child_id_set.end()) |
229 DestroyNodeAndSubtree(old_children[i]); | 243 DestroySubtree(old_children[i]); |
230 } | 244 } |
231 | 245 |
232 return true; | 246 return true; |
233 } | 247 } |
234 | 248 |
235 bool AXTree::CreateNewChildVector(AXNode* node, | 249 bool AXTree::CreateNewChildVector(AXNode* node, |
236 const std::vector<int32> new_child_ids, | 250 const std::vector<int32> new_child_ids, |
237 std::vector<AXNode*>* new_children, | 251 std::vector<AXNode*>* new_children, |
238 AXTreeUpdateState* update_state) { | 252 AXTreeUpdateState* update_state) { |
239 bool success = true; | 253 bool success = true; |
(...skipping 20 matching lines...) Expand all Loading... |
260 update_state->pending_nodes.insert(child); | 274 update_state->pending_nodes.insert(child); |
261 update_state->new_nodes.insert(child); | 275 update_state->new_nodes.insert(child); |
262 } | 276 } |
263 new_children->push_back(child); | 277 new_children->push_back(child); |
264 } | 278 } |
265 | 279 |
266 return success; | 280 return success; |
267 } | 281 } |
268 | 282 |
269 } // namespace ui | 283 } // namespace ui |
OLD | NEW |