Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(283)

Side by Side Diff: content/browser/accessibility/browser_accessibility_manager_win.cc

Issue 1762143002: Use unique IDs for accessibility nodes on Android (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fix null obj deref in DCHECK Created 4 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698