| 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_win.h" | 5 #include "content/browser/accessibility/browser_accessibility_manager_win.h" |
| 6 | 6 |
| 7 #include <stddef.h> | 7 #include <stddef.h> |
| 8 #include <stdint.h> | 8 #include <stdint.h> |
| 9 | 9 |
| 10 #include <vector> | 10 #include <vector> |
| 11 | 11 |
| 12 #include "base/command_line.h" | 12 #include "base/command_line.h" |
| 13 #include "base/win/scoped_comptr.h" | 13 #include "base/win/scoped_comptr.h" |
| 14 #include "base/win/windows_version.h" | 14 #include "base/win/windows_version.h" |
| 15 #include "content/browser/accessibility/browser_accessibility_state_impl.h" | 15 #include "content/browser/accessibility/browser_accessibility_state_impl.h" |
| 16 #include "content/browser/accessibility/browser_accessibility_win.h" | 16 #include "content/browser/accessibility/browser_accessibility_win.h" |
| 17 #include "content/browser/renderer_host/legacy_render_widget_host_win.h" | 17 #include "content/browser/renderer_host/legacy_render_widget_host_win.h" |
| 18 #include "content/common/accessibility_messages.h" | 18 #include "content/common/accessibility_messages.h" |
| 19 #include "ui/base/win/atl_module.h" | 19 #include "ui/base/win/atl_module.h" |
| 20 | 20 |
| 21 namespace content { | 21 namespace content { |
| 22 | 22 |
| 23 // Map from unique_id_win to BrowserAccessibility | |
| 24 using UniqueIDWinMap = base::hash_map<LONG, BrowserAccessibility*>; | |
| 25 base::LazyInstance<UniqueIDWinMap> g_unique_id_map = LAZY_INSTANCE_INITIALIZER; | |
| 26 | |
| 27 // static | 23 // static |
| 28 BrowserAccessibilityManager* BrowserAccessibilityManager::Create( | 24 BrowserAccessibilityManager* BrowserAccessibilityManager::Create( |
| 29 const ui::AXTreeUpdate& initial_tree, | 25 const ui::AXTreeUpdate& initial_tree, |
| 30 BrowserAccessibilityDelegate* delegate, | 26 BrowserAccessibilityDelegate* delegate, |
| 31 BrowserAccessibilityFactory* factory) { | 27 BrowserAccessibilityFactory* factory) { |
| 32 return new BrowserAccessibilityManagerWin(initial_tree, delegate, factory); | 28 return new BrowserAccessibilityManagerWin(initial_tree, delegate, factory); |
| 33 } | 29 } |
| 34 | 30 |
| 35 BrowserAccessibilityManagerWin* | 31 BrowserAccessibilityManagerWin* |
| 36 BrowserAccessibilityManager::ToBrowserAccessibilityManagerWin() { | 32 BrowserAccessibilityManager::ToBrowserAccessibilityManagerWin() { |
| (...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 142 return; | 138 return; |
| 143 } | 139 } |
| 144 | 140 |
| 145 // If a focus event is needed on the root, fire that first before | 141 // If a focus event is needed on the root, fire that first before |
| 146 // this event. | 142 // this event. |
| 147 if (event == EVENT_OBJECT_FOCUS && node == GetRoot()) | 143 if (event == EVENT_OBJECT_FOCUS && node == GetRoot()) |
| 148 focus_event_on_root_needed_ = false; | 144 focus_event_on_root_needed_ = false; |
| 149 else if (focus_event_on_root_needed_) | 145 else if (focus_event_on_root_needed_) |
| 150 OnWindowFocused(); | 146 OnWindowFocused(); |
| 151 | 147 |
| 152 LONG child_id = node->ToBrowserAccessibilityWin()->unique_id_win(); | 148 // Pass the negation of this node's unique id in the |child_id| |
| 149 // argument to NotifyWinEvent; the AT client will then call get_accChild |
| 150 // on the HWND's accessibility object and pass it that same id, which |
| 151 // we can use to retrieve the IAccessible for this node. |
| 152 LONG child_id = -node->unique_id(); |
| 153 ::NotifyWinEvent(event, hwnd, OBJID_CLIENT, child_id); | 153 ::NotifyWinEvent(event, hwnd, OBJID_CLIENT, child_id); |
| 154 } | 154 } |
| 155 | 155 |
| 156 void BrowserAccessibilityManagerWin::OnIAccessible2Used() { | 156 void BrowserAccessibilityManagerWin::OnIAccessible2Used() { |
| 157 BrowserAccessibilityStateImpl::GetInstance()->OnScreenReaderDetected(); | 157 BrowserAccessibilityStateImpl::GetInstance()->OnScreenReaderDetected(); |
| 158 } | 158 } |
| 159 | 159 |
| 160 void BrowserAccessibilityManagerWin::OnWindowFocused() { | 160 void BrowserAccessibilityManagerWin::OnWindowFocused() { |
| 161 // Make sure we don't call this recursively. | 161 // Make sure we don't call this recursively. |
| 162 if (inside_on_window_focused_) | 162 if (inside_on_window_focused_) |
| (...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 286 } | 286 } |
| 287 default: | 287 default: |
| 288 // Not all WebKit accessibility events result in a Windows | 288 // Not all WebKit accessibility events result in a Windows |
| 289 // accessibility notification. | 289 // accessibility notification. |
| 290 break; | 290 break; |
| 291 } | 291 } |
| 292 | 292 |
| 293 if (!node) | 293 if (!node) |
| 294 return; | 294 return; |
| 295 | 295 |
| 296 if (event_id != EVENT_MIN) { | 296 if (event_id != EVENT_MIN) |
| 297 // Pass the node's unique id in the |child_id| argument to NotifyWinEvent; | |
| 298 // the AT client will then call get_accChild on the HWND's accessibility | |
| 299 // object and pass it that same id, which we can use to retrieve the | |
| 300 // IAccessible for this node. | |
| 301 MaybeCallNotifyWinEvent(event_id, node); | 297 MaybeCallNotifyWinEvent(event_id, node); |
| 302 } | 298 |
| 303 | 299 |
| 304 // If this is a layout complete notification (sent when a container scrolls) | 300 // If this is a layout complete notification (sent when a container scrolls) |
| 305 // and there is a descendant tracked object, send a notification on it. | 301 // and there is a descendant tracked object, send a notification on it. |
| 306 // TODO(dmazzoni): remove once http://crbug.com/113483 is fixed. | 302 // TODO(dmazzoni): remove once http://crbug.com/113483 is fixed. |
| 307 if (event_type == ui::AX_EVENT_LAYOUT_COMPLETE && | 303 if (event_type == ui::AX_EVENT_LAYOUT_COMPLETE && |
| 308 tracked_scroll_object_ && | 304 tracked_scroll_object_ && |
| 309 tracked_scroll_object_->IsDescendantOf(node)) { | 305 tracked_scroll_object_->IsDescendantOf(node)) { |
| 310 MaybeCallNotifyWinEvent( | 306 MaybeCallNotifyWinEvent( |
| 311 IA2_EVENT_VISIBLE_DATA_CHANGED, tracked_scroll_object_); | 307 IA2_EVENT_VISIBLE_DATA_CHANGED, tracked_scroll_object_); |
| 312 tracked_scroll_object_->Release(); | 308 tracked_scroll_object_->Release(); |
| 313 tracked_scroll_object_ = NULL; | 309 tracked_scroll_object_ = NULL; |
| 314 } | 310 } |
| 315 } | 311 } |
| 316 | 312 |
| 317 void BrowserAccessibilityManagerWin::OnNodeCreated(ui::AXTree* tree, | 313 void BrowserAccessibilityManagerWin::OnNodeCreated(ui::AXTree* tree, |
| 318 ui::AXNode* node) { | 314 ui::AXNode* node) { |
| 319 DCHECK(node); | 315 DCHECK(node); |
| 320 BrowserAccessibilityManager::OnNodeCreated(tree, node); | 316 BrowserAccessibilityManager::OnNodeCreated(tree, node); |
| 321 BrowserAccessibility* obj = GetFromAXNode(node); | 317 BrowserAccessibility* obj = GetFromAXNode(node); |
| 322 if (!obj) | 318 if (!obj) |
| 323 return; | 319 return; |
| 324 if (!obj->IsNative()) | 320 if (!obj->IsNative()) |
| 325 return; | 321 return; |
| 326 LONG unique_id_win = obj->ToBrowserAccessibilityWin()->unique_id_win(); | |
| 327 g_unique_id_map.Get()[unique_id_win] = obj; | |
| 328 } | 322 } |
| 329 | 323 |
| 330 void BrowserAccessibilityManagerWin::OnNodeWillBeDeleted(ui::AXTree* tree, | 324 void BrowserAccessibilityManagerWin::OnNodeWillBeDeleted(ui::AXTree* tree, |
| 331 ui::AXNode* node) { | 325 ui::AXNode* node) { |
| 332 DCHECK(node); | 326 DCHECK(node); |
| 333 BrowserAccessibility* obj = GetFromAXNode(node); | 327 BrowserAccessibility* obj = GetFromAXNode(node); |
| 334 if (obj && obj->IsNative()) { | 328 if (obj && obj->IsNative()) { |
| 335 g_unique_id_map.Get().erase( | |
| 336 obj->ToBrowserAccessibilityWin()->unique_id_win()); | |
| 337 if (obj == tracked_scroll_object_) { | 329 if (obj == tracked_scroll_object_) { |
| 338 tracked_scroll_object_->Release(); | 330 tracked_scroll_object_->Release(); |
| 339 tracked_scroll_object_ = NULL; | 331 tracked_scroll_object_ = NULL; |
| 340 } | 332 } |
| 341 } | 333 } |
| 342 | 334 |
| 343 // Call the inherited function at the bottom, otherwise our call to | 335 // Call the inherited function at the bottom, otherwise our call to |
| 344 // |GetFromAXNode|, above, will fail! | 336 // |GetFromAXNode|, above, will fail! |
| 345 BrowserAccessibilityManager::OnNodeWillBeDeleted(tree, node); | 337 BrowserAccessibilityManager::OnNodeWillBeDeleted(tree, node); |
| 346 } | 338 } |
| (...skipping 13 matching lines...) Expand all Loading... |
| 360 | 352 |
| 361 // Do a sequence of Windows-specific updates on each node. Each one is | 353 // Do a sequence of Windows-specific updates on each node. Each one is |
| 362 // done in a single pass that must complete before the next step starts. | 354 // done in a single pass that must complete before the next step starts. |
| 363 // The first step moves win_attributes_ to old_win_attributes_ and then | 355 // The first step moves win_attributes_ to old_win_attributes_ and then |
| 364 // recomputes all of win_attributes_ other than IAccessibleText. | 356 // recomputes all of win_attributes_ other than IAccessibleText. |
| 365 for (size_t i = 0; i < changes.size(); ++i) { | 357 for (size_t i = 0; i < changes.size(); ++i) { |
| 366 const ui::AXNode* changed_node = changes[i].node; | 358 const ui::AXNode* changed_node = changes[i].node; |
| 367 DCHECK(changed_node); | 359 DCHECK(changed_node); |
| 368 BrowserAccessibility* obj = GetFromAXNode(changed_node); | 360 BrowserAccessibility* obj = GetFromAXNode(changed_node); |
| 369 if (obj && obj->IsNative() && !obj->PlatformIsChildOfLeaf()) | 361 if (obj && obj->IsNative() && !obj->PlatformIsChildOfLeaf()) |
| 370 obj->ToBrowserAccessibilityWin()->UpdateStep1ComputeWinAttributes(); | 362 ToBrowserAccessibilityWin(obj)->UpdateStep1ComputeWinAttributes(); |
| 371 } | 363 } |
| 372 | 364 |
| 373 // The next step updates the hypertext of each node, which is a | 365 // The next step updates the hypertext of each node, which is a |
| 374 // concatenation of all of its child text nodes, so it can't run until | 366 // concatenation of all of its child text nodes, so it can't run until |
| 375 // the text of all of the nodes was computed in the previous step. | 367 // the text of all of the nodes was computed in the previous step. |
| 376 for (size_t i = 0; i < changes.size(); ++i) { | 368 for (size_t i = 0; i < changes.size(); ++i) { |
| 377 const ui::AXNode* changed_node = changes[i].node; | 369 const ui::AXNode* changed_node = changes[i].node; |
| 378 DCHECK(changed_node); | 370 DCHECK(changed_node); |
| 379 BrowserAccessibility* obj = GetFromAXNode(changed_node); | 371 BrowserAccessibility* obj = GetFromAXNode(changed_node); |
| 380 if (obj && obj->IsNative() && !obj->PlatformIsChildOfLeaf()) | 372 if (obj && obj->IsNative() && !obj->PlatformIsChildOfLeaf()) |
| 381 obj->ToBrowserAccessibilityWin()->UpdateStep2ComputeHypertext(); | 373 ToBrowserAccessibilityWin(obj)->UpdateStep2ComputeHypertext(); |
| 382 } | 374 } |
| 383 | 375 |
| 384 // The third step fires events on nodes based on what's changed - like | 376 // The third step fires events on nodes based on what's changed - like |
| 385 // if the name, value, or description changed, or if the hypertext had | 377 // if the name, value, or description changed, or if the hypertext had |
| 386 // text inserted or removed. It's able to figure out exactly what changed | 378 // text inserted or removed. It's able to figure out exactly what changed |
| 387 // because we still have old_win_attributes_ populated. | 379 // because we still have old_win_attributes_ populated. |
| 388 // This step has to run after the previous two steps complete because the | 380 // This step has to run after the previous two steps complete because the |
| 389 // client may walk the tree when it receives any of these events. | 381 // client may walk the tree when it receives any of these events. |
| 390 // At the end, it deletes old_win_attributes_ since they're not needed | 382 // At the end, it deletes old_win_attributes_ since they're not needed |
| 391 // anymore. | 383 // anymore. |
| 392 for (size_t i = 0; i < changes.size(); ++i) { | 384 for (size_t i = 0; i < changes.size(); ++i) { |
| 393 const ui::AXNode* changed_node = changes[i].node; | 385 const ui::AXNode* changed_node = changes[i].node; |
| 394 DCHECK(changed_node); | 386 DCHECK(changed_node); |
| 395 BrowserAccessibility* obj = GetFromAXNode(changed_node); | 387 BrowserAccessibility* obj = GetFromAXNode(changed_node); |
| 396 if (obj && obj->IsNative() && !obj->PlatformIsChildOfLeaf()) { | 388 if (obj && obj->IsNative() && !obj->PlatformIsChildOfLeaf()) { |
| 397 obj->ToBrowserAccessibilityWin()->UpdateStep3FireEvents( | 389 ToBrowserAccessibilityWin(obj)->UpdateStep3FireEvents( |
| 398 changes[i].type == AXTreeDelegate::SUBTREE_CREATED); | 390 changes[i].type == AXTreeDelegate::SUBTREE_CREATED); |
| 399 } | 391 } |
| 400 } | 392 } |
| 401 } | 393 } |
| 402 | 394 |
| 403 void BrowserAccessibilityManagerWin::TrackScrollingObject( | 395 void BrowserAccessibilityManagerWin::TrackScrollingObject( |
| 404 BrowserAccessibilityWin* node) { | 396 BrowserAccessibilityWin* node) { |
| 405 if (tracked_scroll_object_) | 397 if (tracked_scroll_object_) |
| 406 tracked_scroll_object_->Release(); | 398 tracked_scroll_object_->Release(); |
| 407 tracked_scroll_object_ = node; | 399 tracked_scroll_object_ = node; |
| 408 tracked_scroll_object_->AddRef(); | 400 tracked_scroll_object_->AddRef(); |
| 409 } | 401 } |
| 410 | 402 |
| 411 BrowserAccessibilityWin* BrowserAccessibilityManagerWin::GetFromUniqueIdWin( | |
| 412 LONG unique_id_win) { | |
| 413 auto iter = g_unique_id_map.Get().find(unique_id_win); | |
| 414 if (iter == g_unique_id_map.Get().end()) | |
| 415 return nullptr; | |
| 416 | |
| 417 return iter->second->ToBrowserAccessibilityWin(); | |
| 418 } | |
| 419 | |
| 420 } // namespace content | 403 } // namespace content |
| OLD | NEW |