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

Side by Side Diff: chrome/browser/accessibility/browser_accessibility_manager.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.h" 5 #include "chrome/browser/accessibility/browser_accessibility_manager.h"
6 6
7 #include "chrome/common/render_messages_params.h" 7 #include "chrome/browser/accessibility/browser_accessibility.h"
8 8
9 using webkit_glue::WebAccessibility; 9 using webkit_glue::WebAccessibility;
10 10
11 // Start child IDs at -1 and decrement each time, because clients use
12 // child IDs of 1, 2, 3, ... to access the children of an object by
13 // index, so we use negative IDs to clearly distinguish between indices
14 // and unique IDs.
15 // static
16 int32 BrowserAccessibilityManager::next_child_id_ = -1;
11 17
12 BrowserAccessibilityManager::BrowserAccessibilityManager( 18 BrowserAccessibilityManager::BrowserAccessibilityManager(
13 gfx::NativeWindow parent_window) 19 gfx::NativeView parent_view,
14 : parent_window_(parent_window) { 20 const WebAccessibility& src,
21 BrowserAccessibilityDelegate* delegate,
22 BrowserAccessibilityFactory* factory)
23 : parent_view_(parent_view),
24 delegate_(delegate),
25 factory_(factory),
26 focus_(NULL) {
27 root_ = CreateAccessibilityTree(NULL, GetNextChildID(), src, 0);
28 if (!focus_)
29 focus_ = root_;
30 }
31
32 // static
33 int32 BrowserAccessibilityManager::GetNextChildID() {
34 // Get the next child ID, and wrap around when we get near the end
35 // of a 32-bit integer range. It's okay to wrap around; we just want
36 // to avoid it as long as possible because clients may cache the ID of
37 // an object for a while to determine if they've seen it before.
38 next_child_id_--;
39 if (next_child_id_ == -2000000000)
40 next_child_id_ = -1;
41
42 return next_child_id_;
15 } 43 }
16 44
17 BrowserAccessibilityManager::~BrowserAccessibilityManager() { 45 BrowserAccessibilityManager::~BrowserAccessibilityManager() {
46 // Clients could still hold references to some nodes of the tree, so
47 // calling Inactivate will make sure that as many nodes as possible are
48 // released now, and remaining nodes are marked as inactive so that
49 // calls to any methods on them will return E_FAIL;
50 root_->ReleaseTree();
51 root_->ReleaseReference();
52 }
53
54 BrowserAccessibility* BrowserAccessibilityManager::GetRoot() {
55 return root_;
56 }
57
58 BrowserAccessibility* BrowserAccessibilityManager::GetFromChildID(
59 int32 child_id) {
60 base::hash_map<int32, BrowserAccessibility*>::iterator iter =
61 child_id_map_.find(child_id);
62 if (iter != child_id_map_.end()) {
63 return iter->second;
64 } else {
65 return NULL;
66 }
67 }
68
69 void BrowserAccessibilityManager::Remove(int32 child_id) {
70 child_id_map_.erase(child_id);
18 } 71 }
19 72
20 void BrowserAccessibilityManager::OnAccessibilityNotifications( 73 void BrowserAccessibilityManager::OnAccessibilityNotifications(
21 const std::vector<ViewHostMsg_AccessibilityNotification_Params>& params) { 74 const std::vector<ViewHostMsg_AccessibilityNotification_Params>& params) {
22 for (uint32 index = 0; index < params.size(); index++) { 75 for (uint32 index = 0; index < params.size(); index++) {
23 const ViewHostMsg_AccessibilityNotification_Params& param = params[index]; 76 const ViewHostMsg_AccessibilityNotification_Params& param = params[index];
24 77
25 switch (param.notification_type) { 78 switch (param.notification_type) {
26 case ViewHostMsg_AccessibilityNotification_Params:: 79 case ViewHostMsg_AccessibilityNotification_Params::
27 NOTIFICATION_TYPE_CHECK_STATE_CHANGED: 80 NOTIFICATION_TYPE_CHECK_STATE_CHANGED:
(...skipping 19 matching lines...) Expand all
47 NOTIFICATION_TYPE_SELECTED_TEXT_CHANGED: 100 NOTIFICATION_TYPE_SELECTED_TEXT_CHANGED:
48 OnAccessibilityObjectTextChange(param.acc_obj); 101 OnAccessibilityObjectTextChange(param.acc_obj);
49 break; 102 break;
50 default: 103 default:
51 DCHECK(0); 104 DCHECK(0);
52 break; 105 break;
53 } 106 }
54 } 107 }
55 } 108 }
56 109
57 gfx::NativeWindow BrowserAccessibilityManager::GetParentWindow() { 110 void BrowserAccessibilityManager::OnAccessibilityObjectStateChange(
58 return parent_window_; 111 const WebAccessibility& acc_obj) {
59 } 112 BrowserAccessibility* new_browser_acc = UpdateTree(acc_obj);
113 if (!new_browser_acc)
114 return;
115
116 NotifyAccessibilityEvent(
117 ViewHostMsg_AccessibilityNotification_Params::
118 NOTIFICATION_TYPE_CHECK_STATE_CHANGED,
119 new_browser_acc);
120 }
121
122 void BrowserAccessibilityManager::OnAccessibilityObjectChildrenChange(
123 const WebAccessibility& acc_obj) {
124 BrowserAccessibility* new_browser_acc = UpdateTree(acc_obj);
125 if (!new_browser_acc)
126 return;
127
128 NotifyAccessibilityEvent(
129 ViewHostMsg_AccessibilityNotification_Params::
130 NOTIFICATION_TYPE_CHILDREN_CHANGED,
131 new_browser_acc);
132 }
133
134 void BrowserAccessibilityManager::OnAccessibilityObjectFocusChange(
135 const WebAccessibility& acc_obj) {
136 BrowserAccessibility* new_browser_acc = UpdateTree(acc_obj);
137 if (!new_browser_acc)
138 return;
139
140 focus_ = new_browser_acc;
141 if (delegate_ && delegate_->HasFocus())
142 GotFocus();
143 }
144
145 void BrowserAccessibilityManager::OnAccessibilityObjectLoadComplete(
146 const WebAccessibility& acc_obj) {
147 root_->ReleaseTree();
148 root_->ReleaseReference();
149 focus_ = NULL;
150
151 root_ = CreateAccessibilityTree(NULL, GetNextChildID(), acc_obj, 0);
152 if (!focus_)
153 focus_ = root_;
154
155 NotifyAccessibilityEvent(
156 ViewHostMsg_AccessibilityNotification_Params::
157 NOTIFICATION_TYPE_LOAD_COMPLETE,
158 root_);
159 if (delegate_ && delegate_->HasFocus())
160 GotFocus();
161 }
162
163 void BrowserAccessibilityManager::OnAccessibilityObjectValueChange(
164 const WebAccessibility& acc_obj) {
165 BrowserAccessibility* new_browser_acc = UpdateTree(acc_obj);
166 if (!new_browser_acc)
167 return;
168
169 NotifyAccessibilityEvent(
170 ViewHostMsg_AccessibilityNotification_Params::
171 NOTIFICATION_TYPE_VALUE_CHANGED,
172 root_);
173 }
174
175 void BrowserAccessibilityManager::OnAccessibilityObjectTextChange(
176 const WebAccessibility& acc_obj) {
177 BrowserAccessibility* new_browser_acc = UpdateTree(acc_obj);
178 if (!new_browser_acc)
179 return;
180
181 NotifyAccessibilityEvent(
182 ViewHostMsg_AccessibilityNotification_Params::
183 NOTIFICATION_TYPE_SELECTED_TEXT_CHANGED,
184 root_);
185 }
186
187 void BrowserAccessibilityManager::GotFocus() {
188 // TODO(ctguil): Remove when tree update logic handles focus changes.
189 if (!focus_)
190 return;
191
192 NotifyAccessibilityEvent(
193 ViewHostMsg_AccessibilityNotification_Params::
194 NOTIFICATION_TYPE_FOCUS_CHANGED,
195 focus_);
196 }
197
198 gfx::NativeView BrowserAccessibilityManager::GetParentView() {
199 return parent_view_;
200 }
201
202 BrowserAccessibility* BrowserAccessibilityManager::GetFocus(
203 BrowserAccessibility* root) {
204 if (focus_ && (!root || focus_->IsDescendantOf(root)))
205 return focus_;
206
207 return NULL;
208 }
209
210 void BrowserAccessibilityManager::SetFocus(
211 const BrowserAccessibility& node) {
212 if (delegate_)
213 delegate_->SetAccessibilityFocus(node.renderer_id());
214 }
215
216 void BrowserAccessibilityManager::DoDefaultAction(
217 const BrowserAccessibility& node) {
218 if (delegate_)
219 delegate_->AccessibilityDoDefaultAction(node.renderer_id());
220 }
221
222 bool BrowserAccessibilityManager::CanModifyTreeInPlace(
223 BrowserAccessibility* current_root,
224 const WebAccessibility& new_root) {
225 if (current_root->renderer_id() != new_root.id)
226 return false;
227 if (current_root->GetChildCount() != new_root.children.size())
228 return false;
229 for (unsigned int i = 0; i < current_root->GetChildCount(); i++) {
230 if (!CanModifyTreeInPlace(current_root->GetChild(i),
231 new_root.children[i])) {
232 return false;
233 }
234 }
235 return true;
236 }
237
238 void BrowserAccessibilityManager::ModifyTreeInPlace(
239 BrowserAccessibility* current_root,
240 const WebAccessibility& new_root) {
241 DCHECK_EQ(current_root->renderer_id(), new_root.id);
242 DCHECK_EQ(current_root->GetChildCount(), new_root.children.size());
243 for (unsigned int i = 0; i < current_root->GetChildCount(); i++)
244 ModifyTreeInPlace(current_root->GetChild(i), new_root.children[i]);
245 current_root->Initialize(
246 this,
247 current_root->GetParent(),
248 current_root->child_id(),
249 current_root->index_in_parent(),
250 new_root);
251 }
252
253
254 BrowserAccessibility* BrowserAccessibilityManager::UpdateTree(
255 const WebAccessibility& acc_obj) {
256 base::hash_map<int, int32>::iterator iter =
257 renderer_id_to_child_id_map_.find(acc_obj.id);
258 if (iter == renderer_id_to_child_id_map_.end())
259 return NULL;
260
261 int32 child_id = iter->second;
262 BrowserAccessibility* old_browser_acc = GetFromChildID(child_id);
263 if (!old_browser_acc)
264 return NULL;
265
266 if (CanModifyTreeInPlace(old_browser_acc, acc_obj)) {
267 ModifyTreeInPlace(old_browser_acc, acc_obj);
268 return old_browser_acc;
269 }
270
271 BrowserAccessibility* new_browser_acc = CreateAccessibilityTree(
272 old_browser_acc->GetParent(),
273 child_id,
274 acc_obj,
275 old_browser_acc->index_in_parent());
276
277 if (old_browser_acc->GetParent()) {
278 old_browser_acc->GetParent()->ReplaceChild(
279 old_browser_acc,
280 new_browser_acc);
281 } else {
282 DCHECK_EQ(old_browser_acc, root_);
283 root_ = new_browser_acc;
284 }
285 old_browser_acc->ReleaseTree();
286 old_browser_acc->ReleaseReference();
287 child_id_map_[child_id] = new_browser_acc;
288
289 return new_browser_acc;
290 }
291
292 BrowserAccessibility* BrowserAccessibilityManager::CreateAccessibilityTree(
293 BrowserAccessibility* parent,
294 int child_id,
295 const WebAccessibility& src,
296 int index_in_parent) {
297 BrowserAccessibility* instance = factory_->Create();
298
299 instance->Initialize(this, parent, child_id, index_in_parent, src);
300 child_id_map_[child_id] = instance;
301 renderer_id_to_child_id_map_[src.id] = child_id;
302 if ((src.state >> WebAccessibility::STATE_FOCUSED) & 1)
303 focus_ = instance;
304 for (int i = 0; i < static_cast<int>(src.children.size()); ++i) {
305 BrowserAccessibility* child = CreateAccessibilityTree(
306 instance, GetNextChildID(), src.children[i], i);
307 instance->AddChild(child);
308 }
309
310 return instance;
311 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698