Chromium Code Reviews| 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 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 |
| OLD | NEW |