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

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

Issue 1589623002: Keep track of accessibility focus across windows. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: git cl format Created 4 years, 10 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 109 matching lines...) Expand 10 before | Expand all | Expand 10 after
120 auto iter = ax_tree_id_map->find(ax_tree_id); 120 auto iter = ax_tree_id_map->find(ax_tree_id);
121 return iter == ax_tree_id_map->end() ? nullptr : iter->second; 121 return iter == ax_tree_id_map->end() ? nullptr : iter->second;
122 } 122 }
123 123
124 BrowserAccessibilityManager::BrowserAccessibilityManager( 124 BrowserAccessibilityManager::BrowserAccessibilityManager(
125 BrowserAccessibilityDelegate* delegate, 125 BrowserAccessibilityDelegate* delegate,
126 BrowserAccessibilityFactory* factory) 126 BrowserAccessibilityFactory* factory)
127 : delegate_(delegate), 127 : delegate_(delegate),
128 factory_(factory), 128 factory_(factory),
129 tree_(new ui::AXSerializableTree()), 129 tree_(new ui::AXSerializableTree()),
130 focus_(NULL),
131 user_is_navigating_away_(false), 130 user_is_navigating_away_(false),
132 osk_state_(OSK_ALLOWED), 131 osk_state_(OSK_ALLOWED),
133 ax_tree_id_(AXTreeIDRegistry::kNoAXTreeID), 132 ax_tree_id_(AXTreeIDRegistry::kNoAXTreeID),
134 parent_node_id_from_parent_tree_(0) { 133 parent_node_id_from_parent_tree_(0) {
135 tree_->SetDelegate(this); 134 tree_->SetDelegate(this);
136 } 135 }
137 136
138 BrowserAccessibilityManager::BrowserAccessibilityManager( 137 BrowserAccessibilityManager::BrowserAccessibilityManager(
139 const ui::AXTreeUpdate& initial_tree, 138 const ui::AXTreeUpdate& initial_tree,
140 BrowserAccessibilityDelegate* delegate, 139 BrowserAccessibilityDelegate* delegate,
141 BrowserAccessibilityFactory* factory) 140 BrowserAccessibilityFactory* factory)
142 : delegate_(delegate), 141 : delegate_(delegate),
143 factory_(factory), 142 factory_(factory),
144 tree_(new ui::AXSerializableTree()), 143 tree_(new ui::AXSerializableTree()),
145 focus_(NULL),
146 user_is_navigating_away_(false), 144 user_is_navigating_away_(false),
147 osk_state_(OSK_ALLOWED), 145 osk_state_(OSK_ALLOWED),
148 ax_tree_id_(AXTreeIDRegistry::kNoAXTreeID), 146 ax_tree_id_(AXTreeIDRegistry::kNoAXTreeID),
149 parent_node_id_from_parent_tree_(0) { 147 parent_node_id_from_parent_tree_(0) {
150 tree_->SetDelegate(this); 148 tree_->SetDelegate(this);
151 Initialize(initial_tree); 149 Initialize(initial_tree);
152 } 150 }
153 151
154 BrowserAccessibilityManager::~BrowserAccessibilityManager() { 152 BrowserAccessibilityManager::~BrowserAccessibilityManager() {
155 tree_.reset(NULL); 153 tree_.reset(NULL);
156 g_ax_tree_id_map.Get().erase(ax_tree_id_); 154 g_ax_tree_id_map.Get().erase(ax_tree_id_);
157 } 155 }
158 156
159 void BrowserAccessibilityManager::Initialize( 157 void BrowserAccessibilityManager::Initialize(
160 const ui::AXTreeUpdate& initial_tree) { 158 const ui::AXTreeUpdate& initial_tree) {
161 if (!tree_->Unserialize(initial_tree)) { 159 if (!tree_->Unserialize(initial_tree)) {
162 if (delegate_) { 160 if (delegate_) {
163 LOG(ERROR) << tree_->error(); 161 LOG(ERROR) << tree_->error();
164 delegate_->AccessibilityFatalError(); 162 delegate_->AccessibilityFatalError();
165 } else { 163 } else {
166 LOG(FATAL) << tree_->error(); 164 LOG(FATAL) << tree_->error();
167 } 165 }
168 } 166 }
169
170 if (!focus_)
171 SetFocus(tree_->root(), false);
172 } 167 }
173 168
174 // static 169 // static
175 ui::AXTreeUpdate 170 ui::AXTreeUpdate
176 BrowserAccessibilityManager::GetEmptyDocument() { 171 BrowserAccessibilityManager::GetEmptyDocument() {
177 ui::AXNodeData empty_document; 172 ui::AXNodeData empty_document;
178 empty_document.id = 0; 173 empty_document.id = 0;
179 empty_document.role = ui::AX_ROLE_ROOT_WEB_AREA; 174 empty_document.role = ui::AX_ROLE_ROOT_WEB_AREA;
180 ui::AXTreeUpdate update; 175 ui::AXTreeUpdate update;
181 update.nodes.push_back(empty_document); 176 update.nodes.push_back(empty_document);
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
240 } 235 }
241 236
242 return nullptr; 237 return nullptr;
243 } 238 }
244 239
245 const ui::AXTreeData& BrowserAccessibilityManager::GetTreeData() { 240 const ui::AXTreeData& BrowserAccessibilityManager::GetTreeData() {
246 return tree_->data(); 241 return tree_->data();
247 } 242 }
248 243
249 void BrowserAccessibilityManager::OnWindowFocused() { 244 void BrowserAccessibilityManager::OnWindowFocused() {
250 if (focus_) 245 BrowserAccessibility* focus = GetFocus();
251 NotifyAccessibilityEvent(ui::AX_EVENT_FOCUS, GetFromAXNode(focus_)); 246 if (focus)
247 NotifyAccessibilityEvent(ui::AX_EVENT_FOCUS, focus);
252 } 248 }
253 249
254 void BrowserAccessibilityManager::OnWindowBlurred() { 250 void BrowserAccessibilityManager::OnWindowBlurred() {
255 if (focus_) 251 BrowserAccessibility* focus = GetFocus();
256 NotifyAccessibilityEvent(ui::AX_EVENT_BLUR, GetFromAXNode(focus_)); 252 if (focus)
253 NotifyAccessibilityEvent(ui::AX_EVENT_BLUR, focus);
257 } 254 }
258 255
259 void BrowserAccessibilityManager::UserIsNavigatingAway() { 256 void BrowserAccessibilityManager::UserIsNavigatingAway() {
260 user_is_navigating_away_ = true; 257 user_is_navigating_away_ = true;
261 } 258 }
262 259
263 void BrowserAccessibilityManager::UserIsReloading() { 260 void BrowserAccessibilityManager::UserIsReloading() {
264 user_is_navigating_away_ = true; 261 user_is_navigating_away_ = true;
265 } 262 }
266 263
267 void BrowserAccessibilityManager::NavigationSucceeded() { 264 void BrowserAccessibilityManager::NavigationSucceeded() {
268 user_is_navigating_away_ = false; 265 user_is_navigating_away_ = false;
269 } 266 }
270 267
271 void BrowserAccessibilityManager::NavigationFailed() { 268 void BrowserAccessibilityManager::NavigationFailed() {
272 user_is_navigating_away_ = false; 269 user_is_navigating_away_ = false;
273 } 270 }
274 271
275 void BrowserAccessibilityManager::GotMouseDown() { 272 void BrowserAccessibilityManager::GotMouseDown() {
276 if (!focus_) 273 BrowserAccessibility* focus = GetFocus();
274 if (!focus)
277 return; 275 return;
278 276
279 osk_state_ = OSK_ALLOWED_WITHIN_FOCUSED_OBJECT; 277 osk_state_ = OSK_ALLOWED_WITHIN_FOCUSED_OBJECT;
280 NotifyAccessibilityEvent(ui::AX_EVENT_FOCUS, GetFromAXNode(focus_)); 278 NotifyAccessibilityEvent(ui::AX_EVENT_FOCUS, focus);
281 } 279 }
282 280
283 bool BrowserAccessibilityManager::UseRootScrollOffsetsWhenComputingBounds() { 281 bool BrowserAccessibilityManager::UseRootScrollOffsetsWhenComputingBounds() {
284 return true; 282 return true;
285 } 283 }
286 284
287 void BrowserAccessibilityManager::OnAccessibilityEvents( 285 void BrowserAccessibilityManager::OnAccessibilityEvents(
288 const std::vector<AXEventNotificationDetails>& details) { 286 const std::vector<AXEventNotificationDetails>& details) {
289 bool should_send_initial_focus = false;
290
291 // Process all changes to the accessibility tree first. 287 // Process all changes to the accessibility tree first.
292 for (uint32_t index = 0; index < details.size(); ++index) { 288 for (uint32_t index = 0; index < details.size(); ++index) {
293 const AXEventNotificationDetails& detail = details[index]; 289 const AXEventNotificationDetails& detail = details[index];
294 if (!tree_->Unserialize(detail.update)) { 290 if (!tree_->Unserialize(detail.update)) {
295 if (delegate_) { 291 if (delegate_) {
296 LOG(ERROR) << tree_->error(); 292 LOG(ERROR) << tree_->error();
297 delegate_->AccessibilityFatalError(); 293 delegate_->AccessibilityFatalError();
298 } else { 294 } else {
299 CHECK(false) << tree_->error(); 295 CHECK(false) << tree_->error();
300 } 296 }
301 return; 297 return;
302 } 298 }
David Tseng 2016/01/28 02:00:56 Are there clients on other platforms that may need
303
304 // Set focus to the root if it's not anywhere else.
305 if (!focus_) {
306 SetFocus(tree_->root(), false);
307 should_send_initial_focus = true;
308 }
309 } 299 }
310 300
311 if (should_send_initial_focus && NativeViewHasFocus())
312 NotifyAccessibilityEvent(ui::AX_EVENT_FOCUS, GetFromAXNode(focus_));
313
314 // Now iterate over the events again and fire the events. 301 // Now iterate over the events again and fire the events.
315 for (uint32_t index = 0; index < details.size(); index++) { 302 for (uint32_t index = 0; index < details.size(); index++) {
316 const AXEventNotificationDetails& detail = details[index]; 303 const AXEventNotificationDetails& detail = details[index];
317 304
318 // Find the node corresponding to the id that's the target of the 305 // Find the node corresponding to the id that's the target of the
319 // event (which may not be the root of the update tree). 306 // event (which may not be the root of the update tree).
320 ui::AXNode* node = tree_->GetFromId(detail.id); 307 ui::AXNode* node = tree_->GetFromId(detail.id);
321 if (!node) 308 if (!node)
322 continue; 309 continue;
323 310
324 ui::AXEvent event_type = detail.event_type; 311 ui::AXEvent event_type = detail.event_type;
325 if (event_type == ui::AX_EVENT_FOCUS || 312 if (event_type == ui::AX_EVENT_FOCUS ||
326 event_type == ui::AX_EVENT_BLUR) { 313 event_type == ui::AX_EVENT_BLUR) {
327 SetFocus(node, false);
328
329 if (osk_state_ != OSK_DISALLOWED_BECAUSE_TAB_HIDDEN && 314 if (osk_state_ != OSK_DISALLOWED_BECAUSE_TAB_HIDDEN &&
330 osk_state_ != OSK_DISALLOWED_BECAUSE_TAB_JUST_APPEARED) 315 osk_state_ != OSK_DISALLOWED_BECAUSE_TAB_JUST_APPEARED)
331 osk_state_ = OSK_ALLOWED; 316 osk_state_ = OSK_ALLOWED;
332 317
333 // Don't send a native focus event if the window itself doesn't 318 // Don't send a native focus event if the window itself doesn't
334 // have focus. 319 // have focus.
335 if (!NativeViewHasFocus()) 320 if (!NativeViewHasFocus())
336 continue; 321 continue;
337 } 322 }
338 323
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
383 if (ancestor->PlatformIsLeaf()) 368 if (ancestor->PlatformIsLeaf())
384 node = ancestor; 369 node = ancestor;
385 ancestor = ancestor->GetParent(); 370 ancestor = ancestor->GetParent();
386 } 371 }
387 372
388 // The "scrolled to anchor" notification is a great way to get a 373 // The "scrolled to anchor" notification is a great way to get a
389 // screen reader to jump directly to a specific location in a document. 374 // screen reader to jump directly to a specific location in a document.
390 NotifyAccessibilityEvent(ui::AX_EVENT_SCROLLED_TO_ANCHOR, node); 375 NotifyAccessibilityEvent(ui::AX_EVENT_SCROLLED_TO_ANCHOR, node);
391 } 376 }
392 377
393 BrowserAccessibility* BrowserAccessibilityManager::GetActiveDescendantFocus( 378 BrowserAccessibility* BrowserAccessibilityManager::GetActiveDescendantFocus() {
394 BrowserAccessibility* root) { 379 BrowserAccessibility* focus = GetFocus();
395 BrowserAccessibility* node = BrowserAccessibilityManager::GetFocus(root); 380 if (!focus)
396 if (!node)
397 return NULL; 381 return NULL;
398 382
399 int active_descendant_id; 383 int active_descendant_id;
400 if (node->GetIntAttribute(ui::AX_ATTR_ACTIVEDESCENDANT_ID, 384 if (focus->GetIntAttribute(ui::AX_ATTR_ACTIVEDESCENDANT_ID,
401 &active_descendant_id)) { 385 &active_descendant_id)) {
402 BrowserAccessibility* active_descendant = 386 BrowserAccessibility* active_descendant =
403 node->manager()->GetFromID(active_descendant_id); 387 focus->manager()->GetFromID(active_descendant_id);
404 if (active_descendant) 388 if (active_descendant)
405 return active_descendant; 389 return active_descendant;
406 } 390 }
407 return node; 391 return focus;
408 } 392 }
409 393
410 bool BrowserAccessibilityManager::NativeViewHasFocus() { 394 bool BrowserAccessibilityManager::NativeViewHasFocus() {
411 BrowserAccessibilityDelegate* delegate = GetDelegateFromRootManager(); 395 BrowserAccessibilityDelegate* delegate = GetDelegateFromRootManager();
412 if (delegate) 396 if (delegate)
413 return delegate->AccessibilityViewHasFocus(); 397 return delegate->AccessibilityViewHasFocus();
414 return false; 398 return false;
415 } 399 }
416 400
417 BrowserAccessibility* BrowserAccessibilityManager::GetFocus( 401 BrowserAccessibility* BrowserAccessibilityManager::GetFocus() {
418 BrowserAccessibility* root) { 402 int32_t focus_id = GetTreeData().focus_id;
419 if (!focus_) 403 BrowserAccessibility* obj = GetFromID(focus_id);
420 return nullptr; 404 if (!obj)
405 return GetRoot();
421 406
422 if (root && !focus_->IsDescendantOf(root->node()))
423 return nullptr;
424
425 BrowserAccessibility* obj = GetFromAXNode(focus_);
426 DCHECK(obj);
427 if (obj->HasIntAttribute(ui::AX_ATTR_CHILD_TREE_ID)) { 407 if (obj->HasIntAttribute(ui::AX_ATTR_CHILD_TREE_ID)) {
428 BrowserAccessibilityManager* child_manager = 408 BrowserAccessibilityManager* child_manager =
429 BrowserAccessibilityManager::FromID( 409 BrowserAccessibilityManager::FromID(
430 obj->GetIntAttribute(ui::AX_ATTR_CHILD_TREE_ID)); 410 obj->GetIntAttribute(ui::AX_ATTR_CHILD_TREE_ID));
431 if (child_manager) 411 if (child_manager)
432 return child_manager->GetFocus(child_manager->GetRoot()); 412 return child_manager->GetFocus();
433 } 413 }
434 414
435 return obj; 415 return obj;
436 } 416 }
437 417
438 void BrowserAccessibilityManager::SetFocus(ui::AXNode* node, bool notify) { 418 void BrowserAccessibilityManager::SetFocus(const BrowserAccessibility& node) {
439 if (focus_ != node) 419 if (delegate_)
440 focus_ = node; 420 delegate_->AccessibilitySetFocus(node.GetId());
441
442 if (notify && node && delegate_)
443 delegate_->AccessibilitySetFocus(node->id());
444 }
445
446 void BrowserAccessibilityManager::SetFocus(
447 BrowserAccessibility* obj, bool notify) {
448 if (obj->node())
449 SetFocus(obj->node(), notify);
450 } 421 }
451 422
452 void BrowserAccessibilityManager::DoDefaultAction( 423 void BrowserAccessibilityManager::DoDefaultAction(
453 const BrowserAccessibility& node) { 424 const BrowserAccessibility& node) {
454 if (delegate_) 425 if (delegate_)
455 delegate_->AccessibilityDoDefaultAction(node.GetId()); 426 delegate_->AccessibilityDoDefaultAction(node.GetId());
456 } 427 }
457 428
458 void BrowserAccessibilityManager::ScrollToMakeVisible( 429 void BrowserAccessibilityManager::ScrollToMakeVisible(
459 const BrowserAccessibility& node, gfx::Rect subfocus) { 430 const BrowserAccessibility& node, gfx::Rect subfocus) {
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
551 522
552 return next_node; 523 return next_node;
553 } 524 }
554 525
555 void BrowserAccessibilityManager::OnTreeDataChanged(ui::AXTree* tree) { 526 void BrowserAccessibilityManager::OnTreeDataChanged(ui::AXTree* tree) {
556 } 527 }
557 528
558 void BrowserAccessibilityManager::OnNodeWillBeDeleted(ui::AXTree* tree, 529 void BrowserAccessibilityManager::OnNodeWillBeDeleted(ui::AXTree* tree,
559 ui::AXNode* node) { 530 ui::AXNode* node) {
560 DCHECK(node); 531 DCHECK(node);
561 if (node == focus_ && tree_) {
562 if (node != tree_->root())
563 SetFocus(tree_->root(), false);
564 else
565 focus_ = NULL;
566 }
567 if (id_wrapper_map_.find(node->id()) == id_wrapper_map_.end()) 532 if (id_wrapper_map_.find(node->id()) == id_wrapper_map_.end())
568 return; 533 return;
569 GetFromAXNode(node)->Destroy(); 534 GetFromAXNode(node)->Destroy();
570 id_wrapper_map_.erase(node->id()); 535 id_wrapper_map_.erase(node->id());
571 } 536 }
572 537
573 void BrowserAccessibilityManager::OnSubtreeWillBeDeleted(ui::AXTree* tree, 538 void BrowserAccessibilityManager::OnSubtreeWillBeDeleted(ui::AXTree* tree,
574 ui::AXNode* node) { 539 ui::AXNode* node) {
575 DCHECK(node); 540 DCHECK(node);
576 BrowserAccessibility* obj = GetFromAXNode(node); 541 BrowserAccessibility* obj = GetFromAXNode(node);
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
641 tree_->CreateTreeSource()); 606 tree_->CreateTreeSource());
642 ui::AXTreeSerializer<const ui::AXNode*, 607 ui::AXTreeSerializer<const ui::AXNode*,
643 ui::AXNodeData, 608 ui::AXNodeData,
644 ui::AXTreeData> serializer(tree_source.get()); 609 ui::AXTreeData> serializer(tree_source.get());
645 ui::AXTreeUpdate update; 610 ui::AXTreeUpdate update;
646 serializer.SerializeChanges(tree_->root(), &update); 611 serializer.SerializeChanges(tree_->root(), &update);
647 return update; 612 return update;
648 } 613 }
649 614
650 } // namespace content 615 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698