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