OLD | NEW |
1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 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 | 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 "config.h" | 5 #include "config.h" |
| 6 #include "WebViewImpl.h" |
6 | 7 |
| 8 #include "AccessibilityObject.h" |
| 9 #include "AccessibilityObjectWrapper.h" |
7 #include "AXObjectCache.h" | 10 #include "AXObjectCache.h" |
8 #include "Document.h" | 11 #include "Document.h" |
9 #include "Frame.h" | 12 #include "Frame.h" |
10 #include "RefPtr.h" | 13 #include "WebAccessibilityCacheImpl.h" |
11 #undef LOG | 14 #include "WebAccessibilityObject.h" |
| 15 #include "WebFrameImpl.h" |
12 | 16 |
13 #include "webkit/glue/webaccessibilitymanager_impl.h" | 17 #include <wtf/PassRefPtr.h> |
14 | 18 |
15 #include "webkit/api/public/WebAccessibilityObject.h" | 19 using namespace WebCore; |
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 | 20 |
21 using WebKit::WebAccessibilityObject; | 21 namespace WebKit { |
22 using WebKit::WebFrameImpl; | |
23 using WebKit::WebView; | |
24 | 22 |
25 namespace webkit_glue { | 23 const int invalidObjectId = -1; |
| 24 const int firstObjectId = 1000; |
26 | 25 |
27 // struct WebAccessibilityManagerImpl::GlueAccessibilityObjectRoot | 26 static PassRefPtr<AccessibilityObject> toAccessibilityObject(const WebAccessibilityObject& object) |
28 struct WebAccessibilityManagerImpl::GlueAccessibilityObjectRoot { | 27 { |
29 GlueAccessibilityObjectRoot() {} | 28 return object; |
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 } | 29 } |
39 | 30 |
40 // class WebAccessibilityManagerImpl | 31 // WebView ---------------------------------------------------------------- |
41 WebAccessibilityManagerImpl::WebAccessibilityManagerImpl() | 32 |
42 : root_(new GlueAccessibilityObjectRoot), | 33 WebAccessibilityCache* WebAccessibilityCache::create() |
43 acc_obj_id_(1000) { | 34 { |
| 35 return new WebAccessibilityCacheImpl(); |
44 } | 36 } |
45 | 37 |
46 WebAccessibilityManagerImpl::~WebAccessibilityManagerImpl() { | 38 // WeakHandle ------------------------------------------------------------- |
47 int_to_glue_acc_obj_map_.clear(); | 39 |
48 acc_obj_to_int_map_.clear(); | 40 PassRefPtr<WebAccessibilityCacheImpl::WeakHandle> WebAccessibilityCacheImpl::WeakHandle::create(AccessibilityObject* object) |
| 41 { |
| 42 // FIXME: Remove resetting ref-count from AccessibilityObjectWrapper |
| 43 // and convert to use adoptRef. |
| 44 return new WebAccessibilityCacheImpl::WeakHandle(object); |
49 } | 45 } |
50 | 46 |
51 bool WebAccessibilityManagerImpl::GetAccObjInfo(WebView* view, | 47 WebAccessibilityCacheImpl::WeakHandle::WeakHandle(AccessibilityObject* object) |
52 const WebAccessibility::InParams& in_params, | 48 : AccessibilityObjectWrapper(object) |
53 WebAccessibility::OutParams* out_params) { | 49 { |
54 if (!root_->acc_obj_root_ && !InitAccObjRoot(view)) { | 50 m_object->setWrapper(this); |
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 } | 51 } |
201 | 52 |
202 bool WebAccessibilityManagerImpl::InitAccObjRoot(WebView* view) { | 53 // WebAccessibilityCacheImpl ---------------------------------------- |
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 | 54 |
210 WebCore::Document* doc = main_frame_impl->frame()->document(); | 55 void WebAccessibilityCacheImpl::WeakHandle::detach() |
211 | 56 { |
212 if (!doc || !doc->renderer()) | 57 if (m_object) |
213 return false; | 58 m_object = 0; |
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 } | 59 } |
230 | 60 |
231 bool WebAccessibilityManagerImpl::ClearAccObjMap(int acc_obj_id, | 61 WebAccessibilityCacheImpl::WebAccessibilityCacheImpl() |
232 bool clear_all) { | 62 : m_nextNewId(firstObjectId) |
233 if (clear_all) { | 63 , m_initialized(false) |
234 // Clear maps and invalidate root. | 64 { |
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 } | 65 } |
264 | 66 |
265 int WebAccessibilityManagerImpl::FocusAccObj( | 67 WebAccessibilityCacheImpl::~WebAccessibilityCacheImpl() |
266 const WebAccessibilityObject& object) { | 68 { |
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 } | 69 } |
288 | 70 |
289 } // namespace webkit_glue | 71 void WebAccessibilityCacheImpl::initialize(WebView* view) |
| 72 { |
| 73 AXObjectCache::enableAccessibility(); |
| 74 WebAccessibilityObject root = view->accessibilityObject(); |
| 75 if (root.isNull()) |
| 76 return; |
| 77 |
| 78 RefPtr<AccessibilityObject> rootObject = toAccessibilityObject(root); |
| 79 |
| 80 // Insert root in hashmaps. |
| 81 m_objectMap.set(m_nextNewId, WeakHandle::create(rootObject.get())); |
| 82 m_idMap.set(rootObject.get(), m_nextNewId++); |
| 83 |
| 84 m_initialized = true; |
| 85 } |
| 86 |
| 87 WebAccessibilityObject WebAccessibilityCacheImpl::getObjectById(int id) |
| 88 { |
| 89 ObjectMap::iterator it = m_objectMap.find(id); |
| 90 |
| 91 if (it == m_objectMap.end() || !it->second) |
| 92 return WebAccessibilityObject(); |
| 93 |
| 94 return WebAccessibilityObject(it->second->accessibilityObject()); |
| 95 } |
| 96 |
| 97 bool WebAccessibilityCacheImpl::isValidId(int id) const |
| 98 { |
| 99 return id >= firstObjectId; |
| 100 } |
| 101 |
| 102 void WebAccessibilityCacheImpl::remove(int id) |
| 103 { |
| 104 ObjectMap::iterator it = m_objectMap.find(id); |
| 105 |
| 106 if (it == m_objectMap.end()) |
| 107 return; |
| 108 |
| 109 if (it->second) { |
| 110 // Erase element from reverse hashmap. |
| 111 IdMap::iterator it2 = m_idMap.find(it->second->accessibilityObject()); |
| 112 if (it2 != m_idMap.end()) |
| 113 m_idMap.remove(it2); |
| 114 } |
| 115 |
| 116 m_objectMap.remove(it); |
| 117 } |
| 118 |
| 119 void WebAccessibilityCacheImpl::clear() |
| 120 { |
| 121 m_objectMap.clear(); |
| 122 m_idMap.clear(); |
| 123 } |
| 124 |
| 125 int WebAccessibilityCacheImpl::addOrGetId(const WebAccessibilityObject& object) { |
| 126 if (object.isNull()) |
| 127 return invalidObjectId; |
| 128 |
| 129 RefPtr<AccessibilityObject> o = toAccessibilityObject(object); |
| 130 |
| 131 IdMap::iterator it = m_idMap.find(o.get()); |
| 132 |
| 133 if (it != m_idMap.end()) |
| 134 return it->second; |
| 135 |
| 136 // Insert new accessibility object in hashmaps and return its newly |
| 137 // assigned accessibility object id. |
| 138 m_objectMap.set(m_nextNewId, WeakHandle::create(o.get())); |
| 139 m_idMap.set(o.get(), m_nextNewId); |
| 140 |
| 141 return m_nextNewId++; |
| 142 } |
| 143 |
| 144 } |
OLD | NEW |