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 |