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

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

Issue 1705853002: NOT FOR REVIEW. ax tree focus with debugging (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fixed crash 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 105 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698