Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(412)

Side by Side Diff: content/browser/accessibility/browser_accessibility_manager.cc

Issue 7966013: Rewrite renderer accessibility to not use WebAccessibilityCache. (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 9 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 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 "content/browser/accessibility/browser_accessibility_manager.h" 5 #include "content/browser/accessibility/browser_accessibility_manager.h"
6 6
7 #include "base/logging.h" 7 #include "base/logging.h"
8 #include "content/browser/accessibility/browser_accessibility.h" 8 #include "content/browser/accessibility/browser_accessibility.h"
9 #include "content/common/view_messages.h" 9 #include "content/common/view_messages.h"
10 10
(...skipping 25 matching lines...) Expand all
36 #endif 36 #endif
37 37
38 // static 38 // static
39 BrowserAccessibilityManager* BrowserAccessibilityManager::CreateEmptyDocument( 39 BrowserAccessibilityManager* BrowserAccessibilityManager::CreateEmptyDocument(
40 gfx::NativeView parent_view, 40 gfx::NativeView parent_view,
41 WebAccessibility::State state, 41 WebAccessibility::State state,
42 BrowserAccessibilityDelegate* delegate, 42 BrowserAccessibilityDelegate* delegate,
43 BrowserAccessibilityFactory* factory) { 43 BrowserAccessibilityFactory* factory) {
44 // Use empty document to process notifications 44 // Use empty document to process notifications
45 webkit_glue::WebAccessibility empty_document; 45 webkit_glue::WebAccessibility empty_document;
46 // Renderer id's always start at 1000 as determined by webkit. Boot strap 46 empty_document.id = 0;
47 // our ability to reuse BrowserAccessibility instances. 47 empty_document.role = WebAccessibility::ROLE_ROOT_WEB_AREA;
48 empty_document.id = 1000;
49 empty_document.role = WebAccessibility::ROLE_WEB_AREA;
50 empty_document.state = state; 48 empty_document.state = state;
51 return BrowserAccessibilityManager::Create( 49 return BrowserAccessibilityManager::Create(
52 parent_view, empty_document, delegate, factory); 50 parent_view, empty_document, delegate, factory);
53 } 51 }
54 52
55 BrowserAccessibilityManager::BrowserAccessibilityManager( 53 BrowserAccessibilityManager::BrowserAccessibilityManager(
56 gfx::NativeView parent_view, 54 gfx::NativeView parent_view,
57 const WebAccessibility& src, 55 const WebAccessibility& src,
58 BrowserAccessibilityDelegate* delegate, 56 BrowserAccessibilityDelegate* delegate,
59 BrowserAccessibilityFactory* factory) 57 BrowserAccessibilityFactory* factory)
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
107 int32 renderer_id) { 105 int32 renderer_id) {
108 base::hash_map<int32, int32>::iterator iter = 106 base::hash_map<int32, int32>::iterator iter =
109 renderer_id_to_child_id_map_.find(renderer_id); 107 renderer_id_to_child_id_map_.find(renderer_id);
110 if (iter == renderer_id_to_child_id_map_.end()) 108 if (iter == renderer_id_to_child_id_map_.end())
111 return NULL; 109 return NULL;
112 110
113 int32 child_id = iter->second; 111 int32 child_id = iter->second;
114 return GetFromChildID(child_id); 112 return GetFromChildID(child_id);
115 } 113 }
116 114
115 void BrowserAccessibilityManager::GotFocus() {
116 if (!focus_)
117 return;
118
119 NotifyAccessibilityEvent(ViewHostMsg_AccEvent::FOCUS_CHANGED, focus_);
120 }
121
117 void BrowserAccessibilityManager::Remove(int32 child_id, int32 renderer_id) { 122 void BrowserAccessibilityManager::Remove(int32 child_id, int32 renderer_id) {
118 child_id_map_.erase(child_id); 123 child_id_map_.erase(child_id);
119 124
120 // TODO(ctguil): Investigate if hit. We should never have a newer entry. 125 // TODO(ctguil): Investigate if hit. We should never have a newer entry.
121 DCHECK(renderer_id_to_child_id_map_[renderer_id] == child_id); 126 DCHECK(renderer_id_to_child_id_map_[renderer_id] == child_id);
122 // Make sure we don't overwrite a newer entry (see UpdateNode for a possible 127 // Make sure we don't overwrite a newer entry (see UpdateNode for a possible
123 // corner case). 128 // corner case).
124 if (renderer_id_to_child_id_map_[renderer_id] == child_id) 129 if (renderer_id_to_child_id_map_[renderer_id] == child_id)
125 renderer_id_to_child_id_map_.erase(renderer_id); 130 renderer_id_to_child_id_map_.erase(renderer_id);
126 } 131 }
127 132
128 void BrowserAccessibilityManager::OnAccessibilityNotifications( 133 void BrowserAccessibilityManager::OnAccessibilityNotifications(
129 const std::vector<ViewHostMsg_AccessibilityNotification_Params>& params) { 134 const std::vector<ViewHostMsg_AccessibilityNotification_Params>& params) {
130 for (uint32 index = 0; index < params.size(); index++) { 135 for (uint32 index = 0; index < params.size(); index++) {
131 const ViewHostMsg_AccessibilityNotification_Params& param = params[index]; 136 const ViewHostMsg_AccessibilityNotification_Params& param = params[index];
132 137
133 switch (param.notification_type) { 138 // Update the tree.
134 // Notifications where children are included. 139 UpdateNode(param.acc_tree, param.includes_children);
135 case ViewHostMsg_AccEvent::CHILDREN_CHANGED:
136 case ViewHostMsg_AccEvent::LIVE_REGION_CHANGED:
137 OnSimpleAccessibilityNotification(
138 param.acc_obj, param.notification_type, true);
139 break;
140 140
141 case ViewHostMsg_AccEvent::FOCUS_CHANGED: 141 // Find the node corresponding to the id that's the target of the
142 OnAccessibilityObjectFocusChange(param.acc_obj); 142 // notification (which may not be the root of the update tree).
143 break; 143 base::hash_map<int32, int32>::iterator iter =
144 renderer_id_to_child_id_map_.find(param.id);
145 if (iter == renderer_id_to_child_id_map_.end()) {
146 continue;
147 }
148 int32 child_id = iter->second;
149 BrowserAccessibility* node = GetFromChildID(child_id);
150 if (!node) {
151 NOTREACHED();
152 continue;
153 }
144 154
145 case ViewHostMsg_AccEvent::LOAD_COMPLETE: 155 if (param.notification_type == ViewHostMsg_AccEvent::FOCUS_CHANGED) {
146 OnAccessibilityObjectLoadComplete(param.acc_obj); 156 SetFocus(node, false);
147 break;
148 157
149 // All other notifications: the node is updated, but 158 // Don't send a native focus event if the window itself doesn't
150 // children are not included. 159 // have focus.
151 case ViewHostMsg_AccEvent::ACTIVE_DESCENDANT_CHANGED: 160 if (delegate_ && !delegate_->HasFocus())
152 case ViewHostMsg_AccEvent::ALERT: 161 continue;
153 case ViewHostMsg_AccEvent::CHECK_STATE_CHANGED: 162 }
154 case ViewHostMsg_AccEvent::LAYOUT_COMPLETE:
155 case ViewHostMsg_AccEvent::MENU_LIST_VALUE_CHANGED:
156 case ViewHostMsg_AccEvent::OBJECT_HIDE:
157 case ViewHostMsg_AccEvent::OBJECT_SHOW:
158 case ViewHostMsg_AccEvent::ROW_COLLAPSED:
159 case ViewHostMsg_AccEvent::ROW_COUNT_CHANGED:
160 case ViewHostMsg_AccEvent::ROW_EXPANDED:
161 case ViewHostMsg_AccEvent::SCROLLED_TO_ANCHOR:
162 case ViewHostMsg_AccEvent::SELECTED_CHILDREN_CHANGED:
163 case ViewHostMsg_AccEvent::SELECTED_TEXT_CHANGED:
164 case ViewHostMsg_AccEvent::TEXT_INSERTED:
165 case ViewHostMsg_AccEvent::TEXT_REMOVED:
166 case ViewHostMsg_AccEvent::VALUE_CHANGED:
167 OnSimpleAccessibilityNotification(
168 param.acc_obj, param.notification_type, false);
169 break;
170 163
171 default: 164 // Send the notification event to the operating system.
172 DCHECK(0); 165 NotifyAccessibilityEvent(param.notification_type, node);
166
167 // Set initial focus when a page is loaded.
168 if (param.notification_type == ViewHostMsg_AccEvent::LOAD_COMPLETE) {
169 if (!focus_)
170 SetFocus(root_, false);
171 if (!delegate_ || delegate_->HasFocus())
172 NotifyAccessibilityEvent(ViewHostMsg_AccEvent::FOCUS_CHANGED, focus_);
173 } 173 }
174 } 174 }
175 } 175 }
176 176
177 void BrowserAccessibilityManager::OnSimpleAccessibilityNotification(
178 const WebAccessibility& acc_obj,
179 int notification_type,
180 bool include_children) {
181 BrowserAccessibility* new_browser_acc =
182 UpdateNode(acc_obj, include_children);
183 if (!new_browser_acc)
184 return;
185
186 NotifyAccessibilityEvent(notification_type, new_browser_acc);
187 }
188
189 void BrowserAccessibilityManager::OnAccessibilityObjectFocusChange(
190 const WebAccessibility& acc_obj) {
191 BrowserAccessibility* new_browser_acc = UpdateNode(acc_obj, false);
192 if (!new_browser_acc)
193 return;
194
195 SetFocus(new_browser_acc, false);
196 if (delegate_ && delegate_->HasFocus()) {
197 GotFocus();
198 } else if (!delegate_) {
199 // Mac currently does not have a BrowserAccessibilityDelegate.
200 NotifyAccessibilityEvent(ViewHostMsg_AccEvent::FOCUS_CHANGED, focus_);
201 }
202 }
203
204 void BrowserAccessibilityManager::OnAccessibilityObjectLoadComplete(
205 const WebAccessibility& acc_obj) {
206 SetFocus(NULL, false);
207
208 root_ = UpdateNode(acc_obj, true);
209 if (!focus_)
210 SetFocus(root_, false);
211
212 NotifyAccessibilityEvent(ViewHostMsg_AccEvent::LOAD_COMPLETE, root_);
213 if (delegate_ && delegate_->HasFocus())
214 GotFocus();
215 }
216
217 void BrowserAccessibilityManager::GotFocus() {
218 // TODO(ctguil): Remove when tree update logic handles focus changes.
219 if (!focus_)
220 return;
221
222 NotifyAccessibilityEvent(ViewHostMsg_AccEvent::FOCUS_CHANGED, focus_);
223 }
224
225 gfx::NativeView BrowserAccessibilityManager::GetParentView() { 177 gfx::NativeView BrowserAccessibilityManager::GetParentView() {
226 return parent_view_; 178 return parent_view_;
227 } 179 }
228 180
229 BrowserAccessibility* BrowserAccessibilityManager::GetFocus( 181 BrowserAccessibility* BrowserAccessibilityManager::GetFocus(
230 BrowserAccessibility* root) { 182 BrowserAccessibility* root) {
231 if (focus_ && (!root || focus_->IsDescendantOf(root))) 183 if (focus_ && (!root || focus_->IsDescendantOf(root)))
232 return focus_; 184 return focus_;
233 185
234 return NULL; 186 return NULL;
(...skipping 18 matching lines...) Expand all
253 if (delegate_) 205 if (delegate_)
254 delegate_->AccessibilityDoDefaultAction(node.renderer_id()); 206 delegate_->AccessibilityDoDefaultAction(node.renderer_id());
255 } 207 }
256 208
257 gfx::Rect BrowserAccessibilityManager::GetViewBounds() { 209 gfx::Rect BrowserAccessibilityManager::GetViewBounds() {
258 if (delegate_) 210 if (delegate_)
259 return delegate_->GetViewBounds(); 211 return delegate_->GetViewBounds();
260 return gfx::Rect(); 212 return gfx::Rect();
261 } 213 }
262 214
263 BrowserAccessibility* BrowserAccessibilityManager::UpdateNode( 215 void BrowserAccessibilityManager::UpdateNode(
264 const WebAccessibility& src, 216 const WebAccessibility& src,
265 bool include_children) { 217 bool include_children) {
266 base::hash_map<int32, int32>::iterator iter = 218 BrowserAccessibility* current = NULL;
267 renderer_id_to_child_id_map_.find(src.id); 219 if (src.role == WebAccessibility::ROLE_ROOT_WEB_AREA) {
268 if (iter == renderer_id_to_child_id_map_.end()) 220 // As an exceptional case, there can only be one root of the tree, so
269 return NULL; 221 // if we get a new root, replace the current root no matter what the
222 // current root's renderer ID is.
223 current = root_;
224 renderer_id_to_child_id_map_.erase(current->renderer_id());
225 renderer_id_to_child_id_map_[src.id] = current->child_id();
226 } else {
227 // Otherwise, replace the node based on its renderer ID.
228 base::hash_map<int32, int32>::iterator iter =
229 renderer_id_to_child_id_map_.find(src.id);
230 if (iter != renderer_id_to_child_id_map_.end()) {
231 int32 child_id = iter->second;
232 current = GetFromChildID(child_id);
233 }
234 }
270 235
271 int32 child_id = iter->second;
272 BrowserAccessibility* current = GetFromChildID(child_id);
273 if (!current) 236 if (!current)
274 return NULL; 237 return;
275 238
276 if (!include_children) { 239 if (!include_children) {
277 DCHECK_EQ(0U, src.children.size()); 240 DCHECK_EQ(0U, src.children.size());
278 current->Initialize( 241 current->Initialize(
279 this, 242 this,
280 current->parent(), 243 current->parent(),
281 current->child_id(), 244 current->child_id(),
282 current->index_in_parent(), 245 current->index_in_parent(),
283 src); 246 src);
284 current->SendNodeUpdateEvents(); 247 current->SendNodeUpdateEvents();
285 return current; 248 return;
286 } 249 }
287 250
288 BrowserAccessibility* current_parent = current->parent(); 251 BrowserAccessibility* current_parent = current->parent();
289 int current_index_in_parent = current->index_in_parent(); 252 int current_index_in_parent = current->index_in_parent();
290 253
291 // Detach all of the nodes in the old tree and get a single flat vector 254 // Detach all of the nodes in the old tree and get a single flat vector
292 // of all node pointers. 255 // of all node pointers.
293 std::vector<BrowserAccessibility*> old_tree_nodes; 256 std::vector<BrowserAccessibility*> old_tree_nodes;
294 current->DetachTree(&old_tree_nodes); 257 current->DetachTree(&old_tree_nodes);
295 258
296 // Build a new tree, reusing old nodes if possible. Each node that's 259 // Build a new tree, reusing old nodes if possible. Each node that's
297 // reused will have its reference count incremented by one. 260 // reused will have its reference count incremented by one.
298 current = CreateAccessibilityTree( 261 current = CreateAccessibilityTree(
299 current_parent, src, current_index_in_parent, true); 262 current_parent, src, current_index_in_parent, true);
300 263
301 // Decrement the reference count of all nodes in the old tree, which will 264 // Decrement the reference count of all nodes in the old tree, which will
302 // delete any nodes no longer needed. 265 // delete any nodes no longer needed.
303 for (int i = 0; i < static_cast<int>(old_tree_nodes.size()); i++) 266 for (int i = 0; i < static_cast<int>(old_tree_nodes.size()); i++)
304 old_tree_nodes[i]->InternalReleaseReference(false); 267 old_tree_nodes[i]->InternalReleaseReference(false);
305 268
306 if (!focus_ || !focus_->instance_active()) 269 if (!focus_ || !focus_->instance_active())
307 SetFocus(root_, false); 270 SetFocus(root_, false);
308
309 return current;
310 } 271 }
311 272
312 BrowserAccessibility* BrowserAccessibilityManager::CreateAccessibilityTree( 273 BrowserAccessibility* BrowserAccessibilityManager::CreateAccessibilityTree(
313 BrowserAccessibility* parent, 274 BrowserAccessibility* parent,
314 const WebAccessibility& src, 275 const WebAccessibility& src,
315 int index_in_parent, 276 int index_in_parent,
316 bool send_show_events) { 277 bool send_show_events) {
317 BrowserAccessibility* instance = NULL; 278 BrowserAccessibility* instance = NULL;
318 int32 child_id = 0; 279 int32 child_id = 0;
319 bool children_can_send_show_events = send_show_events; 280 bool children_can_send_show_events = send_show_events;
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
368 // is so that we send a single OBJECT_SHOW event for the root of a subtree 329 // is so that we send a single OBJECT_SHOW event for the root of a subtree
369 // that just appeared for the first time, but not on any descendant of 330 // that just appeared for the first time, but not on any descendant of
370 // that subtree. 331 // that subtree.
371 if (send_show_events) 332 if (send_show_events)
372 NotifyAccessibilityEvent(ViewHostMsg_AccEvent::OBJECT_SHOW, instance); 333 NotifyAccessibilityEvent(ViewHostMsg_AccEvent::OBJECT_SHOW, instance);
373 334
374 instance->SendNodeUpdateEvents(); 335 instance->SendNodeUpdateEvents();
375 336
376 return instance; 337 return instance;
377 } 338 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698