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 25 matching lines...) Expand all Loading... |
36 return nullptr; | 36 return nullptr; |
37 } | 37 } |
38 | 38 |
39 } // namespace | 39 } // namespace |
40 | 40 |
41 // Map from AXTreeID to BrowserAccessibilityManager | 41 // Map from AXTreeID to BrowserAccessibilityManager |
42 using AXTreeIDMap = | 42 using AXTreeIDMap = |
43 base::hash_map<AXTreeIDRegistry::AXTreeID, BrowserAccessibilityManager*>; | 43 base::hash_map<AXTreeIDRegistry::AXTreeID, BrowserAccessibilityManager*>; |
44 base::LazyInstance<AXTreeIDMap> g_ax_tree_id_map = LAZY_INSTANCE_INITIALIZER; | 44 base::LazyInstance<AXTreeIDMap> g_ax_tree_id_map = LAZY_INSTANCE_INITIALIZER; |
45 | 45 |
| 46 // A function to call when focus changes, for testing only. |
| 47 base::LazyInstance<base::Closure> g_focus_change_callback_for_testing = |
| 48 LAZY_INSTANCE_INITIALIZER; |
| 49 |
46 ui::AXTreeUpdate MakeAXTreeUpdate( | 50 ui::AXTreeUpdate MakeAXTreeUpdate( |
47 const ui::AXNodeData& node1, | 51 const ui::AXNodeData& node1, |
48 const ui::AXNodeData& node2 /* = ui::AXNodeData() */, | 52 const ui::AXNodeData& node2 /* = ui::AXNodeData() */, |
49 const ui::AXNodeData& node3 /* = ui::AXNodeData() */, | 53 const ui::AXNodeData& node3 /* = ui::AXNodeData() */, |
50 const ui::AXNodeData& node4 /* = ui::AXNodeData() */, | 54 const ui::AXNodeData& node4 /* = ui::AXNodeData() */, |
51 const ui::AXNodeData& node5 /* = ui::AXNodeData() */, | 55 const ui::AXNodeData& node5 /* = ui::AXNodeData() */, |
52 const ui::AXNodeData& node6 /* = ui::AXNodeData() */, | 56 const ui::AXNodeData& node6 /* = ui::AXNodeData() */, |
53 const ui::AXNodeData& node7 /* = ui::AXNodeData() */, | 57 const ui::AXNodeData& node7 /* = ui::AXNodeData() */, |
54 const ui::AXNodeData& node8 /* = ui::AXNodeData() */, | 58 const ui::AXNodeData& node8 /* = ui::AXNodeData() */, |
55 const ui::AXNodeData& node9 /* = ui::AXNodeData() */, | 59 const ui::AXNodeData& node9 /* = ui::AXNodeData() */, |
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
172 ui::AXNodeData empty_document; | 176 ui::AXNodeData empty_document; |
173 empty_document.id = 0; | 177 empty_document.id = 0; |
174 empty_document.role = ui::AX_ROLE_ROOT_WEB_AREA; | 178 empty_document.role = ui::AX_ROLE_ROOT_WEB_AREA; |
175 ui::AXTreeUpdate update; | 179 ui::AXTreeUpdate update; |
176 update.nodes.push_back(empty_document); | 180 update.nodes.push_back(empty_document); |
177 return update; | 181 return update; |
178 } | 182 } |
179 | 183 |
180 void BrowserAccessibilityManager::FireFocusEventsIfNeeded() { | 184 void BrowserAccessibilityManager::FireFocusEventsIfNeeded() { |
181 BrowserAccessibility* focus = GetFocus(); | 185 BrowserAccessibility* focus = GetFocus(); |
182 if (delegate_ && !delegate_->AccessibilityViewHasFocus()) | |
183 focus = nullptr; | |
184 | 186 |
185 if (!CanFireEvents()) | 187 // Don't fire focus events if the window itself doesn't have focus. |
186 focus = nullptr; | 188 // Bypass this check if a global focus listener was set up for testing |
| 189 // so that the test passes whether the window is active or not. |
| 190 if (!g_focus_change_callback_for_testing.Pointer()) { |
| 191 if (delegate_ && !delegate_->AccessibilityViewHasFocus()) |
| 192 focus = nullptr; |
| 193 |
| 194 if (!CanFireEvents()) |
| 195 focus = nullptr; |
| 196 } |
187 | 197 |
188 // Don't allow the document to be focused if it has no children and | 198 // Don't allow the document to be focused if it has no children and |
189 // hasn't finished loading yet. Wait for at least a tiny bit of content, | 199 // hasn't finished loading yet. Wait for at least a tiny bit of content, |
190 // or for the document to actually finish loading. | 200 // or for the document to actually finish loading. |
191 if (focus && | 201 if (focus && |
192 focus == focus->manager()->GetRoot() && | 202 focus == focus->manager()->GetRoot() && |
193 focus->PlatformChildCount() == 0 && | 203 focus->PlatformChildCount() == 0 && |
194 !focus->HasState(ui::AX_STATE_BUSY) && | 204 !focus->HasState(ui::AX_STATE_BUSY) && |
195 !focus->manager()->GetTreeData().loaded) { | 205 !focus->manager()->GetTreeData().loaded) { |
196 focus = nullptr; | 206 focus = nullptr; |
197 } | 207 } |
198 | 208 |
199 if (focus && focus != last_focused_node_) | 209 if (focus && focus != last_focused_node_) |
200 FireFocusEvent(focus); | 210 FireFocusEvent(focus); |
201 | 211 |
202 last_focused_node_ = focus; | 212 last_focused_node_ = focus; |
203 last_focused_manager_ = focus ? focus->manager() : nullptr; | 213 last_focused_manager_ = focus ? focus->manager() : nullptr; |
204 } | 214 } |
205 | 215 |
206 bool BrowserAccessibilityManager::CanFireEvents() { | 216 bool BrowserAccessibilityManager::CanFireEvents() { |
207 return true; | 217 return true; |
208 } | 218 } |
209 | 219 |
210 void BrowserAccessibilityManager::FireFocusEvent(BrowserAccessibility* node) { | 220 void BrowserAccessibilityManager::FireFocusEvent(BrowserAccessibility* node) { |
211 NotifyAccessibilityEvent(ui::AX_EVENT_FOCUS, node); | 221 NotifyAccessibilityEvent(ui::AX_EVENT_FOCUS, node); |
| 222 |
| 223 if (!g_focus_change_callback_for_testing.Get().is_null()) |
| 224 g_focus_change_callback_for_testing.Get().Run(); |
212 } | 225 } |
213 | 226 |
214 BrowserAccessibility* BrowserAccessibilityManager::GetRoot() { | 227 BrowserAccessibility* BrowserAccessibilityManager::GetRoot() { |
215 // tree_ can be null during destruction. | 228 // tree_ can be null during destruction. |
216 if (!tree_) | 229 if (!tree_) |
217 return nullptr; | 230 return nullptr; |
218 | 231 |
219 // tree_->root() can be null during AXTreeDelegate callbacks. | 232 // tree_->root() can be null during AXTreeDelegate callbacks. |
220 ui::AXNode* root = tree_->root(); | 233 ui::AXNode* root = tree_->root(); |
221 return root ? GetFromAXNode(root) : nullptr; | 234 return root ? GetFromAXNode(root) : nullptr; |
(...skipping 227 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
449 if (!root_manager) | 462 if (!root_manager) |
450 root_manager = this; | 463 root_manager = this; |
451 int32_t focused_tree_id = root_manager->GetTreeData().focused_tree_id; | 464 int32_t focused_tree_id = root_manager->GetTreeData().focused_tree_id; |
452 | 465 |
453 BrowserAccessibilityManager* focused_manager = nullptr; | 466 BrowserAccessibilityManager* focused_manager = nullptr; |
454 if (focused_tree_id) | 467 if (focused_tree_id) |
455 focused_manager =BrowserAccessibilityManager::FromID(focused_tree_id); | 468 focused_manager =BrowserAccessibilityManager::FromID(focused_tree_id); |
456 if (!focused_manager) | 469 if (!focused_manager) |
457 focused_manager = root_manager; | 470 focused_manager = root_manager; |
458 | 471 |
459 int32_t focus_id = focused_manager->GetTreeData().focus_id; | 472 return focused_manager->GetFocusFromThisOrDescendantFrame(); |
460 BrowserAccessibility* obj = focused_manager->GetFromID(focus_id); | 473 } |
| 474 |
| 475 BrowserAccessibility* |
| 476 BrowserAccessibilityManager::GetFocusFromThisOrDescendantFrame() { |
| 477 int32_t focus_id = GetTreeData().focus_id; |
| 478 BrowserAccessibility* obj = GetFromID(focus_id); |
461 if (!obj) | 479 if (!obj) |
462 return focused_manager->GetRoot(); | 480 return GetRoot(); |
463 | 481 |
464 if (obj->HasIntAttribute(ui::AX_ATTR_CHILD_TREE_ID)) { | 482 if (obj->HasIntAttribute(ui::AX_ATTR_CHILD_TREE_ID)) { |
465 BrowserAccessibilityManager* child_manager = | 483 BrowserAccessibilityManager* child_manager = |
466 BrowserAccessibilityManager::FromID( | 484 BrowserAccessibilityManager::FromID( |
467 obj->GetIntAttribute(ui::AX_ATTR_CHILD_TREE_ID)); | 485 obj->GetIntAttribute(ui::AX_ATTR_CHILD_TREE_ID)); |
468 if (child_manager) | 486 if (child_manager) |
469 return child_manager->GetFocus(); | 487 return child_manager->GetFocusFromThisOrDescendantFrame(); |
470 } | 488 } |
471 | 489 |
472 return obj; | 490 return obj; |
473 } | 491 } |
474 | 492 |
475 void BrowserAccessibilityManager::SetFocus(const BrowserAccessibility& node) { | 493 void BrowserAccessibilityManager::SetFocus(const BrowserAccessibility& node) { |
476 if (delegate_) | 494 if (delegate_) |
477 delegate_->AccessibilitySetFocus(node.GetId()); | 495 delegate_->AccessibilitySetFocus(node.GetId()); |
478 } | 496 } |
479 | 497 |
480 void BrowserAccessibilityManager::SetFocusLocallyForTesting( | 498 void BrowserAccessibilityManager::SetFocusLocallyForTesting( |
481 BrowserAccessibility* node) { | 499 BrowserAccessibility* node) { |
482 ui::AXTreeData data = GetTreeData(); | 500 ui::AXTreeData data = GetTreeData(); |
483 data.focus_id = node->GetId(); | 501 data.focus_id = node->GetId(); |
484 tree_->UpdateData(data); | 502 tree_->UpdateData(data); |
485 } | 503 } |
486 | 504 |
| 505 // static |
| 506 void BrowserAccessibilityManager::SetFocusChangeCallbackForTesting( |
| 507 const base::Closure& callback) { |
| 508 g_focus_change_callback_for_testing.Get() = callback; |
| 509 } |
| 510 |
487 void BrowserAccessibilityManager::DoDefaultAction( | 511 void BrowserAccessibilityManager::DoDefaultAction( |
488 const BrowserAccessibility& node) { | 512 const BrowserAccessibility& node) { |
489 if (delegate_) | 513 if (delegate_) |
490 delegate_->AccessibilityDoDefaultAction(node.GetId()); | 514 delegate_->AccessibilityDoDefaultAction(node.GetId()); |
491 } | 515 } |
492 | 516 |
493 void BrowserAccessibilityManager::ScrollToMakeVisible( | 517 void BrowserAccessibilityManager::ScrollToMakeVisible( |
494 const BrowserAccessibility& node, gfx::Rect subfocus) { | 518 const BrowserAccessibility& node, gfx::Rect subfocus) { |
495 if (delegate_) { | 519 if (delegate_) { |
496 delegate_->AccessibilityScrollToMakeVisible(node.GetId(), subfocus); | 520 delegate_->AccessibilityScrollToMakeVisible(node.GetId(), subfocus); |
(...skipping 313 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
810 tree_->CreateTreeSource()); | 834 tree_->CreateTreeSource()); |
811 ui::AXTreeSerializer<const ui::AXNode*, | 835 ui::AXTreeSerializer<const ui::AXNode*, |
812 ui::AXNodeData, | 836 ui::AXNodeData, |
813 ui::AXTreeData> serializer(tree_source.get()); | 837 ui::AXTreeData> serializer(tree_source.get()); |
814 ui::AXTreeUpdate update; | 838 ui::AXTreeUpdate update; |
815 serializer.SerializeChanges(tree_->root(), &update); | 839 serializer.SerializeChanges(tree_->root(), &update); |
816 return update; | 840 return update; |
817 } | 841 } |
818 | 842 |
819 } // namespace content | 843 } // namespace content |
OLD | NEW |