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 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
106 root_ = nullptr; | 106 root_ = nullptr; |
107 DestroySubtree(old_root, &update_state); | 107 DestroySubtree(old_root, &update_state); |
108 } else { | 108 } else { |
109 for (int i = 0; i < node->child_count(); ++i) | 109 for (int i = 0; i < node->child_count(); ++i) |
110 DestroySubtree(node->ChildAtIndex(i), &update_state); | 110 DestroySubtree(node->ChildAtIndex(i), &update_state); |
111 std::vector<AXNode*> children; | 111 std::vector<AXNode*> children; |
112 node->SwapChildren(children); | 112 node->SwapChildren(children); |
113 update_state.pending_nodes.insert(node); | 113 update_state.pending_nodes.insert(node); |
114 } | 114 } |
115 } | 115 } |
116 std::set<int> node_created_ids; | |
117 std::set<int> text_changed_ids; | |
118 for (size_t i = 0; i < update.nodes.size(); ++i) { | |
119 AXNode* original_node = GetFromId(update.nodes[i].id); | |
120 std::string original_text; | |
121 if (original_node) | |
122 original_text = original_node->data().GetStringAttribute(AX_ATTR_NAME); | |
116 | 123 |
117 for (size_t i = 0; i < update.nodes.size(); ++i) { | |
118 if (!UpdateNode(update.nodes[i], &update_state)) | 124 if (!UpdateNode(update.nodes[i], &update_state)) |
119 return false; | 125 return false; |
126 | |
127 AXNode* updated_node = GetFromId(update.nodes[i].id); | |
128 std::string updated_text; | |
129 if (updated_node) | |
130 updated_text = updated_node->data().GetStringAttribute(AX_ATTR_NAME); | |
131 if (!original_node && updated_node) | |
132 node_created_ids.insert(update.nodes[i].id); | |
133 if (!original_text.empty() && !updated_text.empty() && | |
134 updated_text != original_text) { | |
135 text_changed_ids.insert(update.nodes[i].id); | |
136 } | |
120 } | 137 } |
121 | 138 |
122 if (!update_state.pending_nodes.empty()) { | 139 if (!update_state.pending_nodes.empty()) { |
123 error_ = "Nodes left pending by the update:"; | 140 error_ = "Nodes left pending by the update:"; |
124 for (std::set<AXNode*>::iterator iter = update_state.pending_nodes.begin(); | 141 for (std::set<AXNode*>::iterator iter = update_state.pending_nodes.begin(); |
125 iter != update_state.pending_nodes.end(); ++iter) { | 142 iter != update_state.pending_nodes.end(); ++iter) { |
126 error_ += base::StringPrintf(" %d", (*iter)->id()); | 143 error_ += base::StringPrintf(" %d", (*iter)->id()); |
127 } | 144 } |
128 return false; | 145 return false; |
129 } | 146 } |
130 | 147 |
131 if (delegate_) { | 148 if (delegate_) { |
132 std::set<AXNode*>& new_nodes = update_state.new_nodes; | 149 std::set<AXNode*>& new_nodes = update_state.new_nodes; |
133 std::vector<AXTreeDelegate::Change> changes; | 150 std::vector<AXTreeDelegate::Change> changes; |
134 changes.reserve(update.nodes.size()); | 151 changes.reserve(update.nodes.size()); |
135 for (size_t i = 0; i < update.nodes.size(); ++i) { | 152 for (size_t i = 0; i < update.nodes.size(); ++i) { |
136 AXNode* node = GetFromId(update.nodes[i].id); | 153 AXNode* node = GetFromId(update.nodes[i].id); |
137 if (new_nodes.find(node) != new_nodes.end()) { | 154 if (new_nodes.find(node) != new_nodes.end()) { |
138 if (new_nodes.find(node->parent()) == new_nodes.end()) { | 155 if (new_nodes.find(node->parent()) == new_nodes.end()) { |
139 changes.push_back( | 156 changes.push_back( |
140 AXTreeDelegate::Change(node, AXTreeDelegate::SUBTREE_CREATED)); | 157 AXTreeDelegate::Change(node, AXTreeDelegate::SUBTREE_CREATED)); |
141 } else { | 158 } else { |
142 changes.push_back( | 159 // Node creation based on |new_nodes| is sometimes unreliable. Define |
143 AXTreeDelegate::Change(node, AXTreeDelegate::NODE_CREATED)); | 160 // creation based on this tree. |
161 if (node_created_ids.find(node->data().id) != | |
162 node_created_ids.end()) { | |
163 changes.push_back( | |
164 AXTreeDelegate::Change(node, AXTreeDelegate::NODE_CREATED)); | |
165 } | |
144 } | 166 } |
145 } else { | 167 } else { |
146 changes.push_back( | 168 if (text_changed_ids.find(node->data().id) == text_changed_ids.end()) { |
147 AXTreeDelegate::Change(node, AXTreeDelegate::NODE_CHANGED)); | 169 changes.push_back( |
170 AXTreeDelegate::Change(node, AXTreeDelegate::NODE_CHANGED)); | |
171 } else { | |
172 changes.push_back( | |
173 AXTreeDelegate::Change(node, AXTreeDelegate::TEXT_CHANGED)); | |
174 } | |
148 } | 175 } |
149 } | 176 } |
150 delegate_->OnAtomicUpdateFinished( | 177 delegate_->OnAtomicUpdateFinished( |
151 this, root_->id() != old_root_id, changes); | 178 this, root_->id() != old_root_id, changes); |
152 } | 179 } |
153 | 180 |
154 return true; | 181 return true; |
155 } | 182 } |
156 | 183 |
157 std::string AXTree::ToString() const { | 184 std::string AXTree::ToString() const { |
(...skipping 15 matching lines...) Expand all Loading... | |
173 // This method updates one node in the tree based on serialized data | 200 // This method updates one node in the tree based on serialized data |
174 // received in an AXTreeUpdate. See AXTreeUpdate for pre and post | 201 // received in an AXTreeUpdate. See AXTreeUpdate for pre and post |
175 // conditions. | 202 // conditions. |
176 | 203 |
177 // Look up the node by id. If it's not found, then either the root | 204 // Look up the node by id. If it's not found, then either the root |
178 // of the tree is being swapped, or we're out of sync with the source | 205 // of the tree is being swapped, or we're out of sync with the source |
179 // and this is a serious error. | 206 // and this is a serious error. |
180 AXNode* node = GetFromId(src.id); | 207 AXNode* node = GetFromId(src.id); |
181 if (node) { | 208 if (node) { |
182 update_state->pending_nodes.erase(node); | 209 update_state->pending_nodes.erase(node); |
183 node->SetData(src); | 210 node->SetData(src); |
dmazzoni
2016/02/19 04:17:32
I think this would be the place to hook it. Right
| |
184 } else { | 211 } else { |
185 if (src.role != AX_ROLE_ROOT_WEB_AREA && | 212 if (src.role != AX_ROLE_ROOT_WEB_AREA && |
186 src.role != AX_ROLE_DESKTOP) { | 213 src.role != AX_ROLE_DESKTOP) { |
187 error_ = base::StringPrintf( | 214 error_ = base::StringPrintf( |
188 "%d is not in the tree and not the new root", src.id); | 215 "%d is not in the tree and not the new root", src.id); |
189 return false; | 216 return false; |
190 } | 217 } |
191 if (update_state->new_root) { | 218 if (update_state->new_root) { |
192 error_ = "Tree update contains two new roots"; | 219 error_ = "Tree update contains two new roots"; |
193 return false; | 220 return false; |
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
305 update_state->pending_nodes.insert(child); | 332 update_state->pending_nodes.insert(child); |
306 update_state->new_nodes.insert(child); | 333 update_state->new_nodes.insert(child); |
307 } | 334 } |
308 new_children->push_back(child); | 335 new_children->push_back(child); |
309 } | 336 } |
310 | 337 |
311 return success; | 338 return success; |
312 } | 339 } |
313 | 340 |
314 } // namespace ui | 341 } // namespace ui |
OLD | NEW |