OLD | NEW |
| (Empty) |
1 // Copyright (c) 2006-2008 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 "config.h" | |
6 | |
7 #include "AXObjectCache.h" | |
8 #include "Document.h" | |
9 #include "Frame.h" | |
10 #include "RefPtr.h" | |
11 #undef LOG | |
12 | |
13 #include "webkit/glue/webaccessibilitymanager_impl.h" | |
14 | |
15 #include "webkit/api/public/WebAccessibilityObject.h" | |
16 #include "webkit/api/src/WebFrameImpl.h" | |
17 #include "webkit/api/src/WebViewImpl.h" | |
18 #include "webkit/glue/glue_accessibility_object.h" | |
19 #include "webkit/glue/glue_util.h" | |
20 | |
21 using WebKit::WebAccessibilityObject; | |
22 using WebKit::WebFrameImpl; | |
23 using WebKit::WebView; | |
24 | |
25 namespace webkit_glue { | |
26 | |
27 // struct WebAccessibilityManagerImpl::GlueAccessibilityObjectRoot | |
28 struct WebAccessibilityManagerImpl::GlueAccessibilityObjectRoot { | |
29 GlueAccessibilityObjectRoot() {} | |
30 | |
31 // Root of the WebKit AccessibilityObject tree. | |
32 RefPtr<GlueAccessibilityObject> acc_obj_root_; | |
33 }; | |
34 | |
35 /*static*/ | |
36 WebAccessibilityManager* WebAccessibilityManager::Create() { | |
37 return new WebAccessibilityManagerImpl(); | |
38 } | |
39 | |
40 // class WebAccessibilityManagerImpl | |
41 WebAccessibilityManagerImpl::WebAccessibilityManagerImpl() | |
42 : root_(new GlueAccessibilityObjectRoot), | |
43 acc_obj_id_(1000) { | |
44 } | |
45 | |
46 WebAccessibilityManagerImpl::~WebAccessibilityManagerImpl() { | |
47 int_to_glue_acc_obj_map_.clear(); | |
48 acc_obj_to_int_map_.clear(); | |
49 } | |
50 | |
51 bool WebAccessibilityManagerImpl::GetAccObjInfo(WebView* view, | |
52 const WebAccessibility::InParams& in_params, | |
53 WebAccessibility::OutParams* out_params) { | |
54 if (!root_->acc_obj_root_ && !InitAccObjRoot(view)) { | |
55 // Failure in retrieving or initializing the root. | |
56 return false; | |
57 } | |
58 | |
59 // Function input parameters. | |
60 int object_id = in_params.object_id; | |
61 int child_id = in_params.child_id; | |
62 | |
63 // Since ids assigned by Chrome starts at 1000, whereas platform-specific ids | |
64 // used to reference a child will be in a wholly different range, we know | |
65 // that any id that high should be treated as a non-direct descendant. | |
66 if (in_params.child_id >= 1000) { | |
67 // Object is not a direct child, re-map the input parameters accordingly. | |
68 // The object to be retrieved is referred to by the |in_params.child_id|, as | |
69 // a result of e.g. a focus event. The local |child_id| is set to 0, to | |
70 // indicate that any function call should refer to the object itself. | |
71 object_id = in_params.child_id; | |
72 child_id = 0; | |
73 } | |
74 | |
75 // Find GlueAccessibilityObject requested by |object_id|. | |
76 IntToGlueAccObjMap::iterator it = | |
77 int_to_glue_acc_obj_map_.find(object_id); | |
78 if (it == int_to_glue_acc_obj_map_.end() || !it->second) { | |
79 // Map did not contain a valid instance of the data requested. | |
80 return false; | |
81 } | |
82 RefPtr<GlueAccessibilityObject> active_acc_obj = it->second; | |
83 | |
84 // Temp paramters for holding output information. | |
85 RefPtr<GlueAccessibilityObject> out_acc_obj = NULL; | |
86 WebCore::String out_string; | |
87 | |
88 switch (in_params.function_id) { | |
89 case WebAccessibility::FUNCTION_DODEFAULTACTION : | |
90 if (!active_acc_obj->DoDefaultAction(child_id)) | |
91 return false; | |
92 break; | |
93 case WebAccessibility::FUNCTION_HITTEST : | |
94 out_acc_obj = active_acc_obj->HitTest(in_params.input_long1, | |
95 in_params.input_long2); | |
96 if (!out_acc_obj.get()) | |
97 return false; | |
98 break; | |
99 case WebAccessibility::FUNCTION_LOCATION : | |
100 if (!active_acc_obj->Location(&out_params->output_long1, | |
101 &out_params->output_long2, | |
102 &out_params->output_long3, | |
103 &out_params->output_long4, | |
104 child_id)) { | |
105 return false; | |
106 } | |
107 break; | |
108 case WebAccessibility::FUNCTION_NAVIGATE : | |
109 out_acc_obj = active_acc_obj->Navigate( | |
110 static_cast<WebAccessibility::Direction>(in_params.input_long1), | |
111 child_id); | |
112 if (!out_acc_obj.get()) | |
113 return false; | |
114 break; | |
115 case WebAccessibility::FUNCTION_GETCHILD : | |
116 if (child_id == 0) { | |
117 // If child requested is self, stay with the same accessibility object. | |
118 out_params->object_id = in_params.object_id; | |
119 out_acc_obj = active_acc_obj.get(); | |
120 } else { | |
121 out_acc_obj = active_acc_obj->GetChild(child_id); | |
122 } | |
123 | |
124 if (!out_acc_obj.get()) | |
125 return false; | |
126 break; | |
127 case WebAccessibility::FUNCTION_CHILDCOUNT : | |
128 if (!active_acc_obj->ChildCount(&out_params->output_long1)) | |
129 return false; | |
130 break; | |
131 case WebAccessibility::FUNCTION_DEFAULTACTION : | |
132 if (!active_acc_obj->DefaultAction(child_id, &out_string)) | |
133 return false; | |
134 break; | |
135 case WebAccessibility::FUNCTION_DESCRIPTION : | |
136 if (!active_acc_obj->Description(child_id, &out_string)) | |
137 return false; | |
138 break; | |
139 case WebAccessibility::FUNCTION_GETFOCUSEDCHILD : | |
140 out_acc_obj = active_acc_obj->GetFocusedChild(); | |
141 if (!out_acc_obj.get()) | |
142 return false; | |
143 break; | |
144 case WebAccessibility::FUNCTION_HELPTEXT : | |
145 if (!active_acc_obj->HelpText(child_id, &out_string)) | |
146 return false; | |
147 break; | |
148 case WebAccessibility::FUNCTION_KEYBOARDSHORTCUT : | |
149 if (!active_acc_obj->KeyboardShortcut(child_id, &out_string)) | |
150 return false; | |
151 break; | |
152 case WebAccessibility::FUNCTION_NAME : | |
153 if (!active_acc_obj->Name(child_id, &out_string)) | |
154 return false; | |
155 break; | |
156 case WebAccessibility::FUNCTION_GETPARENT : | |
157 out_acc_obj = active_acc_obj->GetParent(); | |
158 if (!out_acc_obj.get()) | |
159 return false; | |
160 break; | |
161 case WebAccessibility::FUNCTION_ROLE : | |
162 if (!active_acc_obj->Role(child_id, &out_params->output_long1)) | |
163 return false; | |
164 break; | |
165 case WebAccessibility::FUNCTION_STATE : | |
166 if (!active_acc_obj->State(child_id, &out_params->output_long1)) | |
167 return false; | |
168 break; | |
169 case WebAccessibility::FUNCTION_VALUE : | |
170 if (!active_acc_obj->Value(child_id, &out_string)) | |
171 return false; | |
172 break; | |
173 default: | |
174 // Non-supported function id. | |
175 return false; | |
176 } | |
177 | |
178 // Output and hashmap assignments, as appropriate. | |
179 if (!out_string.isEmpty()) | |
180 out_params->output_string = StringToString16(out_string); | |
181 | |
182 if (out_acc_obj) { | |
183 AccObjToIntMap::iterator it = | |
184 acc_obj_to_int_map_.find(out_acc_obj->accessibilityObject()); | |
185 | |
186 if (it != acc_obj_to_int_map_.end()) { | |
187 // Data already present in map, return previously assigned id. | |
188 out_params->object_id = it->second; | |
189 out_params->output_long1 = -1; | |
190 } else { | |
191 // Insert new GlueAccessibilityObject in hashmaps. | |
192 int_to_glue_acc_obj_map_[acc_obj_id_] = out_acc_obj.get(); | |
193 acc_obj_to_int_map_[out_acc_obj->accessibilityObject()] = acc_obj_id_; | |
194 out_params->object_id = acc_obj_id_++; | |
195 out_params->output_long1 = -1; | |
196 } | |
197 } | |
198 // TODO(klink): Handle simple objects returned. | |
199 return true; | |
200 } | |
201 | |
202 bool WebAccessibilityManagerImpl::InitAccObjRoot(WebView* view) { | |
203 // Enable accessibility and retrieve Document. | |
204 WebCore::AXObjectCache::enableAccessibility(); | |
205 WebFrameImpl* main_frame_impl = | |
206 static_cast<WebFrameImpl*>(view->mainFrame()); | |
207 if (!main_frame_impl || !main_frame_impl->frame()) | |
208 return false; | |
209 | |
210 WebCore::Document* doc = main_frame_impl->frame()->document(); | |
211 | |
212 if (!doc || !doc->renderer()) | |
213 return false; | |
214 | |
215 if (!root_->acc_obj_root_) { | |
216 // Either we've never had a wrapper for this frame's top-level Document, | |
217 // the Document renderer was destroyed and its wrapper was detached, or | |
218 // the previous Document is in the page cache, and the current document | |
219 // needs to be wrapped. | |
220 root_->acc_obj_root_ = GlueAccessibilityObject::CreateInstance(doc-> | |
221 axObjectCache()->getOrCreate(doc->renderer())); | |
222 } | |
223 // Insert root in hashmaps. | |
224 int_to_glue_acc_obj_map_[acc_obj_id_] = root_->acc_obj_root_.get(); | |
225 acc_obj_to_int_map_[root_->acc_obj_root_->accessibilityObject()] = | |
226 acc_obj_id_++; | |
227 | |
228 return true; | |
229 } | |
230 | |
231 bool WebAccessibilityManagerImpl::ClearAccObjMap(int acc_obj_id, | |
232 bool clear_all) { | |
233 if (clear_all) { | |
234 // Clear maps and invalidate root. | |
235 int_to_glue_acc_obj_map_.clear(); | |
236 acc_obj_to_int_map_.clear(); | |
237 root_->acc_obj_root_ = 0; | |
238 return true; | |
239 } | |
240 | |
241 IntToGlueAccObjMap::iterator it = int_to_glue_acc_obj_map_.find(acc_obj_id); | |
242 | |
243 if (it == int_to_glue_acc_obj_map_.end()) { | |
244 // Element not found. | |
245 return false; | |
246 } | |
247 | |
248 if (it->second) { | |
249 // Erase element from reverse hashmap. | |
250 AccObjToIntMap::iterator it2 = | |
251 acc_obj_to_int_map_.find(it->second->accessibilityObject()); | |
252 | |
253 if (it2 != acc_obj_to_int_map_.end()) | |
254 acc_obj_to_int_map_.erase(it2); | |
255 } | |
256 int_to_glue_acc_obj_map_.erase(it); | |
257 | |
258 if (acc_obj_id == 1000) { | |
259 // Invalidate root. | |
260 root_->acc_obj_root_ = 0; | |
261 } | |
262 return true; | |
263 } | |
264 | |
265 int WebAccessibilityManagerImpl::FocusAccObj( | |
266 const WebAccessibilityObject& object) { | |
267 if (object.isNull()) { | |
268 // Return with failure. | |
269 return -1; | |
270 } | |
271 | |
272 RefPtr<WebCore::AccessibilityObject> acc_obj = | |
273 WebAccessibilityObjectToAccessibilityObject(object); | |
274 | |
275 AccObjToIntMap::iterator it = acc_obj_to_int_map_.find(acc_obj.get()); | |
276 | |
277 if (it != acc_obj_to_int_map_.end()) | |
278 return it->second; | |
279 | |
280 // Insert new accessibility object in hashmaps and return its newly | |
281 // assigned accessibility object id. | |
282 int_to_glue_acc_obj_map_[acc_obj_id_] = | |
283 GlueAccessibilityObject::CreateInstance(acc_obj.get()); | |
284 acc_obj_to_int_map_[acc_obj.get()] = acc_obj_id_; | |
285 | |
286 return acc_obj_id_++; | |
287 } | |
288 | |
289 } // namespace webkit_glue | |
OLD | NEW |