OLD | NEW |
1 // Copyright (c) 2010 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 "webkit/glue/webaccessibility.h" | 5 #include "webkit/glue/webaccessibility.h" |
6 | 6 |
7 #include "third_party/WebKit/WebKit/chromium/public/WebAccessibilityCache.h" | 7 #include "third_party/WebKit/WebKit/chromium/public/WebAccessibilityCache.h" |
8 #include "third_party/WebKit/WebKit/chromium/public/WebAccessibilityObject.h" | 8 #include "third_party/WebKit/WebKit/chromium/public/WebAccessibilityObject.h" |
9 #include "third_party/WebKit/WebKit/chromium/public/WebAccessibilityRole.h" | 9 #include "third_party/WebKit/WebKit/chromium/public/WebAccessibilityRole.h" |
| 10 #include "third_party/WebKit/WebKit/chromium/public/WebPoint.h" |
| 11 #include "third_party/WebKit/WebKit/chromium/public/WebRect.h" |
10 #include "third_party/WebKit/WebKit/chromium/public/WebString.h" | 12 #include "third_party/WebKit/WebKit/chromium/public/WebString.h" |
11 | 13 |
12 using WebKit::WebAccessibilityCache; | 14 using WebKit::WebAccessibilityCache; |
13 using WebKit::WebAccessibilityRole; | 15 using WebKit::WebAccessibilityRole; |
14 using WebKit::WebAccessibilityObject; | 16 using WebKit::WebAccessibilityObject; |
| 17 using WebKit::WebPoint; |
| 18 using WebKit::WebRect; |
| 19 using WebKit::WebString; |
15 | 20 |
16 namespace webkit_glue { | 21 namespace webkit_glue { |
17 | 22 |
18 // Provides a conversion between the WebKit::WebAccessibilityRole and a role | 23 // Provides a conversion between the WebKit::WebAccessibilityRole and a role |
19 // supported on the Browser side. Listed alphabetically by the | 24 // supported on the Browser side. Listed alphabetically by the |
20 // WebAccessibilityRole (except for default role). | 25 // WebAccessibilityRole (except for default role). |
21 WebAccessibility::Role ConvertRole(WebKit::WebAccessibilityRole role) { | 26 WebAccessibility::Role ConvertRole(WebKit::WebAccessibilityRole role) { |
22 switch (role) { | 27 switch (role) { |
23 case WebKit::WebAccessibilityRoleLandmarkApplication: | 28 case WebKit::WebAccessibilityRoleLandmarkApplication: |
24 return WebAccessibility::ROLE_APPLICATION; | 29 return WebAccessibility::ROLE_APPLICATION; |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
89 case WebKit::WebAccessibilityRoleUserInterfaceTooltip: | 94 case WebKit::WebAccessibilityRoleUserInterfaceTooltip: |
90 return WebAccessibility::ROLE_TOOLTIP; | 95 return WebAccessibility::ROLE_TOOLTIP; |
91 case WebKit::WebAccessibilityRoleDocument: | 96 case WebKit::WebAccessibilityRoleDocument: |
92 case WebKit::WebAccessibilityRoleUnknown: | 97 case WebKit::WebAccessibilityRoleUnknown: |
93 default: | 98 default: |
94 // This is the default role. | 99 // This is the default role. |
95 return WebAccessibility::ROLE_CLIENT; | 100 return WebAccessibility::ROLE_CLIENT; |
96 } | 101 } |
97 } | 102 } |
98 | 103 |
99 uint32 ConvertState(const WebAccessibilityObject& o) { | 104 long ConvertState(const WebAccessibilityObject& o) { |
100 uint32 state = 0; | 105 long state = 0; |
101 if (o.isChecked()) | 106 if (o.isChecked()) |
102 state |= (1 << WebAccessibility::STATE_CHECKED); | 107 state |= static_cast<long>(1 << WebAccessibility::STATE_CHECKED); |
103 | 108 |
104 if (o.canSetFocusAttribute()) | 109 if (o.canSetFocusAttribute()) |
105 state |= (1 << WebAccessibility::STATE_FOCUSABLE); | 110 state |= static_cast<long>(1 << WebAccessibility::STATE_FOCUSABLE); |
106 | 111 |
107 if (o.isFocused()) | 112 if (o.isFocused()) |
108 state |= (1 << WebAccessibility::STATE_FOCUSED); | 113 state |= static_cast<long>(1 << WebAccessibility::STATE_FOCUSED); |
109 | 114 |
110 if (o.isHovered()) | 115 if (o.isHovered()) |
111 state |= (1 << WebAccessibility::STATE_HOTTRACKED); | 116 state |= static_cast<long>(1 << WebAccessibility::STATE_HOTTRACKED); |
112 | 117 |
113 if (o.isIndeterminate()) | 118 if (o.isIndeterminate()) |
114 state |= (1 << WebAccessibility::STATE_INDETERMINATE); | 119 state |= static_cast<long>(1 << WebAccessibility::STATE_INDETERMINATE); |
115 | 120 |
116 if (o.isAnchor()) | 121 if (o.isAnchor()) |
117 state |= (1 << WebAccessibility::STATE_LINKED); | 122 state |= static_cast<long>(1 << WebAccessibility::STATE_LINKED); |
118 | 123 |
119 if (o.isMultiSelectable()) | 124 if (o.isMultiSelectable()) |
120 state |= (1 << WebAccessibility::STATE_MULTISELECTABLE); | 125 state |= static_cast<long>(1 << WebAccessibility::STATE_MULTISELECTABLE); |
121 | 126 |
122 if (o.isOffScreen()) | 127 if (o.isOffScreen()) |
123 state |= (1 << WebAccessibility::STATE_OFFSCREEN); | 128 state |= static_cast<long>(1 << WebAccessibility::STATE_OFFSCREEN); |
124 | 129 |
125 if (o.isPressed()) | 130 if (o.isPressed()) |
126 state |= (1 << WebAccessibility::STATE_PRESSED); | 131 state |= static_cast<long>(1 << WebAccessibility::STATE_PRESSED); |
127 | 132 |
128 if (o.isPasswordField()) | 133 if (o.isPasswordField()) |
129 state |= (1 << WebAccessibility::STATE_PROTECTED); | 134 state |= static_cast<long>(1 << WebAccessibility::STATE_PROTECTED); |
130 | 135 |
131 if (o.isReadOnly()) | 136 if (o.isReadOnly()) |
132 state |= (1 << WebAccessibility::STATE_READONLY); | 137 state |= static_cast<long>(1 << WebAccessibility::STATE_READONLY); |
133 | 138 |
134 if (o.isVisited()) | 139 if (o.isVisited()) |
135 state |= (1 << WebAccessibility::STATE_TRAVERSED); | 140 state |= static_cast<long>(1 << WebAccessibility::STATE_TRAVERSED); |
136 | 141 |
137 if (!o.isEnabled()) | 142 if (!o.isEnabled()) |
138 state |= (1 << WebAccessibility::STATE_UNAVAILABLE); | 143 state |= static_cast<long>(1 << WebAccessibility::STATE_UNAVAILABLE); |
139 | 144 |
140 return state; | 145 return state; |
141 } | 146 } |
142 | 147 |
143 WebAccessibility::WebAccessibility() | 148 int32 WebAccessibility::GetAccObjInfo(WebAccessibilityCache* cache, |
144 : id(-1), | 149 const WebAccessibility::InParams& in_params, |
145 role(ROLE_NONE), | 150 WebAccessibility::OutParams* out_params) { |
146 state(-1) { | 151 // Find object requested by |object_id|. |
| 152 WebAccessibilityObject active_acc_obj; |
| 153 |
| 154 // Since ids assigned by Chrome starts at 1000, whereas platform-specific ids |
| 155 // used to reference a child will be in a wholly different range, we know |
| 156 // that any id that high should be treated as a non-direct descendant. |
| 157 bool local_child = false; |
| 158 if (cache->isValidId(in_params.child_id)) { |
| 159 // Object is not a direct child, re-map the input parameters accordingly. |
| 160 // The object to be retrieved is referred to by the |in_params.child_id|, as |
| 161 // a result of e.g. a focus event. |
| 162 active_acc_obj = cache->getObjectById(in_params.child_id); |
| 163 } else { |
| 164 local_child = true; |
| 165 |
| 166 active_acc_obj = cache->getObjectById(in_params.object_id); |
| 167 if (active_acc_obj.isNull()) |
| 168 return RETURNCODE_FAIL; |
| 169 |
| 170 // child_id == 0 means self. Otherwise, it's a local child - 1. |
| 171 if (in_params.child_id > 0) { |
| 172 unsigned index = in_params.child_id - 1; |
| 173 if (index >= active_acc_obj.childCount()) |
| 174 return RETURNCODE_FAIL; |
| 175 |
| 176 active_acc_obj = active_acc_obj.childAt(index); |
| 177 } |
| 178 } |
| 179 |
| 180 if (active_acc_obj.isNull()) |
| 181 return RETURNCODE_FAIL; |
| 182 |
| 183 // Temp paramters for holding output information. |
| 184 WebAccessibilityObject out_acc_obj; |
| 185 string16 out_string; |
| 186 |
| 187 switch (in_params.function_id) { |
| 188 case WebAccessibility::FUNCTION_DODEFAULTACTION: { |
| 189 if (!active_acc_obj.performDefaultAction()) |
| 190 return RETURNCODE_FALSE; |
| 191 break; |
| 192 } |
| 193 case WebAccessibility::FUNCTION_HITTEST: { |
| 194 WebPoint point(in_params.input_long1, in_params.input_long2); |
| 195 out_acc_obj = active_acc_obj.hitTest(point); |
| 196 if (out_acc_obj.isNull()) |
| 197 return RETURNCODE_FALSE; |
| 198 break; |
| 199 } |
| 200 case WebAccessibility::FUNCTION_LOCATION: { |
| 201 WebRect rect = active_acc_obj.boundingBoxRect(); |
| 202 out_params->output_long1 = rect.x; |
| 203 out_params->output_long2 = rect.y; |
| 204 out_params->output_long3 = rect.width; |
| 205 out_params->output_long4 = rect.height; |
| 206 break; |
| 207 } |
| 208 case WebAccessibility::FUNCTION_NAVIGATE: { |
| 209 WebAccessibility::Direction dir = |
| 210 static_cast<WebAccessibility::Direction>(in_params.input_long1); |
| 211 switch (dir) { |
| 212 case WebAccessibility::DIRECTION_DOWN: |
| 213 case WebAccessibility::DIRECTION_UP: |
| 214 case WebAccessibility::DIRECTION_LEFT: |
| 215 case WebAccessibility::DIRECTION_RIGHT: |
| 216 // These directions are not implemented, matching Mozilla and IE. |
| 217 return RETURNCODE_FALSE; |
| 218 case WebAccessibility::DIRECTION_LASTCHILD: |
| 219 case WebAccessibility::DIRECTION_FIRSTCHILD: |
| 220 // MSDN states that navigating to first/last child can only be from |
| 221 // self. |
| 222 if (!local_child) |
| 223 return RETURNCODE_FALSE; |
| 224 |
| 225 if (dir == WebAccessibility::DIRECTION_FIRSTCHILD) { |
| 226 out_acc_obj = active_acc_obj.firstChild(); |
| 227 } else { |
| 228 out_acc_obj = active_acc_obj.lastChild(); |
| 229 } |
| 230 break; |
| 231 case WebAccessibility::DIRECTION_NEXT: |
| 232 case WebAccessibility::DIRECTION_PREVIOUS: { |
| 233 if (dir == WebAccessibility::DIRECTION_NEXT) { |
| 234 out_acc_obj = active_acc_obj.nextSibling(); |
| 235 } else { |
| 236 out_acc_obj = active_acc_obj.previousSibling(); |
| 237 } |
| 238 break; |
| 239 } |
| 240 default: |
| 241 return RETURNCODE_FALSE; |
| 242 } |
| 243 |
| 244 if (out_acc_obj.isNull()) |
| 245 return RETURNCODE_FALSE; |
| 246 |
| 247 break; |
| 248 } |
| 249 case WebAccessibility::FUNCTION_GETCHILD: { |
| 250 out_params->object_id = in_params.object_id; |
| 251 out_acc_obj = active_acc_obj; |
| 252 break; |
| 253 } |
| 254 case WebAccessibility::FUNCTION_CHILDCOUNT: { |
| 255 out_params->output_long1 = active_acc_obj.childCount(); |
| 256 break; |
| 257 } |
| 258 case WebAccessibility::FUNCTION_DEFAULTACTION: { |
| 259 out_string = active_acc_obj.actionVerb(); |
| 260 if (out_string.empty()) |
| 261 return RETURNCODE_FALSE; |
| 262 break; |
| 263 } |
| 264 case WebAccessibility::FUNCTION_DESCRIPTION: { |
| 265 out_string = active_acc_obj.accessibilityDescription(); |
| 266 if (out_string.empty()) |
| 267 return RETURNCODE_FALSE; |
| 268 // From the Mozilla MSAA implementation: |
| 269 // "Signal to screen readers that this description is speakable and is not |
| 270 // a formatted positional information description. Don't localize the |
| 271 // 'Description: ' part of this string, it will be parsed out by assistive |
| 272 // technologies." |
| 273 out_string = L"Description: " + out_string; |
| 274 break; |
| 275 } |
| 276 case WebAccessibility::FUNCTION_GETFOCUSEDCHILD: { |
| 277 out_acc_obj = active_acc_obj.focusedChild(); |
| 278 if (out_acc_obj.isNull()) |
| 279 return RETURNCODE_FALSE; |
| 280 break; |
| 281 } |
| 282 case WebAccessibility::FUNCTION_HELPTEXT: { |
| 283 out_string = active_acc_obj.helpText(); |
| 284 if (out_string.empty()) |
| 285 return RETURNCODE_FALSE; |
| 286 break; |
| 287 } |
| 288 case WebAccessibility::FUNCTION_KEYBOARDSHORTCUT: { |
| 289 out_string = active_acc_obj.keyboardShortcut(); |
| 290 if (out_string.empty()) |
| 291 return RETURNCODE_FALSE; |
| 292 break; |
| 293 } |
| 294 case WebAccessibility::FUNCTION_NAME: { |
| 295 out_string = active_acc_obj.title(); |
| 296 if (out_string.empty()) |
| 297 return RETURNCODE_FALSE; |
| 298 break; |
| 299 } |
| 300 case WebAccessibility::FUNCTION_GETPARENT: { |
| 301 out_acc_obj = active_acc_obj.parentObject(); |
| 302 if (out_acc_obj.isNull()) |
| 303 return RETURNCODE_FALSE; |
| 304 break; |
| 305 } |
| 306 case WebAccessibility::FUNCTION_ROLE: { |
| 307 out_params->output_long1 = ConvertRole(active_acc_obj.roleValue()); |
| 308 break; |
| 309 } |
| 310 case WebAccessibility::FUNCTION_STATE: { |
| 311 out_params->output_long1 = ConvertState(active_acc_obj); |
| 312 break; |
| 313 } |
| 314 case WebAccessibility::FUNCTION_VALUE: { |
| 315 out_string = active_acc_obj.stringValue(); |
| 316 if (out_string.empty()) |
| 317 return RETURNCODE_FALSE; |
| 318 break; |
| 319 } |
| 320 default: |
| 321 // Non-supported function id. |
| 322 return RETURNCODE_FAIL; |
| 323 } |
| 324 |
| 325 // Output and hashmap assignments, as appropriate. |
| 326 if (!out_string.empty()) |
| 327 out_params->output_string = out_string; |
| 328 |
| 329 if (out_acc_obj.isNull()) |
| 330 return RETURNCODE_TRUE; |
| 331 |
| 332 int id = cache->addOrGetId(out_acc_obj); |
| 333 out_params->object_id = id; |
| 334 out_params->output_long1 = -1; |
| 335 |
| 336 // TODO(ctguil): Handle simple objects returned. |
| 337 return RETURNCODE_TRUE; |
147 } | 338 } |
148 | 339 |
149 WebAccessibility::WebAccessibility(const WebKit::WebAccessibilityObject& src, | |
150 WebKit::WebAccessibilityCache* cache) { | |
151 Init(src, cache); | |
152 } | |
153 | |
154 void WebAccessibility::Init(const WebKit::WebAccessibilityObject& src, | |
155 WebKit::WebAccessibilityCache* cache) { | |
156 name = src.title(); | |
157 value = src.stringValue(); | |
158 action = src.actionVerb(); | |
159 description = src.accessibilityDescription(); | |
160 help = src.helpText(); | |
161 shortcut = src.keyboardShortcut(); | |
162 role = ConvertRole(src.roleValue()); | |
163 state = ConvertState(src); | |
164 location = src.boundingBoxRect(); | |
165 | |
166 // Add the source object to the cache and store its id. | |
167 id = cache->addOrGetId(src); | |
168 | |
169 // Recursively create children. | |
170 int child_count = src.childCount(); | |
171 children.resize(child_count); | |
172 for (int i = 0; i < child_count; i++) { | |
173 children[i].Init(src.childAt(i), cache); | |
174 } | |
175 } | |
176 | |
177 } // namespace webkit_glue | 340 } // namespace webkit_glue |
OLD | NEW |