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

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

Issue 3551015: Make BrowserAccessibilityManager cross platform. Step 2. (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: Addressing linux (shlib dbg) and mac (clang) buildbot compile errors. Created 10 years, 2 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 | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2010 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 "chrome/browser/accessibility/browser_accessibility_manager_win.h" 5 #include "chrome/browser/accessibility/browser_accessibility_manager_win.h"
6 6
7 #include "chrome/browser/accessibility/browser_accessibility_win.h" 7 #include "chrome/browser/accessibility/browser_accessibility_win.h"
8 #include "chrome/browser/renderer_host/render_process_host.h"
9 #include "chrome/browser/renderer_host/render_view_host.h"
10 #include "chrome/common/render_messages.h"
11 #include "chrome/common/render_messages_params.h"
12 8
13 using webkit_glue::WebAccessibility; 9 using webkit_glue::WebAccessibility;
14 10
15 // static 11 // static
16 BrowserAccessibilityManager* BrowserAccessibilityManager::Create( 12 BrowserAccessibilityManager* BrowserAccessibilityManager::Create(
17 gfx::NativeWindow parent_window, 13 gfx::NativeView parent_view,
18 const webkit_glue::WebAccessibility& src, 14 const WebAccessibility& src,
19 BrowserAccessibilityDelegate* delegate) { 15 BrowserAccessibilityDelegate* delegate,
16 BrowserAccessibilityFactory* factory) {
20 return new BrowserAccessibilityManagerWin( 17 return new BrowserAccessibilityManagerWin(
21 parent_window, src, delegate, new BrowserAccessibilityWinFactory()); 18 parent_view,
19 src,
20 delegate,
21 factory);
22 } 22 }
23 23
24 // Factory method to create an instance of BrowserAccessibility 24 // Defining this here instead of in the base implementation file to address link
25 BrowserAccessibilityWin* BrowserAccessibilityWinFactory::Create() { 25 // errors on the linux shared library build. (linux shlib)
26 CComObject<BrowserAccessibilityWin>* instance; 26 BrowserAccessibility* BrowserAccessibilityFactory::Create() {
27 HRESULT hr = CComObject<BrowserAccessibilityWin>::CreateInstance(&instance); 27 return BrowserAccessibility::Create();
28 DCHECK(SUCCEEDED(hr));
29 return instance->NewReference();
30 } 28 }
31 29
32 // static 30 BrowserAccessibilityManagerWin*
33 // Start child IDs at -1 and decrement each time, because clients use 31 BrowserAccessibilityManager::toBrowserAccessibilityManagerWin() {
34 // child IDs of 1, 2, 3, ... to access the children of an object by 32 return static_cast<BrowserAccessibilityManagerWin*>(this);
35 // index, so we use negative IDs to clearly distinguish between indices 33 }
36 // and unique IDs.
37 LONG BrowserAccessibilityManagerWin::next_child_id_ = -1;
38 34
39 BrowserAccessibilityManagerWin::BrowserAccessibilityManagerWin( 35 BrowserAccessibilityManagerWin::BrowserAccessibilityManagerWin(
40 HWND parent_window, 36 HWND parent_view,
41 const webkit_glue::WebAccessibility& src, 37 const WebAccessibility& src,
42 BrowserAccessibilityDelegate* delegate, 38 BrowserAccessibilityDelegate* delegate,
43 BrowserAccessibilityWinFactory* factory) 39 BrowserAccessibilityFactory* factory)
44 : BrowserAccessibilityManager(parent_window), 40 : BrowserAccessibilityManager(parent_view, src, delegate, factory) {
45 delegate_(delegate),
46 factory_(factory),
47 focus_(NULL) {
48 HRESULT hr = ::CreateStdAccessibleObject( 41 HRESULT hr = ::CreateStdAccessibleObject(
49 parent_window, OBJID_WINDOW, IID_IAccessible, 42 parent_view, OBJID_WINDOW, IID_IAccessible,
50 reinterpret_cast<void **>(&window_iaccessible_)); 43 reinterpret_cast<void **>(&window_iaccessible_));
51 DCHECK(SUCCEEDED(hr)); 44 DCHECK(SUCCEEDED(hr));
52 root_ = CreateAccessibilityTree(NULL, GetNextChildID(), src, 0);
53 if (!focus_)
54 focus_ = root_;
55 } 45 }
56 46
57 BrowserAccessibilityManagerWin::~BrowserAccessibilityManagerWin() { 47 BrowserAccessibilityManagerWin::~BrowserAccessibilityManagerWin() {
58 // Clients could still hold references to some nodes of the tree, so
59 // calling Inactivate will make sure that as many nodes as possible are
60 // released now, and remaining nodes are marked as inactive so that
61 // calls to any methods on them will return E_FAIL;
62 root_->InactivateTree();
63 root_->Release();
64 }
65
66 BrowserAccessibilityWin* BrowserAccessibilityManagerWin::GetRoot() {
67 return root_;
68 }
69
70 void BrowserAccessibilityManagerWin::Remove(LONG child_id) {
71 child_id_map_.erase(child_id);
72 }
73
74 BrowserAccessibilityWin* BrowserAccessibilityManagerWin::GetFromChildID(
75 LONG child_id) {
76 base::hash_map<LONG, BrowserAccessibilityWin*>::iterator iter =
77 child_id_map_.find(child_id);
78 if (iter != child_id_map_.end()) {
79 return iter->second;
80 } else {
81 return NULL;
82 }
83 } 48 }
84 49
85 IAccessible* BrowserAccessibilityManagerWin::GetParentWindowIAccessible() { 50 IAccessible* BrowserAccessibilityManagerWin::GetParentWindowIAccessible() {
86 return window_iaccessible_; 51 return window_iaccessible_;
87 } 52 }
88 53
89 BrowserAccessibilityWin* BrowserAccessibilityManagerWin::GetFocus( 54 void BrowserAccessibilityManagerWin::NotifyAccessibilityEvent(
90 BrowserAccessibilityWin* root) { 55 ViewHostMsg_AccessibilityNotification_Params::NotificationType n,
91 if (focus_ && (!root || focus_->IsDescendantOf(root))) 56 BrowserAccessibility* node) {
92 return focus_; 57 LONG event_id;
93 58 switch (n) {
94 return NULL; 59 case ViewHostMsg_AccessibilityNotification_Params::
95 } 60 NOTIFICATION_TYPE_CHECK_STATE_CHANGED:
96 61 event_id = EVENT_OBJECT_STATECHANGE;
97 void BrowserAccessibilityManagerWin::SetFocus( 62 break;
98 const BrowserAccessibilityWin& node) { 63 case ViewHostMsg_AccessibilityNotification_Params::
99 if (delegate_) 64 NOTIFICATION_TYPE_CHILDREN_CHANGED:
100 delegate_->SetAccessibilityFocus(node.renderer_id()); 65 event_id = EVENT_OBJECT_REORDER;
101 } 66 break;
102 67 case ViewHostMsg_AccessibilityNotification_Params::
103 void BrowserAccessibilityManagerWin::DoDefaultAction( 68 NOTIFICATION_TYPE_FOCUS_CHANGED:
104 const BrowserAccessibilityWin& node) { 69 event_id = EVENT_OBJECT_FOCUS;
105 if (delegate_) 70 break;
106 delegate_->AccessibilityDoDefaultAction(node.renderer_id()); 71 case ViewHostMsg_AccessibilityNotification_Params::
107 } 72 NOTIFICATION_TYPE_LOAD_COMPLETE:
108 73 event_id = IA2_EVENT_DOCUMENT_LOAD_COMPLETE;
109 bool BrowserAccessibilityManagerWin::CanModifyTreeInPlace( 74 break;
110 BrowserAccessibilityWin* current_root, 75 case ViewHostMsg_AccessibilityNotification_Params::
111 const webkit_glue::WebAccessibility& new_root) { 76 NOTIFICATION_TYPE_VALUE_CHANGED:
112 if (current_root->renderer_id() != new_root.id) 77 event_id = EVENT_OBJECT_VALUECHANGE;
113 return false; 78 break;
114 if (current_root->GetChildCount() != new_root.children.size()) 79 case ViewHostMsg_AccessibilityNotification_Params::
115 return false; 80 NOTIFICATION_TYPE_SELECTED_TEXT_CHANGED:
116 for (unsigned int i = 0; i < current_root->GetChildCount(); i++) { 81 event_id = IA2_EVENT_TEXT_CARET_MOVED;
117 if (!CanModifyTreeInPlace(current_root->GetChild(i),
118 new_root.children[i])) {
119 return false;
120 }
121 }
122 return true;
123 }
124
125 void BrowserAccessibilityManagerWin::ModifyTreeInPlace(
126 BrowserAccessibilityWin* current_root,
127 const webkit_glue::WebAccessibility& new_root) {
128 DCHECK_EQ(current_root->renderer_id(), new_root.id);
129 DCHECK_EQ(current_root->GetChildCount(), new_root.children.size());
130 for (unsigned int i = 0; i < current_root->GetChildCount(); i++)
131 ModifyTreeInPlace(current_root->GetChild(i), new_root.children[i]);
132 current_root->Initialize(
133 this,
134 current_root->GetParent(),
135 current_root->child_id(),
136 current_root->index_in_parent(),
137 new_root);
138 }
139
140
141 BrowserAccessibilityWin* BrowserAccessibilityManagerWin::UpdateTree(
142 const webkit_glue::WebAccessibility& acc_obj) {
143 base::hash_map<int, LONG>::iterator iter =
144 renderer_id_to_child_id_map_.find(acc_obj.id);
145 if (iter == renderer_id_to_child_id_map_.end())
146 return NULL;
147
148 LONG child_id = iter->second;
149 BrowserAccessibilityWin* old_browser_acc = GetFromChildID(child_id);
150 if (!old_browser_acc)
151 return NULL;
152
153 if (CanModifyTreeInPlace(old_browser_acc, acc_obj)) {
154 ModifyTreeInPlace(old_browser_acc, acc_obj);
155 return old_browser_acc;
156 } 82 }
157 83
158 BrowserAccessibilityWin* new_browser_acc = CreateAccessibilityTree( 84 NotifyWinEvent(event_id, GetParentView(), OBJID_CLIENT, node->child_id());
159 old_browser_acc->GetParent(),
160 child_id,
161 acc_obj,
162 old_browser_acc->index_in_parent());
163
164 if (old_browser_acc->GetParent()) {
165 old_browser_acc->GetParent()->ReplaceChild(
166 old_browser_acc,
167 new_browser_acc);
168 } else {
169 DCHECK_EQ(old_browser_acc, root_);
170 root_ = new_browser_acc;
171 }
172 old_browser_acc->InactivateTree();
173 old_browser_acc->Release();
174 child_id_map_[child_id] = new_browser_acc;
175
176 return new_browser_acc;
177 } 85 }
178
179 void BrowserAccessibilityManagerWin::GotFocus() {
180 // TODO(ctguil): Remove when tree update logic handles focus changes.
181 if (!focus_)
182 return;
183
184 NotifyWinEvent(
185 EVENT_OBJECT_FOCUS,
186 GetParentWindow(),
187 OBJID_CLIENT,
188 focus_->child_id());
189 }
190
191 IAccessible* BrowserAccessibilityManagerWin::GetRootAccessible() {
192 return root_;
193 }
194
195 void BrowserAccessibilityManagerWin::OnAccessibilityObjectStateChange(
196 const webkit_glue::WebAccessibility& acc_obj) {
197 BrowserAccessibilityWin* new_browser_acc = UpdateTree(acc_obj);
198 if (!new_browser_acc)
199 return;
200
201 LONG child_id = new_browser_acc->child_id();
202 NotifyWinEvent(
203 EVENT_OBJECT_STATECHANGE, GetParentWindow(), OBJID_CLIENT, child_id);
204 }
205
206 void BrowserAccessibilityManagerWin::OnAccessibilityObjectChildrenChange(
207 const webkit_glue::WebAccessibility& acc_obj) {
208 BrowserAccessibilityWin* new_browser_acc = UpdateTree(acc_obj);
209 if (!new_browser_acc)
210 return;
211
212 LONG child_id;
213 if (root_ != new_browser_acc) {
214 child_id = new_browser_acc->GetParent()->child_id();
215 } else {
216 child_id = CHILDID_SELF;
217 }
218
219 NotifyWinEvent(
220 EVENT_OBJECT_REORDER, GetParentWindow(), OBJID_CLIENT, child_id);
221 }
222
223 void BrowserAccessibilityManagerWin::OnAccessibilityObjectFocusChange(
224 const webkit_glue::WebAccessibility& acc_obj) {
225 BrowserAccessibilityWin* new_browser_acc = UpdateTree(acc_obj);
226 if (!new_browser_acc)
227 return;
228
229 focus_ = new_browser_acc;
230 LONG child_id = new_browser_acc->child_id();
231 if (delegate_ && delegate_->HasFocus())
232 GotFocus();
233 }
234
235 void BrowserAccessibilityManagerWin::OnAccessibilityObjectLoadComplete(
236 const webkit_glue::WebAccessibility& acc_obj) {
237 root_->InactivateTree();
238 root_->Release();
239 focus_ = NULL;
240
241 root_ = CreateAccessibilityTree(NULL, GetNextChildID(), acc_obj, 0);
242 if (!focus_)
243 focus_ = root_;
244
245 NotifyWinEvent(
246 IA2_EVENT_DOCUMENT_LOAD_COMPLETE,
247 GetParentWindow(),
248 OBJID_CLIENT,
249 root_->child_id());
250 if (delegate_ && delegate_->HasFocus())
251 GotFocus();
252 }
253
254 void BrowserAccessibilityManagerWin::OnAccessibilityObjectValueChange(
255 const webkit_glue::WebAccessibility& acc_obj) {
256 BrowserAccessibilityWin* new_browser_acc = UpdateTree(acc_obj);
257 if (!new_browser_acc)
258 return;
259
260 LONG child_id = new_browser_acc->child_id();
261 NotifyWinEvent(
262 EVENT_OBJECT_VALUECHANGE, GetParentWindow(), OBJID_CLIENT, child_id);
263 }
264
265 void BrowserAccessibilityManagerWin::OnAccessibilityObjectTextChange(
266 const webkit_glue::WebAccessibility& acc_obj) {
267 BrowserAccessibilityWin* new_browser_acc = UpdateTree(acc_obj);
268 if (!new_browser_acc)
269 return;
270
271 LONG child_id = new_browser_acc->child_id();
272 NotifyWinEvent(
273 IA2_EVENT_TEXT_CARET_MOVED, GetParentWindow(), OBJID_CLIENT, child_id);
274 }
275
276 LONG BrowserAccessibilityManagerWin::GetNextChildID() {
277 // Get the next child ID, and wrap around when we get near the end
278 // of a 32-bit integer range. It's okay to wrap around; we just want
279 // to avoid it as long as possible because clients may cache the ID of
280 // an object for a while to determine if they've seen it before.
281 next_child_id_--;
282 if (next_child_id_ == -2000000000)
283 next_child_id_ = -1;
284
285 return next_child_id_;
286 }
287
288 BrowserAccessibilityWin*
289 BrowserAccessibilityManagerWin::CreateAccessibilityTree(
290 BrowserAccessibilityWin* parent,
291 int child_id,
292 const webkit_glue::WebAccessibility& src,
293 int index_in_parent) {
294 BrowserAccessibilityWin* instance = factory_->Create();
295
296 instance->Initialize(this, parent, child_id, index_in_parent, src);
297 child_id_map_[child_id] = instance;
298 renderer_id_to_child_id_map_[src.id] = child_id;
299 if ((src.state >> WebAccessibility::STATE_FOCUSED) & 1)
300 focus_ = instance;
301 for (int i = 0; i < static_cast<int>(src.children.size()); ++i) {
302 BrowserAccessibilityWin* child = CreateAccessibilityTree(
303 instance, GetNextChildID(), src.children[i], i);
304 instance->AddChild(child);
305 }
306
307 return instance;
308 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698