| 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 |