OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 <stddef.h> | 7 #include <stddef.h> |
8 | 8 |
9 #include "base/logging.h" | 9 #include "base/logging.h" |
10 #include "build/build_config.h" | 10 #include "build/build_config.h" |
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
116 auto iter = ax_tree_id_map->find(ax_tree_id); | 116 auto iter = ax_tree_id_map->find(ax_tree_id); |
117 return iter == ax_tree_id_map->end() ? nullptr : iter->second; | 117 return iter == ax_tree_id_map->end() ? nullptr : iter->second; |
118 } | 118 } |
119 | 119 |
120 BrowserAccessibilityManager::BrowserAccessibilityManager( | 120 BrowserAccessibilityManager::BrowserAccessibilityManager( |
121 BrowserAccessibilityDelegate* delegate, | 121 BrowserAccessibilityDelegate* delegate, |
122 BrowserAccessibilityFactory* factory) | 122 BrowserAccessibilityFactory* factory) |
123 : delegate_(delegate), | 123 : delegate_(delegate), |
124 factory_(factory), | 124 factory_(factory), |
125 tree_(new ui::AXSerializableTree()), | 125 tree_(new ui::AXSerializableTree()), |
126 focus_(NULL), | |
127 user_is_navigating_away_(false), | 126 user_is_navigating_away_(false), |
128 osk_state_(OSK_ALLOWED), | 127 osk_state_(OSK_ALLOWED), |
129 ax_tree_id_(AXTreeIDRegistry::kNoAXTreeID), | 128 ax_tree_id_(AXTreeIDRegistry::kNoAXTreeID), |
130 parent_node_id_from_parent_tree_(0) { | 129 parent_node_id_from_parent_tree_(0) { |
131 tree_->SetDelegate(this); | 130 tree_->SetDelegate(this); |
132 } | 131 } |
133 | 132 |
134 BrowserAccessibilityManager::BrowserAccessibilityManager( | 133 BrowserAccessibilityManager::BrowserAccessibilityManager( |
135 const ui::AXTreeUpdate& initial_tree, | 134 const ui::AXTreeUpdate& initial_tree, |
136 BrowserAccessibilityDelegate* delegate, | 135 BrowserAccessibilityDelegate* delegate, |
137 BrowserAccessibilityFactory* factory) | 136 BrowserAccessibilityFactory* factory) |
138 : delegate_(delegate), | 137 : delegate_(delegate), |
139 factory_(factory), | 138 factory_(factory), |
140 tree_(new ui::AXSerializableTree()), | 139 tree_(new ui::AXSerializableTree()), |
141 focus_(NULL), | |
142 user_is_navigating_away_(false), | 140 user_is_navigating_away_(false), |
143 osk_state_(OSK_ALLOWED), | 141 osk_state_(OSK_ALLOWED), |
144 ax_tree_id_(AXTreeIDRegistry::kNoAXTreeID), | 142 ax_tree_id_(AXTreeIDRegistry::kNoAXTreeID), |
145 parent_node_id_from_parent_tree_(0) { | 143 parent_node_id_from_parent_tree_(0) { |
146 tree_->SetDelegate(this); | 144 tree_->SetDelegate(this); |
147 Initialize(initial_tree); | 145 Initialize(initial_tree); |
148 } | 146 } |
149 | 147 |
150 BrowserAccessibilityManager::~BrowserAccessibilityManager() { | 148 BrowserAccessibilityManager::~BrowserAccessibilityManager() { |
151 tree_.reset(NULL); | 149 tree_.reset(NULL); |
152 g_ax_tree_id_map.Get().erase(ax_tree_id_); | 150 g_ax_tree_id_map.Get().erase(ax_tree_id_); |
153 } | 151 } |
154 | 152 |
155 void BrowserAccessibilityManager::Initialize( | 153 void BrowserAccessibilityManager::Initialize( |
156 const ui::AXTreeUpdate& initial_tree) { | 154 const ui::AXTreeUpdate& initial_tree) { |
157 if (!tree_->Unserialize(initial_tree)) { | 155 if (!tree_->Unserialize(initial_tree)) { |
158 if (delegate_) { | 156 if (delegate_) { |
159 LOG(ERROR) << tree_->error(); | 157 LOG(ERROR) << tree_->error(); |
160 delegate_->AccessibilityFatalError(); | 158 delegate_->AccessibilityFatalError(); |
161 } else { | 159 } else { |
162 LOG(FATAL) << tree_->error(); | 160 LOG(FATAL) << tree_->error(); |
163 } | 161 } |
164 } | 162 } |
165 | |
166 if (!focus_) | |
167 SetFocus(tree_->root(), false); | |
168 } | 163 } |
169 | 164 |
170 // static | 165 // static |
171 ui::AXTreeUpdate | 166 ui::AXTreeUpdate |
172 BrowserAccessibilityManager::GetEmptyDocument() { | 167 BrowserAccessibilityManager::GetEmptyDocument() { |
173 ui::AXNodeData empty_document; | 168 ui::AXNodeData empty_document; |
174 empty_document.id = 0; | 169 empty_document.id = 0; |
175 empty_document.role = ui::AX_ROLE_ROOT_WEB_AREA; | 170 empty_document.role = ui::AX_ROLE_ROOT_WEB_AREA; |
176 ui::AXTreeUpdate update; | 171 ui::AXTreeUpdate update; |
177 update.nodes.push_back(empty_document); | 172 update.nodes.push_back(empty_document); |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
236 } | 231 } |
237 | 232 |
238 return nullptr; | 233 return nullptr; |
239 } | 234 } |
240 | 235 |
241 const ui::AXTreeData& BrowserAccessibilityManager::GetTreeData() { | 236 const ui::AXTreeData& BrowserAccessibilityManager::GetTreeData() { |
242 return tree_->data(); | 237 return tree_->data(); |
243 } | 238 } |
244 | 239 |
245 void BrowserAccessibilityManager::OnWindowFocused() { | 240 void BrowserAccessibilityManager::OnWindowFocused() { |
246 if (focus_) | 241 BrowserAccessibility* focus = GetFocus(); |
247 NotifyAccessibilityEvent(ui::AX_EVENT_FOCUS, GetFromAXNode(focus_)); | 242 if (focus) |
| 243 NotifyAccessibilityEvent(ui::AX_EVENT_FOCUS, focus); |
248 } | 244 } |
249 | 245 |
250 void BrowserAccessibilityManager::OnWindowBlurred() { | 246 void BrowserAccessibilityManager::OnWindowBlurred() { |
251 if (focus_) | 247 BrowserAccessibility* focus = GetFocus(); |
252 NotifyAccessibilityEvent(ui::AX_EVENT_BLUR, GetFromAXNode(focus_)); | 248 if (focus) |
| 249 NotifyAccessibilityEvent(ui::AX_EVENT_BLUR, focus); |
253 } | 250 } |
254 | 251 |
255 void BrowserAccessibilityManager::UserIsNavigatingAway() { | 252 void BrowserAccessibilityManager::UserIsNavigatingAway() { |
256 user_is_navigating_away_ = true; | 253 user_is_navigating_away_ = true; |
257 } | 254 } |
258 | 255 |
259 void BrowserAccessibilityManager::UserIsReloading() { | 256 void BrowserAccessibilityManager::UserIsReloading() { |
260 user_is_navigating_away_ = true; | 257 user_is_navigating_away_ = true; |
261 } | 258 } |
262 | 259 |
263 void BrowserAccessibilityManager::NavigationSucceeded() { | 260 void BrowserAccessibilityManager::NavigationSucceeded() { |
264 user_is_navigating_away_ = false; | 261 user_is_navigating_away_ = false; |
265 } | 262 } |
266 | 263 |
267 void BrowserAccessibilityManager::NavigationFailed() { | 264 void BrowserAccessibilityManager::NavigationFailed() { |
268 user_is_navigating_away_ = false; | 265 user_is_navigating_away_ = false; |
269 } | 266 } |
270 | 267 |
271 void BrowserAccessibilityManager::GotMouseDown() { | 268 void BrowserAccessibilityManager::GotMouseDown() { |
272 if (!focus_) | 269 BrowserAccessibility* focus = GetFocus(); |
| 270 if (!focus) |
273 return; | 271 return; |
274 | 272 |
275 osk_state_ = OSK_ALLOWED_WITHIN_FOCUSED_OBJECT; | 273 osk_state_ = OSK_ALLOWED_WITHIN_FOCUSED_OBJECT; |
276 NotifyAccessibilityEvent(ui::AX_EVENT_FOCUS, GetFromAXNode(focus_)); | 274 NotifyAccessibilityEvent(ui::AX_EVENT_FOCUS, focus); |
277 } | 275 } |
278 | 276 |
279 bool BrowserAccessibilityManager::UseRootScrollOffsetsWhenComputingBounds() { | 277 bool BrowserAccessibilityManager::UseRootScrollOffsetsWhenComputingBounds() { |
280 return true; | 278 return true; |
281 } | 279 } |
282 | 280 |
283 void BrowserAccessibilityManager::OnAccessibilityEvents( | 281 void BrowserAccessibilityManager::OnAccessibilityEvents( |
284 const std::vector<AXEventNotificationDetails>& details) { | 282 const std::vector<AXEventNotificationDetails>& details) { |
285 bool should_send_initial_focus = false; | |
286 | |
287 // Process all changes to the accessibility tree first. | 283 // Process all changes to the accessibility tree first. |
288 for (uint32_t index = 0; index < details.size(); ++index) { | 284 for (uint32_t index = 0; index < details.size(); ++index) { |
289 const AXEventNotificationDetails& detail = details[index]; | 285 const AXEventNotificationDetails& detail = details[index]; |
290 if (!tree_->Unserialize(detail.update)) { | 286 if (!tree_->Unserialize(detail.update)) { |
291 if (delegate_) { | 287 if (delegate_) { |
292 LOG(ERROR) << tree_->error(); | 288 LOG(ERROR) << tree_->error(); |
293 delegate_->AccessibilityFatalError(); | 289 delegate_->AccessibilityFatalError(); |
294 } else { | 290 } else { |
295 CHECK(false) << tree_->error(); | 291 CHECK(false) << tree_->error(); |
296 } | 292 } |
297 return; | 293 return; |
298 } | 294 } |
299 | |
300 // Set focus to the root if it's not anywhere else. | |
301 if (!focus_) { | |
302 SetFocus(tree_->root(), false); | |
303 should_send_initial_focus = true; | |
304 } | |
305 } | 295 } |
306 | 296 |
307 if (should_send_initial_focus && NativeViewHasFocus()) | |
308 NotifyAccessibilityEvent(ui::AX_EVENT_FOCUS, GetFromAXNode(focus_)); | |
309 | |
310 // Now iterate over the events again and fire the events. | 297 // Now iterate over the events again and fire the events. |
311 for (uint32_t index = 0; index < details.size(); index++) { | 298 for (uint32_t index = 0; index < details.size(); index++) { |
312 const AXEventNotificationDetails& detail = details[index]; | 299 const AXEventNotificationDetails& detail = details[index]; |
313 | 300 |
314 // Find the node corresponding to the id that's the target of the | 301 // Find the node corresponding to the id that's the target of the |
315 // event (which may not be the root of the update tree). | 302 // event (which may not be the root of the update tree). |
316 ui::AXNode* node = tree_->GetFromId(detail.id); | 303 ui::AXNode* node = tree_->GetFromId(detail.id); |
317 if (!node) | 304 if (!node) |
318 continue; | 305 continue; |
319 | 306 |
320 ui::AXEvent event_type = detail.event_type; | 307 ui::AXEvent event_type = detail.event_type; |
321 if (event_type == ui::AX_EVENT_FOCUS || | 308 if (event_type == ui::AX_EVENT_FOCUS || |
322 event_type == ui::AX_EVENT_BLUR) { | 309 event_type == ui::AX_EVENT_BLUR) { |
323 SetFocus(node, false); | |
324 | |
325 if (osk_state_ != OSK_DISALLOWED_BECAUSE_TAB_HIDDEN && | 310 if (osk_state_ != OSK_DISALLOWED_BECAUSE_TAB_HIDDEN && |
326 osk_state_ != OSK_DISALLOWED_BECAUSE_TAB_JUST_APPEARED) | 311 osk_state_ != OSK_DISALLOWED_BECAUSE_TAB_JUST_APPEARED) |
327 osk_state_ = OSK_ALLOWED; | 312 osk_state_ = OSK_ALLOWED; |
328 | 313 |
329 // Don't send a native focus event if the window itself doesn't | 314 // Don't send a native focus event if the window itself doesn't |
330 // have focus. | 315 // have focus. |
331 if (!NativeViewHasFocus()) | 316 if (!NativeViewHasFocus()) |
332 continue; | 317 continue; |
333 } | 318 } |
334 | 319 |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
380 node = ancestor; | 365 node = ancestor; |
381 ancestor = ancestor->GetParent(); | 366 ancestor = ancestor->GetParent(); |
382 } | 367 } |
383 | 368 |
384 // The "scrolled to anchor" notification is a great way to get a | 369 // The "scrolled to anchor" notification is a great way to get a |
385 // screen reader to jump directly to a specific location in a document. | 370 // screen reader to jump directly to a specific location in a document. |
386 NotifyAccessibilityEvent(ui::AX_EVENT_SCROLLED_TO_ANCHOR, node); | 371 NotifyAccessibilityEvent(ui::AX_EVENT_SCROLLED_TO_ANCHOR, node); |
387 } | 372 } |
388 | 373 |
389 BrowserAccessibility* BrowserAccessibilityManager::GetActiveDescendantFocus( | 374 BrowserAccessibility* BrowserAccessibilityManager::GetActiveDescendantFocus( |
390 BrowserAccessibility* root) { | 375 BrowserAccessibility* focus) { |
391 BrowserAccessibility* node = BrowserAccessibilityManager::GetFocus(root); | 376 if (!focus) |
392 if (!node) | |
393 return NULL; | 377 return NULL; |
394 | 378 |
395 int active_descendant_id; | 379 int active_descendant_id; |
396 if (node->GetIntAttribute(ui::AX_ATTR_ACTIVEDESCENDANT_ID, | 380 if (focus->GetIntAttribute(ui::AX_ATTR_ACTIVEDESCENDANT_ID, |
397 &active_descendant_id)) { | 381 &active_descendant_id)) { |
398 BrowserAccessibility* active_descendant = | 382 BrowserAccessibility* active_descendant = |
399 node->manager()->GetFromID(active_descendant_id); | 383 focus->manager()->GetFromID(active_descendant_id); |
400 if (active_descendant) | 384 if (active_descendant) |
401 return active_descendant; | 385 return active_descendant; |
402 } | 386 } |
403 return node; | 387 return focus; |
404 } | 388 } |
405 | 389 |
406 bool BrowserAccessibilityManager::NativeViewHasFocus() { | 390 bool BrowserAccessibilityManager::NativeViewHasFocus() { |
407 BrowserAccessibilityDelegate* delegate = GetDelegateFromRootManager(); | 391 BrowserAccessibilityDelegate* delegate = GetDelegateFromRootManager(); |
408 if (delegate) | 392 if (delegate) |
409 return delegate->AccessibilityViewHasFocus(); | 393 return delegate->AccessibilityViewHasFocus(); |
410 return false; | 394 return false; |
411 } | 395 } |
412 | 396 |
413 BrowserAccessibility* BrowserAccessibilityManager::GetFocus( | 397 BrowserAccessibility* BrowserAccessibilityManager::GetFocus() { |
414 BrowserAccessibility* root) { | 398 int32_t focus_id = GetTreeData().focus_id; |
415 if (!focus_) | 399 BrowserAccessibility* obj = GetFromID(focus_id); |
416 return nullptr; | 400 if (!obj) |
| 401 return GetRoot(); |
417 | 402 |
418 if (root && !focus_->IsDescendantOf(root->node())) | |
419 return nullptr; | |
420 | |
421 BrowserAccessibility* obj = GetFromAXNode(focus_); | |
422 DCHECK(obj); | |
423 if (obj->HasIntAttribute(ui::AX_ATTR_CHILD_TREE_ID)) { | 403 if (obj->HasIntAttribute(ui::AX_ATTR_CHILD_TREE_ID)) { |
424 BrowserAccessibilityManager* child_manager = | 404 BrowserAccessibilityManager* child_manager = |
425 BrowserAccessibilityManager::FromID( | 405 BrowserAccessibilityManager::FromID( |
426 obj->GetIntAttribute(ui::AX_ATTR_CHILD_TREE_ID)); | 406 obj->GetIntAttribute(ui::AX_ATTR_CHILD_TREE_ID)); |
427 if (child_manager) | 407 if (child_manager) |
428 return child_manager->GetFocus(child_manager->GetRoot()); | 408 return child_manager->GetFocus(); |
429 } | 409 } |
430 | 410 |
431 return obj; | 411 return obj; |
432 } | 412 } |
433 | 413 |
434 void BrowserAccessibilityManager::SetFocus(ui::AXNode* node, bool notify) { | 414 void BrowserAccessibilityManager::SetFocus(const BrowserAccessibility& node) { |
435 if (focus_ != node) | 415 if (delegate_) |
436 focus_ = node; | 416 delegate_->AccessibilitySetFocus(node.GetId()); |
437 | |
438 if (notify && node && delegate_) | |
439 delegate_->AccessibilitySetFocus(node->id()); | |
440 } | 417 } |
441 | 418 |
442 void BrowserAccessibilityManager::SetFocus( | 419 void BrowserAccessibilityManager::SetFocusLocallyForTesting( |
443 BrowserAccessibility* obj, bool notify) { | 420 BrowserAccessibility* node) { |
444 if (obj->node()) | 421 ui::AXTreeData data = GetTreeData(); |
445 SetFocus(obj->node(), notify); | 422 data.focus_id = node->GetId(); |
| 423 tree_->UpdateData(data); |
446 } | 424 } |
447 | 425 |
448 void BrowserAccessibilityManager::DoDefaultAction( | 426 void BrowserAccessibilityManager::DoDefaultAction( |
449 const BrowserAccessibility& node) { | 427 const BrowserAccessibility& node) { |
450 if (delegate_) | 428 if (delegate_) |
451 delegate_->AccessibilityDoDefaultAction(node.GetId()); | 429 delegate_->AccessibilityDoDefaultAction(node.GetId()); |
452 } | 430 } |
453 | 431 |
454 void BrowserAccessibilityManager::ScrollToMakeVisible( | 432 void BrowserAccessibilityManager::ScrollToMakeVisible( |
455 const BrowserAccessibility& node, gfx::Rect subfocus) { | 433 const BrowserAccessibility& node, gfx::Rect subfocus) { |
(...skipping 215 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
671 | 649 |
672 return text; | 650 return text; |
673 } | 651 } |
674 | 652 |
675 void BrowserAccessibilityManager::OnTreeDataChanged(ui::AXTree* tree) { | 653 void BrowserAccessibilityManager::OnTreeDataChanged(ui::AXTree* tree) { |
676 } | 654 } |
677 | 655 |
678 void BrowserAccessibilityManager::OnNodeWillBeDeleted(ui::AXTree* tree, | 656 void BrowserAccessibilityManager::OnNodeWillBeDeleted(ui::AXTree* tree, |
679 ui::AXNode* node) { | 657 ui::AXNode* node) { |
680 DCHECK(node); | 658 DCHECK(node); |
681 if (node == focus_ && tree_) { | |
682 if (node != tree_->root()) | |
683 SetFocus(tree_->root(), false); | |
684 else | |
685 focus_ = NULL; | |
686 } | |
687 if (id_wrapper_map_.find(node->id()) == id_wrapper_map_.end()) | 659 if (id_wrapper_map_.find(node->id()) == id_wrapper_map_.end()) |
688 return; | 660 return; |
689 GetFromAXNode(node)->Destroy(); | 661 GetFromAXNode(node)->Destroy(); |
690 id_wrapper_map_.erase(node->id()); | 662 id_wrapper_map_.erase(node->id()); |
691 } | 663 } |
692 | 664 |
693 void BrowserAccessibilityManager::OnSubtreeWillBeDeleted(ui::AXTree* tree, | 665 void BrowserAccessibilityManager::OnSubtreeWillBeDeleted(ui::AXTree* tree, |
694 ui::AXNode* node) { | 666 ui::AXNode* node) { |
695 DCHECK(node); | 667 DCHECK(node); |
696 BrowserAccessibility* obj = GetFromAXNode(node); | 668 BrowserAccessibility* obj = GetFromAXNode(node); |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
761 tree_->CreateTreeSource()); | 733 tree_->CreateTreeSource()); |
762 ui::AXTreeSerializer<const ui::AXNode*, | 734 ui::AXTreeSerializer<const ui::AXNode*, |
763 ui::AXNodeData, | 735 ui::AXNodeData, |
764 ui::AXTreeData> serializer(tree_source.get()); | 736 ui::AXTreeData> serializer(tree_source.get()); |
765 ui::AXTreeUpdate update; | 737 ui::AXTreeUpdate update; |
766 serializer.SerializeChanges(tree_->root(), &update); | 738 serializer.SerializeChanges(tree_->root(), &update); |
767 return update; | 739 return update; |
768 } | 740 } |
769 | 741 |
770 } // namespace content | 742 } // namespace content |
OLD | NEW |