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

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

Issue 1925473002: Add verbose logging for native accessibility events. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@load_complete
Patch Set: address all feedback Created 4 years, 7 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_event_win.h"
15 #include "content/browser/accessibility/browser_accessibility_state_impl.h" 16 #include "content/browser/accessibility/browser_accessibility_state_impl.h"
16 #include "content/browser/accessibility/browser_accessibility_win.h" 17 #include "content/browser/accessibility/browser_accessibility_win.h"
17 #include "content/browser/renderer_host/legacy_render_widget_host_win.h" 18 #include "content/browser/renderer_host/legacy_render_widget_host_win.h"
18 #include "content/common/accessibility_messages.h" 19 #include "content/common/accessibility_messages.h"
19 #include "ui/base/win/atl_module.h" 20 #include "ui/base/win/atl_module.h"
20 21
21 namespace content { 22 namespace content {
22 23
23 // static 24 // static
24 BrowserAccessibilityManager* BrowserAccessibilityManager::Create( 25 BrowserAccessibilityManager* BrowserAccessibilityManager::Create(
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
81 return delegate->AccessibilityGetAcceleratedWidget(); 82 return delegate->AccessibilityGetAcceleratedWidget();
82 } 83 }
83 84
84 IAccessible* BrowserAccessibilityManagerWin::GetParentIAccessible() { 85 IAccessible* BrowserAccessibilityManagerWin::GetParentIAccessible() {
85 BrowserAccessibilityDelegate* delegate = GetDelegateFromRootManager(); 86 BrowserAccessibilityDelegate* delegate = GetDelegateFromRootManager();
86 if (!delegate) 87 if (!delegate)
87 return NULL; 88 return NULL;
88 return delegate->AccessibilityGetNativeViewAccessible(); 89 return delegate->AccessibilityGetNativeViewAccessible();
89 } 90 }
90 91
91 void BrowserAccessibilityManagerWin::MaybeCallNotifyWinEvent(
92 DWORD event, BrowserAccessibility* node) {
93 BrowserAccessibilityDelegate* delegate =
94 node->manager()->GetDelegateFromRootManager();
95 if (!delegate) {
96 // This line and other LOG(WARNING) lines are temporary, to debug
97 // flaky failures in DumpAccessibilityEvent* tests.
98 // http://crbug.com/440579
99 DLOG(WARNING) << "Not firing AX event because of no delegate";
100 return;
101 }
102
103 if (!node->IsNative())
104 return;
105
106 HWND hwnd = delegate->AccessibilityGetAcceleratedWidget();
107 if (!hwnd) {
108 DLOG(WARNING) << "Not firing AX event because of no hwnd";
109 return;
110 }
111
112 // Inline text boxes are an internal implementation detail, we don't
113 // expose them to Windows.
114 if (node->GetRole() == ui::AX_ROLE_INLINE_TEXT_BOX)
115 return;
116
117 // It doesn't make sense to fire a REORDER event on a leaf node; that
118 // happens when the node has internal children line inline text boxes.
119 if (event == EVENT_OBJECT_REORDER && node->PlatformChildCount() == 0)
120 return;
121
122 // Pass the negation of this node's unique id in the |child_id|
123 // argument to NotifyWinEvent; the AT client will then call get_accChild
124 // on the HWND's accessibility object and pass it that same id, which
125 // we can use to retrieve the IAccessible for this node.
126 LONG child_id = -node->unique_id();
127 ::NotifyWinEvent(event, hwnd, OBJID_CLIENT, child_id);
128 }
129
130 void BrowserAccessibilityManagerWin::OnIAccessible2Used() { 92 void BrowserAccessibilityManagerWin::OnIAccessible2Used() {
131 BrowserAccessibilityStateImpl::GetInstance()->OnScreenReaderDetected(); 93 BrowserAccessibilityStateImpl::GetInstance()->OnScreenReaderDetected();
132 } 94 }
133 95
134 void BrowserAccessibilityManagerWin::UserIsReloading() { 96 void BrowserAccessibilityManagerWin::UserIsReloading() {
135 if (GetRoot()) 97 if (GetRoot()) {
136 MaybeCallNotifyWinEvent(IA2_EVENT_DOCUMENT_RELOAD, GetRoot()); 98 (new BrowserAccessibilityEventWin(
99 BrowserAccessibilityEvent::FromRenderFrameHost,
100 ui::AX_EVENT_NONE,
101 IA2_EVENT_DOCUMENT_RELOAD,
102 GetRoot()))->Fire();
103 }
137 } 104 }
138 105
139 void BrowserAccessibilityManagerWin::NotifyAccessibilityEvent( 106 void BrowserAccessibilityManagerWin::NotifyAccessibilityEvent(
107 BrowserAccessibilityEvent::Source source,
140 ui::AXEvent event_type, 108 ui::AXEvent event_type,
141 BrowserAccessibility* node) { 109 BrowserAccessibility* node) {
110 if (event_type == ui::AX_EVENT_BLUR) {
111 // Equivalent to focus on the root.
112 event_type = ui::AX_EVENT_FOCUS;
113 node = GetRoot();
114 }
115
116 if (event_type == ui::AX_EVENT_DOCUMENT_SELECTION_CHANGED) {
117 // Fire the event on the object where the focus of the selection is.
118 int32_t focus_id = GetTreeData().sel_focus_object_id;
119 BrowserAccessibility* focus_object = GetFromID(focus_id);
120 if (focus_object) {
121 (new BrowserAccessibilityEventWin(
122 source,
123 ui::AX_EVENT_NONE,
124 IA2_EVENT_TEXT_CARET_MOVED,
125 focus_object))->Fire();
126 return;
127 }
128 }
129
130 BrowserAccessibilityManager::NotifyAccessibilityEvent(
131 source, event_type, node);
132 }
133
134 BrowserAccessibilityEvent::Result
135 BrowserAccessibilityManagerWin::FireWinAccessibilityEvent(
136 BrowserAccessibilityEventWin* event) {
137 const BrowserAccessibility* target = event->target();
138 ui::AXEvent event_type = event->event_type();
139 LONG win_event_type = event->win_event_type();
140
142 BrowserAccessibilityDelegate* root_delegate = GetDelegateFromRootManager(); 141 BrowserAccessibilityDelegate* root_delegate = GetDelegateFromRootManager();
143 if (!root_delegate || !root_delegate->AccessibilityGetAcceleratedWidget()) { 142 if (!root_delegate)
144 DLOG(WARNING) << "Not firing AX event because of no root_delegate or hwnd"; 143 return BrowserAccessibilityEvent::FailedBecauseFrameIsDetached;
145 return; 144
146 } 145 HWND hwnd = root_delegate->AccessibilityGetAcceleratedWidget();
146 if (!hwnd)
147 return BrowserAccessibilityEvent::FailedBecauseNoWindow;
147 148
148 // Don't fire events when this document might be stale as the user has 149 // Don't fire events when this document might be stale as the user has
149 // started navigating to a new document. 150 // started navigating to a new document.
150 if (user_is_navigating_away_) 151 if (user_is_navigating_away_)
151 return; 152 return BrowserAccessibilityEvent::DiscardedBecauseUserNavigatingAway;
152 153
153 // Inline text boxes are an internal implementation detail, we don't 154 // Inline text boxes are an internal implementation detail, we don't
154 // expose them to Windows. 155 // expose them to Windows.
155 if (node->GetRole() == ui::AX_ROLE_INLINE_TEXT_BOX) 156 if (target->GetRole() == ui::AX_ROLE_INLINE_TEXT_BOX)
156 return; 157 return BrowserAccessibilityEvent::NotNeededOnThisPlatform;
157 158
158 LONG event_id = EVENT_MIN; 159 if (event_type == ui::AX_EVENT_LIVE_REGION_CHANGED &&
159 switch (event_type) { 160 target->GetBoolAttribute(ui::AX_ATTR_CONTAINER_LIVE_BUSY))
160 case ui::AX_EVENT_ACTIVEDESCENDANTCHANGED: 161 return BrowserAccessibilityEvent::DiscardedBecauseLiveRegionBusy;
161 event_id = IA2_EVENT_ACTIVE_DESCENDANT_CHANGED; 162
162 break; 163 if (!target)
163 case ui::AX_EVENT_ALERT: 164 return BrowserAccessibilityEvent::FailedBecauseNoFocus;
164 event_id = EVENT_SYSTEM_ALERT; 165
165 break; 166 event->set_target(target);
166 case ui::AX_EVENT_AUTOCORRECTION_OCCURED: 167
167 event_id = IA2_EVENT_OBJECT_ATTRIBUTE_CHANGED; 168 // It doesn't make sense to fire a REORDER event on a leaf node; that
168 break; 169 // happens when the target has internal children inline text boxes.
169 case ui::AX_EVENT_BLUR: 170 if (win_event_type == EVENT_OBJECT_REORDER &&
170 // Equivalent to focus on the root. 171 target->PlatformChildCount() == 0) {
171 event_id = EVENT_OBJECT_FOCUS; 172 return BrowserAccessibilityEvent::NotNeededOnThisPlatform;
172 node = GetRoot();
173 break;
174 case ui::AX_EVENT_CHILDREN_CHANGED:
175 event_id = EVENT_OBJECT_REORDER;
176 break;
177 case ui::AX_EVENT_FOCUS:
178 event_id = EVENT_OBJECT_FOCUS;
179 break;
180 case ui::AX_EVENT_LIVE_REGION_CHANGED:
181 if (node->GetBoolAttribute(ui::AX_ATTR_CONTAINER_LIVE_BUSY))
182 return;
183 event_id = EVENT_OBJECT_LIVEREGIONCHANGED;
184 break;
185 case ui::AX_EVENT_LOAD_COMPLETE:
186 event_id = IA2_EVENT_DOCUMENT_LOAD_COMPLETE;
187 break;
188 case ui::AX_EVENT_SCROLL_POSITION_CHANGED:
189 event_id = EVENT_SYSTEM_SCROLLINGEND;
190 break;
191 case ui::AX_EVENT_SCROLLED_TO_ANCHOR:
192 event_id = EVENT_SYSTEM_SCROLLINGSTART;
193 break;
194 case ui::AX_EVENT_SELECTED_CHILDREN_CHANGED:
195 event_id = EVENT_OBJECT_SELECTIONWITHIN;
196 break;
197 case ui::AX_EVENT_DOCUMENT_SELECTION_CHANGED: {
198 // Fire the event on the object where the focus of the selection is.
199 int32_t focus_id = GetTreeData().sel_focus_object_id;
200 BrowserAccessibility* focus_object = GetFromID(focus_id);
201 if (focus_object)
202 node = focus_object;
203 event_id = IA2_EVENT_TEXT_CARET_MOVED;
204 break;
205 }
206 default:
207 // Not all WebKit accessibility events result in a Windows
208 // accessibility notification.
209 break;
210 } 173 }
211 174
212 if (!node) 175 // Pass the negation of this node's unique id in the |child_id|
213 return; 176 // argument to NotifyWinEvent; the AT client will then call get_accChild
214 177 // on the HWND's accessibility object and pass it that same id, which
215 if (event_id != EVENT_MIN) 178 // we can use to retrieve the IAccessible for this node.
216 MaybeCallNotifyWinEvent(event_id, node); 179 LONG child_id = -target->unique_id();
180 ::NotifyWinEvent(win_event_type, hwnd, OBJID_CLIENT, child_id);
217 181
218 // If this is a layout complete notification (sent when a container scrolls) 182 // If this is a layout complete notification (sent when a container scrolls)
219 // and there is a descendant tracked object, send a notification on it. 183 // and there is a descendant tracked object, send a notification on it.
220 // TODO(dmazzoni): remove once http://crbug.com/113483 is fixed. 184 // TODO(dmazzoni): remove once http://crbug.com/113483 is fixed.
221 if (event_type == ui::AX_EVENT_LAYOUT_COMPLETE && 185 if (event_type == ui::AX_EVENT_LAYOUT_COMPLETE &&
222 tracked_scroll_object_ && 186 tracked_scroll_object_ &&
223 tracked_scroll_object_->IsDescendantOf(node)) { 187 tracked_scroll_object_->IsDescendantOf(target)) {
224 MaybeCallNotifyWinEvent( 188 (new BrowserAccessibilityEventWin(
225 IA2_EVENT_VISIBLE_DATA_CHANGED, tracked_scroll_object_); 189 BrowserAccessibilityEvent::FromScroll,
190 ui::AX_EVENT_NONE,
191 IA2_EVENT_VISIBLE_DATA_CHANGED,
192 tracked_scroll_object_))->Fire();
226 tracked_scroll_object_->Release(); 193 tracked_scroll_object_->Release();
227 tracked_scroll_object_ = NULL; 194 tracked_scroll_object_ = NULL;
228 } 195 }
196
197 return BrowserAccessibilityEvent::Sent;
229 } 198 }
230 199
231 bool BrowserAccessibilityManagerWin::CanFireEvents() { 200 bool BrowserAccessibilityManagerWin::CanFireEvents() {
232 BrowserAccessibilityDelegate* root_delegate = GetDelegateFromRootManager(); 201 BrowserAccessibilityDelegate* root_delegate = GetDelegateFromRootManager();
233 if (!root_delegate) 202 if (!root_delegate)
234 return false; 203 return false;
235 HWND hwnd = root_delegate->AccessibilityGetAcceleratedWidget(); 204 HWND hwnd = root_delegate->AccessibilityGetAcceleratedWidget();
236 return hwnd != nullptr; 205 return hwnd != nullptr;
237 } 206 }
238 207
239 void BrowserAccessibilityManagerWin::FireFocusEvent( 208 void BrowserAccessibilityManagerWin::FireFocusEvent(
209 BrowserAccessibilityEvent::Source source,
240 BrowserAccessibility* node) { 210 BrowserAccessibility* node) {
241 // On Windows, we always fire a FOCUS event on the root of a frame before 211 // On Windows, we always fire a FOCUS event on the root of a frame before
242 // firing a focus event within that frame. 212 // firing a focus event within that frame.
243 if (node->manager() != last_focused_manager_ && 213 if (node->manager() != last_focused_manager_ &&
244 node != node->manager()->GetRoot()) { 214 node != node->manager()->GetRoot()) {
245 NotifyAccessibilityEvent(ui::AX_EVENT_FOCUS, node->manager()->GetRoot()); 215 BrowserAccessibilityEvent::Create(source,
216 ui::AX_EVENT_FOCUS,
217 node->manager()->GetRoot())->Fire();
246 } 218 }
247 219
248 BrowserAccessibilityManager::FireFocusEvent(node); 220 BrowserAccessibilityManager::FireFocusEvent(source, node);
249 } 221 }
250 222
251 void BrowserAccessibilityManagerWin::OnNodeCreated(ui::AXTree* tree, 223 void BrowserAccessibilityManagerWin::OnNodeCreated(ui::AXTree* tree,
252 ui::AXNode* node) { 224 ui::AXNode* node) {
253 DCHECK(node); 225 DCHECK(node);
254 BrowserAccessibilityManager::OnNodeCreated(tree, node); 226 BrowserAccessibilityManager::OnNodeCreated(tree, node);
255 BrowserAccessibility* obj = GetFromAXNode(node); 227 BrowserAccessibility* obj = GetFromAXNode(node);
256 if (!obj) 228 if (!obj)
257 return; 229 return;
258 if (!obj->IsNative()) 230 if (!obj->IsNative())
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
326 298
327 void BrowserAccessibilityManagerWin::TrackScrollingObject( 299 void BrowserAccessibilityManagerWin::TrackScrollingObject(
328 BrowserAccessibilityWin* node) { 300 BrowserAccessibilityWin* node) {
329 if (tracked_scroll_object_) 301 if (tracked_scroll_object_)
330 tracked_scroll_object_->Release(); 302 tracked_scroll_object_->Release();
331 tracked_scroll_object_ = node; 303 tracked_scroll_object_ = node;
332 tracked_scroll_object_->AddRef(); 304 tracked_scroll_object_->AddRef();
333 } 305 }
334 306
335 } // namespace content 307 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698