| 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), | |
| 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 Loading... |
| 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 Loading... |
| 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 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 547 | 525 |
| 548 return next_node; | 526 return next_node; |
| 549 } | 527 } |
| 550 | 528 |
| 551 void BrowserAccessibilityManager::OnTreeDataChanged(ui::AXTree* tree) { | 529 void BrowserAccessibilityManager::OnTreeDataChanged(ui::AXTree* tree) { |
| 552 } | 530 } |
| 553 | 531 |
| 554 void BrowserAccessibilityManager::OnNodeWillBeDeleted(ui::AXTree* tree, | 532 void BrowserAccessibilityManager::OnNodeWillBeDeleted(ui::AXTree* tree, |
| 555 ui::AXNode* node) { | 533 ui::AXNode* node) { |
| 556 DCHECK(node); | 534 DCHECK(node); |
| 557 if (node == focus_ && tree_) { | |
| 558 if (node != tree_->root()) | |
| 559 SetFocus(tree_->root(), false); | |
| 560 else | |
| 561 focus_ = NULL; | |
| 562 } | |
| 563 if (id_wrapper_map_.find(node->id()) == id_wrapper_map_.end()) | 535 if (id_wrapper_map_.find(node->id()) == id_wrapper_map_.end()) |
| 564 return; | 536 return; |
| 565 GetFromAXNode(node)->Destroy(); | 537 GetFromAXNode(node)->Destroy(); |
| 566 id_wrapper_map_.erase(node->id()); | 538 id_wrapper_map_.erase(node->id()); |
| 567 } | 539 } |
| 568 | 540 |
| 569 void BrowserAccessibilityManager::OnSubtreeWillBeDeleted(ui::AXTree* tree, | 541 void BrowserAccessibilityManager::OnSubtreeWillBeDeleted(ui::AXTree* tree, |
| 570 ui::AXNode* node) { | 542 ui::AXNode* node) { |
| 571 DCHECK(node); | 543 DCHECK(node); |
| 572 BrowserAccessibility* obj = GetFromAXNode(node); | 544 BrowserAccessibility* obj = GetFromAXNode(node); |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 637 tree_->CreateTreeSource()); | 609 tree_->CreateTreeSource()); |
| 638 ui::AXTreeSerializer<const ui::AXNode*, | 610 ui::AXTreeSerializer<const ui::AXNode*, |
| 639 ui::AXNodeData, | 611 ui::AXNodeData, |
| 640 ui::AXTreeData> serializer(tree_source.get()); | 612 ui::AXTreeData> serializer(tree_source.get()); |
| 641 ui::AXTreeUpdate update; | 613 ui::AXTreeUpdate update; |
| 642 serializer.SerializeChanges(tree_->root(), &update); | 614 serializer.SerializeChanges(tree_->root(), &update); |
| 643 return update; | 615 return update; |
| 644 } | 616 } |
| 645 | 617 |
| 646 } // namespace content | 618 } // namespace content |
| OLD | NEW |