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

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

Issue 1815933002: Fix WebView accessibility (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Add browser test for focusing into a web view Created 4 years, 9 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
OLDNEW
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
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
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()) {
dcheng 2016/03/24 18:15:11 I wonder if it'd be possible to snoop IPC messages
dmazzoni 2016/03/25 05:02:22 That's how most of the tests in content/ work, we
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 if (g_focus_change_callback_for_testing.Pointer())
223 g_focus_change_callback_for_testing.Get().Run();
212 } 224 }
213 225
214 BrowserAccessibility* BrowserAccessibilityManager::GetRoot() { 226 BrowserAccessibility* BrowserAccessibilityManager::GetRoot() {
215 // tree_ can be null during destruction. 227 // tree_ can be null during destruction.
216 if (!tree_) 228 if (!tree_)
217 return nullptr; 229 return nullptr;
218 230
219 // tree_->root() can be null during AXTreeDelegate callbacks. 231 // tree_->root() can be null during AXTreeDelegate callbacks.
220 ui::AXNode* root = tree_->root(); 232 ui::AXNode* root = tree_->root();
221 return root ? GetFromAXNode(root) : nullptr; 233 return root ? GetFromAXNode(root) : nullptr;
(...skipping 227 matching lines...) Expand 10 before | Expand all | Expand 10 after
449 if (!root_manager) 461 if (!root_manager)
450 root_manager = this; 462 root_manager = this;
451 int32_t focused_tree_id = root_manager->GetTreeData().focused_tree_id; 463 int32_t focused_tree_id = root_manager->GetTreeData().focused_tree_id;
452 464
453 BrowserAccessibilityManager* focused_manager = nullptr; 465 BrowserAccessibilityManager* focused_manager = nullptr;
454 if (focused_tree_id) 466 if (focused_tree_id)
455 focused_manager =BrowserAccessibilityManager::FromID(focused_tree_id); 467 focused_manager =BrowserAccessibilityManager::FromID(focused_tree_id);
456 if (!focused_manager) 468 if (!focused_manager)
457 focused_manager = root_manager; 469 focused_manager = root_manager;
458 470
459 int32_t focus_id = focused_manager->GetTreeData().focus_id; 471 return focused_manager->GetFocusFromThisOrDescendantFrame();
460 BrowserAccessibility* obj = focused_manager->GetFromID(focus_id); 472 }
473
474 BrowserAccessibility*
475 BrowserAccessibilityManager::GetFocusFromThisOrDescendantFrame() {
476 int32_t focus_id = GetTreeData().focus_id;
477 BrowserAccessibility* obj = GetFromID(focus_id);
461 if (!obj) 478 if (!obj)
462 return focused_manager->GetRoot(); 479 return GetRoot();
463 480
464 if (obj->HasIntAttribute(ui::AX_ATTR_CHILD_TREE_ID)) { 481 if (obj->HasIntAttribute(ui::AX_ATTR_CHILD_TREE_ID)) {
465 BrowserAccessibilityManager* child_manager = 482 BrowserAccessibilityManager* child_manager =
466 BrowserAccessibilityManager::FromID( 483 BrowserAccessibilityManager::FromID(
467 obj->GetIntAttribute(ui::AX_ATTR_CHILD_TREE_ID)); 484 obj->GetIntAttribute(ui::AX_ATTR_CHILD_TREE_ID));
468 if (child_manager) 485 if (child_manager)
469 return child_manager->GetFocus(); 486 return child_manager->GetFocusFromThisOrDescendantFrame();
470 } 487 }
471 488
472 return obj; 489 return obj;
473 } 490 }
474 491
475 void BrowserAccessibilityManager::SetFocus(const BrowserAccessibility& node) { 492 void BrowserAccessibilityManager::SetFocus(const BrowserAccessibility& node) {
476 if (delegate_) 493 if (delegate_)
477 delegate_->AccessibilitySetFocus(node.GetId()); 494 delegate_->AccessibilitySetFocus(node.GetId());
478 } 495 }
479 496
480 void BrowserAccessibilityManager::SetFocusLocallyForTesting( 497 void BrowserAccessibilityManager::SetFocusLocallyForTesting(
481 BrowserAccessibility* node) { 498 BrowserAccessibility* node) {
482 ui::AXTreeData data = GetTreeData(); 499 ui::AXTreeData data = GetTreeData();
483 data.focus_id = node->GetId(); 500 data.focus_id = node->GetId();
484 tree_->UpdateData(data); 501 tree_->UpdateData(data);
485 } 502 }
486 503
504 // static
505 void BrowserAccessibilityManager::SetFocusChangeCallbackForTesting(
506 base::Closure callback) {
507 g_focus_change_callback_for_testing.Get() = callback;
508 }
509
487 void BrowserAccessibilityManager::DoDefaultAction( 510 void BrowserAccessibilityManager::DoDefaultAction(
488 const BrowserAccessibility& node) { 511 const BrowserAccessibility& node) {
489 if (delegate_) 512 if (delegate_)
490 delegate_->AccessibilityDoDefaultAction(node.GetId()); 513 delegate_->AccessibilityDoDefaultAction(node.GetId());
491 } 514 }
492 515
493 void BrowserAccessibilityManager::ScrollToMakeVisible( 516 void BrowserAccessibilityManager::ScrollToMakeVisible(
494 const BrowserAccessibility& node, gfx::Rect subfocus) { 517 const BrowserAccessibility& node, gfx::Rect subfocus) {
495 if (delegate_) { 518 if (delegate_) {
496 delegate_->AccessibilityScrollToMakeVisible(node.GetId(), subfocus); 519 delegate_->AccessibilityScrollToMakeVisible(node.GetId(), subfocus);
(...skipping 313 matching lines...) Expand 10 before | Expand all | Expand 10 after
810 tree_->CreateTreeSource()); 833 tree_->CreateTreeSource());
811 ui::AXTreeSerializer<const ui::AXNode*, 834 ui::AXTreeSerializer<const ui::AXNode*,
812 ui::AXNodeData, 835 ui::AXNodeData,
813 ui::AXTreeData> serializer(tree_source.get()); 836 ui::AXTreeData> serializer(tree_source.get());
814 ui::AXTreeUpdate update; 837 ui::AXTreeUpdate update;
815 serializer.SerializeChanges(tree_->root(), &update); 838 serializer.SerializeChanges(tree_->root(), &update);
816 return update; 839 return update;
817 } 840 }
818 841
819 } // namespace content 842 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698