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

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

Issue 3591003: Make BrowserAccessibilityManager cross platform. Step 1.... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: Some cleanup. 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
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "chrome/browser/browser_accessibility_manager_win.h"
6
7 #include "chrome/browser/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
13 using webkit_glue::WebAccessibility;
14
15 // Factory method to create an instance of BrowserAccessibility
16 BrowserAccessibility* BrowserAccessibilityFactory::Create() {
17 CComObject<BrowserAccessibility>* instance;
18 HRESULT hr = CComObject<BrowserAccessibility>::CreateInstance(&instance);
19 DCHECK(SUCCEEDED(hr));
20 return instance->NewReference();
21 }
22
23 // static
24 // Start child IDs at -1 and decrement each time, because clients use
25 // child IDs of 1, 2, 3, ... to access the children of an object by
26 // index, so we use negative IDs to clearly distinguish between indices
27 // and unique IDs.
28 LONG BrowserAccessibilityManager::next_child_id_ = -1;
29
30 BrowserAccessibilityManager::BrowserAccessibilityManager(
31 HWND parent_hwnd,
32 const webkit_glue::WebAccessibility& src,
33 BrowserAccessibilityDelegate* delegate,
34 BrowserAccessibilityFactory* factory)
35 : parent_hwnd_(parent_hwnd),
36 delegate_(delegate),
37 factory_(factory),
38 focus_(NULL) {
39 HRESULT hr = ::CreateStdAccessibleObject(
40 parent_hwnd_, OBJID_WINDOW, IID_IAccessible,
41 reinterpret_cast<void **>(&window_iaccessible_));
42 DCHECK(SUCCEEDED(hr));
43 root_ = CreateAccessibilityTree(NULL, GetNextChildID(), src, 0);
44 if (!focus_)
45 focus_ = root_;
46 }
47
48 BrowserAccessibilityManager::~BrowserAccessibilityManager() {
49 // Clients could still hold references to some nodes of the tree, so
50 // calling Inactivate will make sure that as many nodes as possible are
51 // released now, and remaining nodes are marked as inactive so that
52 // calls to any methods on them will return E_FAIL;
53 root_->InactivateTree();
54 root_->Release();
55 }
56
57 BrowserAccessibility* BrowserAccessibilityManager::GetRoot() {
58 return root_;
59 }
60
61 void BrowserAccessibilityManager::Remove(LONG child_id) {
62 child_id_map_.erase(child_id);
63 }
64
65 BrowserAccessibility* BrowserAccessibilityManager::GetFromChildID(
66 LONG child_id) {
67 base::hash_map<LONG, BrowserAccessibility*>::iterator iter =
68 child_id_map_.find(child_id);
69 if (iter != child_id_map_.end()) {
70 return iter->second;
71 } else {
72 return NULL;
73 }
74 }
75
76 IAccessible* BrowserAccessibilityManager::GetParentWindowIAccessible() {
77 return window_iaccessible_;
78 }
79
80 HWND BrowserAccessibilityManager::GetParentHWND() {
81 return parent_hwnd_;
82 }
83
84 BrowserAccessibility* BrowserAccessibilityManager::GetFocus(
85 BrowserAccessibility* root) {
86 if (focus_ && (!root || focus_->IsDescendantOf(root)))
87 return focus_;
88
89 return NULL;
90 }
91
92 void BrowserAccessibilityManager::SetFocus(const BrowserAccessibility& node) {
93 if (delegate_)
94 delegate_->SetAccessibilityFocus(node.renderer_id());
95 }
96
97 void BrowserAccessibilityManager::DoDefaultAction(
98 const BrowserAccessibility& node) {
99 if (delegate_)
100 delegate_->AccessibilityDoDefaultAction(node.renderer_id());
101 }
102
103 void BrowserAccessibilityManager::OnAccessibilityNotifications(
104 const std::vector<ViewHostMsg_AccessibilityNotification_Params>& params) {
105 for (uint32 index = 0; index < params.size(); index++) {
106 const ViewHostMsg_AccessibilityNotification_Params& param = params[index];
107
108 switch (param.notification_type) {
109 case ViewHostMsg_AccessibilityNotification_Params::
110 NOTIFICATION_TYPE_CHECK_STATE_CHANGED:
111 OnAccessibilityObjectStateChange(param.acc_obj);
112 break;
113 case ViewHostMsg_AccessibilityNotification_Params::
114 NOTIFICATION_TYPE_CHILDREN_CHANGED:
115 OnAccessibilityObjectChildrenChange(param.acc_obj);
116 break;
117 case ViewHostMsg_AccessibilityNotification_Params::
118 NOTIFICATION_TYPE_FOCUS_CHANGED:
119 OnAccessibilityObjectFocusChange(param.acc_obj);
120 break;
121 case ViewHostMsg_AccessibilityNotification_Params::
122 NOTIFICATION_TYPE_LOAD_COMPLETE:
123 OnAccessibilityObjectLoadComplete(param.acc_obj);
124 break;
125 case ViewHostMsg_AccessibilityNotification_Params::
126 NOTIFICATION_TYPE_VALUE_CHANGED:
127 OnAccessibilityObjectValueChange(param.acc_obj);
128 break;
129 default:
130 DCHECK(0);
131 break;
132 }
133 }
134 }
135
136 BrowserAccessibility* BrowserAccessibilityManager::UpdateTree(
137 const webkit_glue::WebAccessibility& acc_obj) {
138 base::hash_map<int, LONG>::iterator iter =
139 renderer_id_to_child_id_map_.find(acc_obj.id);
140 if (iter == renderer_id_to_child_id_map_.end())
141 return NULL;
142
143 LONG child_id = iter->second;
144 BrowserAccessibility* old_browser_acc = GetFromChildID(child_id);
145 if (!old_browser_acc)
146 return NULL;
147
148 if (old_browser_acc->GetChildCount() == 0 && acc_obj.children.size() == 0) {
149 // Reinitialize the BrowserAccessibility if there are no children to update.
150 old_browser_acc->Initialize(
151 this,
152 old_browser_acc->GetParent(),
153 child_id,
154 old_browser_acc->index_in_parent(),
155 acc_obj);
156
157 return old_browser_acc;
158 } else {
159 BrowserAccessibility* new_browser_acc = CreateAccessibilityTree(
160 old_browser_acc->GetParent(),
161 child_id,
162 acc_obj,
163 old_browser_acc->index_in_parent());
164
165 if (old_browser_acc->GetParent()) {
166 old_browser_acc->GetParent()->ReplaceChild(
167 old_browser_acc,
168 new_browser_acc);
169 } else {
170 DCHECK_EQ(old_browser_acc, root_);
171 root_ = new_browser_acc;
172 }
173 old_browser_acc->InactivateTree();
174 old_browser_acc->Release();
175 child_id_map_[child_id] = new_browser_acc;
176
177 return new_browser_acc;
178 }
179 }
180
181 void BrowserAccessibilityManager::OnAccessibilityObjectStateChange(
182 const webkit_glue::WebAccessibility& acc_obj) {
183 BrowserAccessibility* new_browser_acc = UpdateTree(acc_obj);
184 if (!new_browser_acc)
185 return;
186
187 LONG child_id = new_browser_acc->child_id();
188 NotifyWinEvent(
189 EVENT_OBJECT_STATECHANGE, parent_hwnd_, OBJID_CLIENT, child_id);
190 }
191
192 void BrowserAccessibilityManager::OnAccessibilityObjectChildrenChange(
193 const webkit_glue::WebAccessibility& acc_obj) {
194 BrowserAccessibility* new_browser_acc = UpdateTree(acc_obj);
195 if (!new_browser_acc)
196 return;
197
198 LONG child_id;
199 if (root_ != new_browser_acc) {
200 child_id = new_browser_acc->GetParent()->child_id();
201 } else {
202 child_id = CHILDID_SELF;
203 }
204
205 NotifyWinEvent(EVENT_OBJECT_REORDER, parent_hwnd_, OBJID_CLIENT, child_id);
206 }
207
208 void BrowserAccessibilityManager::OnAccessibilityObjectFocusChange(
209 const webkit_glue::WebAccessibility& acc_obj) {
210 BrowserAccessibility* new_browser_acc = UpdateTree(acc_obj);
211 if (!new_browser_acc)
212 return;
213
214 focus_ = new_browser_acc;
215 LONG child_id = new_browser_acc->child_id();
216 NotifyWinEvent(EVENT_OBJECT_FOCUS, parent_hwnd_, OBJID_CLIENT, child_id);
217 }
218
219 void BrowserAccessibilityManager::OnAccessibilityObjectLoadComplete(
220 const webkit_glue::WebAccessibility& acc_obj) {
221 root_->InactivateTree();
222 root_->Release();
223 focus_ = NULL;
224
225 root_ = CreateAccessibilityTree(NULL, GetNextChildID(), acc_obj, 0);
226 if (!focus_)
227 focus_ = root_;
228
229 LONG root_id = root_->child_id();
230 NotifyWinEvent(EVENT_OBJECT_FOCUS, parent_hwnd_, OBJID_CLIENT, root_id);
231 NotifyWinEvent(
232 IA2_EVENT_DOCUMENT_LOAD_COMPLETE, parent_hwnd_, OBJID_CLIENT, root_id);
233 }
234
235 void BrowserAccessibilityManager::OnAccessibilityObjectValueChange(
236 const webkit_glue::WebAccessibility& acc_obj) {
237 BrowserAccessibility* new_browser_acc = UpdateTree(acc_obj);
238 if (!new_browser_acc)
239 return;
240
241 LONG child_id = new_browser_acc->child_id();
242 NotifyWinEvent(
243 EVENT_OBJECT_VALUECHANGE, parent_hwnd_, OBJID_CLIENT, child_id);
244 }
245
246 LONG BrowserAccessibilityManager::GetNextChildID() {
247 // Get the next child ID, and wrap around when we get near the end
248 // of a 32-bit integer range. It's okay to wrap around; we just want
249 // to avoid it as long as possible because clients may cache the ID of
250 // an object for a while to determine if they've seen it before.
251 next_child_id_--;
252 if (next_child_id_ == -2000000000)
253 next_child_id_ = -1;
254
255 return next_child_id_;
256 }
257
258 BrowserAccessibility* BrowserAccessibilityManager::CreateAccessibilityTree(
259 BrowserAccessibility* parent,
260 int child_id,
261 const webkit_glue::WebAccessibility& src,
262 int index_in_parent) {
263 BrowserAccessibility* instance = factory_->Create();
264
265 instance->Initialize(this, parent, child_id, index_in_parent, src);
266 child_id_map_[child_id] = instance;
267 renderer_id_to_child_id_map_[src.id] = child_id;
268 if ((src.state >> WebAccessibility::STATE_FOCUSED) & 1)
269 focus_ = instance;
270 for (int i = 0; i < static_cast<int>(src.children.size()); ++i) {
271 BrowserAccessibility* child = CreateAccessibilityTree(
272 instance, GetNextChildID(), src.children[i], i);
273 instance->AddChild(child);
274 }
275
276 return instance;
277 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698