OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 "content/renderer/accessibility/accessibility_node_serializer.h" | 5 #include "content/renderer/accessibility/accessibility_node_serializer.h" |
6 | 6 |
7 #include <set> | 7 #include <set> |
8 | 8 |
9 #include "base/strings/string_number_conversions.h" | 9 #include "base/strings/string_number_conversions.h" |
10 #include "base/strings/string_util.h" | 10 #include "base/strings/string_util.h" |
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
126 | 126 |
127 } // Anonymous namespace | 127 } // Anonymous namespace |
128 | 128 |
129 void SerializeAccessibilityNode( | 129 void SerializeAccessibilityNode( |
130 const WebAXObject& src, | 130 const WebAXObject& src, |
131 AccessibilityNodeData* dst) { | 131 AccessibilityNodeData* dst) { |
132 dst->role = src.role(); | 132 dst->role = src.role(); |
133 dst->state = ConvertState(src); | 133 dst->state = ConvertState(src); |
134 dst->location = src.boundingBoxRect(); | 134 dst->location = src.boundingBoxRect(); |
135 dst->id = src.axID(); | 135 dst->id = src.axID(); |
136 std::string name = UTF16ToUTF8(src.title()); | 136 std::string name = base::UTF16ToUTF8(src.title()); |
137 | 137 |
138 std::string value; | 138 std::string value; |
139 if (src.valueDescription().length()) { | 139 if (src.valueDescription().length()) { |
140 dst->AddStringAttribute(dst->ATTR_VALUE, | 140 dst->AddStringAttribute(dst->ATTR_VALUE, |
141 UTF16ToUTF8(src.valueDescription())); | 141 base::UTF16ToUTF8(src.valueDescription())); |
142 } else { | 142 } else { |
143 dst->AddStringAttribute(dst->ATTR_VALUE, UTF16ToUTF8(src.stringValue())); | 143 dst->AddStringAttribute(dst->ATTR_VALUE, |
| 144 base::UTF16ToUTF8(src.stringValue())); |
144 } | 145 } |
145 | 146 |
146 if (dst->role == blink::WebAXRoleColorWell) { | 147 if (dst->role == blink::WebAXRoleColorWell) { |
147 int r, g, b; | 148 int r, g, b; |
148 src.colorValue(r, g, b); | 149 src.colorValue(r, g, b); |
149 dst->AddIntAttribute(dst->ATTR_COLOR_VALUE_RED, r); | 150 dst->AddIntAttribute(dst->ATTR_COLOR_VALUE_RED, r); |
150 dst->AddIntAttribute(dst->ATTR_COLOR_VALUE_GREEN, g); | 151 dst->AddIntAttribute(dst->ATTR_COLOR_VALUE_GREEN, g); |
151 dst->AddIntAttribute(dst->ATTR_COLOR_VALUE_BLUE, b); | 152 dst->AddIntAttribute(dst->ATTR_COLOR_VALUE_BLUE, b); |
152 } | 153 } |
153 | 154 |
(...skipping 16 matching lines...) Expand all Loading... |
170 word_starts.reserve(src_word_starts.size()); | 171 word_starts.reserve(src_word_starts.size()); |
171 word_ends.reserve(src_word_starts.size()); | 172 word_ends.reserve(src_word_starts.size()); |
172 for (size_t i = 0; i < src_word_starts.size(); ++i) { | 173 for (size_t i = 0; i < src_word_starts.size(); ++i) { |
173 word_starts.push_back(src_word_starts[i]); | 174 word_starts.push_back(src_word_starts[i]); |
174 word_ends.push_back(src_word_ends[i]); | 175 word_ends.push_back(src_word_ends[i]); |
175 } | 176 } |
176 dst->AddIntListAttribute(dst->ATTR_WORD_STARTS, word_starts); | 177 dst->AddIntListAttribute(dst->ATTR_WORD_STARTS, word_starts); |
177 dst->AddIntListAttribute(dst->ATTR_WORD_ENDS, word_ends); | 178 dst->AddIntListAttribute(dst->ATTR_WORD_ENDS, word_ends); |
178 } | 179 } |
179 | 180 |
180 if (src.accessKey().length()) | 181 if (src.accessKey().length()) { |
181 dst->AddStringAttribute(dst->ATTR_ACCESS_KEY, UTF16ToUTF8(src.accessKey())); | 182 dst->AddStringAttribute(dst->ATTR_ACCESS_KEY, |
182 if (src.actionVerb().length()) | 183 base::UTF16ToUTF8(src.accessKey())); |
183 dst->AddStringAttribute(dst->ATTR_ACTION, UTF16ToUTF8(src.actionVerb())); | 184 } |
| 185 if (src.actionVerb().length()) { |
| 186 dst->AddStringAttribute(dst->ATTR_ACTION, |
| 187 base::UTF16ToUTF8(src.actionVerb())); |
| 188 } |
184 if (src.isAriaReadOnly()) | 189 if (src.isAriaReadOnly()) |
185 dst->AddBoolAttribute(dst->ATTR_ARIA_READONLY, true); | 190 dst->AddBoolAttribute(dst->ATTR_ARIA_READONLY, true); |
186 if (src.isButtonStateMixed()) | 191 if (src.isButtonStateMixed()) |
187 dst->AddBoolAttribute(dst->ATTR_BUTTON_MIXED, true); | 192 dst->AddBoolAttribute(dst->ATTR_BUTTON_MIXED, true); |
188 if (src.canSetValueAttribute()) | 193 if (src.canSetValueAttribute()) |
189 dst->AddBoolAttribute(dst->ATTR_CAN_SET_VALUE, true); | 194 dst->AddBoolAttribute(dst->ATTR_CAN_SET_VALUE, true); |
190 if (src.accessibilityDescription().length()) { | 195 if (src.accessibilityDescription().length()) { |
191 dst->AddStringAttribute(dst->ATTR_DESCRIPTION, | 196 dst->AddStringAttribute(dst->ATTR_DESCRIPTION, |
192 UTF16ToUTF8(src.accessibilityDescription())); | 197 base::UTF16ToUTF8(src.accessibilityDescription())); |
193 } | 198 } |
194 if (src.hasComputedStyle()) { | 199 if (src.hasComputedStyle()) { |
195 dst->AddStringAttribute(dst->ATTR_DISPLAY, | 200 dst->AddStringAttribute(dst->ATTR_DISPLAY, |
196 UTF16ToUTF8(src.computedStyleDisplay())); | 201 base::UTF16ToUTF8(src.computedStyleDisplay())); |
197 } | 202 } |
198 if (src.helpText().length()) | 203 if (src.helpText().length()) |
199 dst->AddStringAttribute(dst->ATTR_HELP, UTF16ToUTF8(src.helpText())); | 204 dst->AddStringAttribute(dst->ATTR_HELP, base::UTF16ToUTF8(src.helpText())); |
200 if (src.keyboardShortcut().length()) { | 205 if (src.keyboardShortcut().length()) { |
201 dst->AddStringAttribute(dst->ATTR_SHORTCUT, | 206 dst->AddStringAttribute(dst->ATTR_SHORTCUT, |
202 UTF16ToUTF8(src.keyboardShortcut())); | 207 base::UTF16ToUTF8(src.keyboardShortcut())); |
203 } | 208 } |
204 if (!src.titleUIElement().isDetached()) { | 209 if (!src.titleUIElement().isDetached()) { |
205 dst->AddIntAttribute(dst->ATTR_TITLE_UI_ELEMENT, | 210 dst->AddIntAttribute(dst->ATTR_TITLE_UI_ELEMENT, |
206 src.titleUIElement().axID()); | 211 src.titleUIElement().axID()); |
207 } | 212 } |
208 if (!src.url().isEmpty()) | 213 if (!src.url().isEmpty()) |
209 dst->AddStringAttribute(dst->ATTR_URL, src.url().spec()); | 214 dst->AddStringAttribute(dst->ATTR_URL, src.url().spec()); |
210 | 215 |
211 if (dst->role == blink::WebAXRoleHeading) | 216 if (dst->role == blink::WebAXRoleHeading) |
212 dst->AddIntAttribute(dst->ATTR_HIERARCHICAL_LEVEL, src.headingLevel()); | 217 dst->AddIntAttribute(dst->ATTR_HIERARCHICAL_LEVEL, src.headingLevel()); |
(...skipping 14 matching lines...) Expand all Loading... |
227 | 232 |
228 WebNode node = src.node(); | 233 WebNode node = src.node(); |
229 bool is_iframe = false; | 234 bool is_iframe = false; |
230 std::string live_atomic; | 235 std::string live_atomic; |
231 std::string live_busy; | 236 std::string live_busy; |
232 std::string live_status; | 237 std::string live_status; |
233 std::string live_relevant; | 238 std::string live_relevant; |
234 | 239 |
235 if (!node.isNull() && node.isElementNode()) { | 240 if (!node.isNull() && node.isElementNode()) { |
236 WebElement element = node.to<WebElement>(); | 241 WebElement element = node.to<WebElement>(); |
237 is_iframe = (element.tagName() == ASCIIToUTF16("IFRAME")); | 242 is_iframe = (element.tagName() == base::ASCIIToUTF16("IFRAME")); |
238 | 243 |
239 if (LowerCaseEqualsASCII(element.getAttribute("aria-expanded"), "true")) | 244 if (LowerCaseEqualsASCII(element.getAttribute("aria-expanded"), "true")) |
240 dst->state |= (1 << blink::WebAXStateExpanded); | 245 dst->state |= (1 << blink::WebAXStateExpanded); |
241 | 246 |
242 // TODO(ctguil): The tagName in WebKit is lower cased but | 247 // TODO(ctguil): The tagName in WebKit is lower cased but |
243 // HTMLElement::nodeName calls localNameUpper. Consider adding | 248 // HTMLElement::nodeName calls localNameUpper. Consider adding |
244 // a WebElement method that returns the original lower cased tagName. | 249 // a WebElement method that returns the original lower cased tagName. |
245 dst->AddStringAttribute( | 250 dst->AddStringAttribute( |
246 dst->ATTR_HTML_TAG, | 251 dst->ATTR_HTML_TAG, |
247 StringToLowerASCII(UTF16ToUTF8(element.tagName()))); | 252 StringToLowerASCII(base::UTF16ToUTF8(element.tagName()))); |
248 for (unsigned i = 0; i < element.attributeCount(); ++i) { | 253 for (unsigned i = 0; i < element.attributeCount(); ++i) { |
249 std::string name = StringToLowerASCII(UTF16ToUTF8( | 254 std::string name = StringToLowerASCII(base::UTF16ToUTF8( |
250 element.attributeLocalName(i))); | 255 element.attributeLocalName(i))); |
251 std::string value = UTF16ToUTF8(element.attributeValue(i)); | 256 std::string value = base::UTF16ToUTF8(element.attributeValue(i)); |
252 dst->html_attributes.push_back(std::make_pair(name, value)); | 257 dst->html_attributes.push_back(std::make_pair(name, value)); |
253 } | 258 } |
254 | 259 |
255 if (dst->role == blink::WebAXRoleEditableText || | 260 if (dst->role == blink::WebAXRoleEditableText || |
256 dst->role == blink::WebAXRoleTextArea || | 261 dst->role == blink::WebAXRoleTextArea || |
257 dst->role == blink::WebAXRoleTextField) { | 262 dst->role == blink::WebAXRoleTextField) { |
258 dst->AddIntAttribute(dst->ATTR_TEXT_SEL_START, src.selectionStart()); | 263 dst->AddIntAttribute(dst->ATTR_TEXT_SEL_START, src.selectionStart()); |
259 dst->AddIntAttribute(dst->ATTR_TEXT_SEL_END, src.selectionEnd()); | 264 dst->AddIntAttribute(dst->ATTR_TEXT_SEL_END, src.selectionEnd()); |
260 | 265 |
261 WebVector<int> src_line_breaks; | 266 WebVector<int> src_line_breaks; |
262 src.lineBreaks(src_line_breaks); | 267 src.lineBreaks(src_line_breaks); |
263 if (src_line_breaks.size() > 0) { | 268 if (src_line_breaks.size() > 0) { |
264 std::vector<int32> line_breaks; | 269 std::vector<int32> line_breaks; |
265 line_breaks.reserve(src_line_breaks.size()); | 270 line_breaks.reserve(src_line_breaks.size()); |
266 for (size_t i = 0; i < src_line_breaks.size(); ++i) | 271 for (size_t i = 0; i < src_line_breaks.size(); ++i) |
267 line_breaks.push_back(src_line_breaks[i]); | 272 line_breaks.push_back(src_line_breaks[i]); |
268 dst->AddIntListAttribute(dst->ATTR_LINE_BREAKS, line_breaks); | 273 dst->AddIntListAttribute(dst->ATTR_LINE_BREAKS, line_breaks); |
269 } | 274 } |
270 } | 275 } |
271 | 276 |
272 // ARIA role. | 277 // ARIA role. |
273 if (element.hasAttribute("role")) { | 278 if (element.hasAttribute("role")) { |
274 dst->AddStringAttribute(dst->ATTR_ROLE, | 279 dst->AddStringAttribute(dst->ATTR_ROLE, |
275 UTF16ToUTF8(element.getAttribute("role"))); | 280 base::UTF16ToUTF8(element.getAttribute("role"))); |
276 } | 281 } |
277 | 282 |
278 // Live region attributes | 283 // Live region attributes |
279 live_atomic = UTF16ToUTF8(element.getAttribute("aria-atomic")); | 284 live_atomic = base::UTF16ToUTF8(element.getAttribute("aria-atomic")); |
280 live_busy = UTF16ToUTF8(element.getAttribute("aria-busy")); | 285 live_busy = base::UTF16ToUTF8(element.getAttribute("aria-busy")); |
281 live_status = UTF16ToUTF8(element.getAttribute("aria-live")); | 286 live_status = base::UTF16ToUTF8(element.getAttribute("aria-live")); |
282 live_relevant = UTF16ToUTF8(element.getAttribute("aria-relevant")); | 287 live_relevant = base::UTF16ToUTF8(element.getAttribute("aria-relevant")); |
283 } | 288 } |
284 | 289 |
285 // Walk up the parent chain to set live region attributes of containers | 290 // Walk up the parent chain to set live region attributes of containers |
286 std::string container_live_atomic; | 291 std::string container_live_atomic; |
287 std::string container_live_busy; | 292 std::string container_live_busy; |
288 std::string container_live_status; | 293 std::string container_live_status; |
289 std::string container_live_relevant; | 294 std::string container_live_relevant; |
290 WebAXObject container_accessible = src; | 295 WebAXObject container_accessible = src; |
291 while (!container_accessible.isDetached()) { | 296 while (!container_accessible.isDetached()) { |
292 WebNode container_node = container_accessible.node(); | 297 WebNode container_node = container_accessible.node(); |
293 if (!container_node.isNull() && container_node.isElementNode()) { | 298 if (!container_node.isNull() && container_node.isElementNode()) { |
294 WebElement container_elem = container_node.to<WebElement>(); | 299 WebElement container_elem = container_node.to<WebElement>(); |
295 if (container_elem.hasAttribute("aria-atomic") && | 300 if (container_elem.hasAttribute("aria-atomic") && |
296 container_live_atomic.empty()) { | 301 container_live_atomic.empty()) { |
297 container_live_atomic = | 302 container_live_atomic = |
298 UTF16ToUTF8(container_elem.getAttribute("aria-atomic")); | 303 base::UTF16ToUTF8(container_elem.getAttribute("aria-atomic")); |
299 } | 304 } |
300 if (container_elem.hasAttribute("aria-busy") && | 305 if (container_elem.hasAttribute("aria-busy") && |
301 container_live_busy.empty()) { | 306 container_live_busy.empty()) { |
302 container_live_busy = | 307 container_live_busy = |
303 UTF16ToUTF8(container_elem.getAttribute("aria-busy")); | 308 base::UTF16ToUTF8(container_elem.getAttribute("aria-busy")); |
304 } | 309 } |
305 if (container_elem.hasAttribute("aria-live") && | 310 if (container_elem.hasAttribute("aria-live") && |
306 container_live_status.empty()) { | 311 container_live_status.empty()) { |
307 container_live_status = | 312 container_live_status = |
308 UTF16ToUTF8(container_elem.getAttribute("aria-live")); | 313 base::UTF16ToUTF8(container_elem.getAttribute("aria-live")); |
309 } | 314 } |
310 if (container_elem.hasAttribute("aria-relevant") && | 315 if (container_elem.hasAttribute("aria-relevant") && |
311 container_live_relevant.empty()) { | 316 container_live_relevant.empty()) { |
312 container_live_relevant = | 317 container_live_relevant = |
313 UTF16ToUTF8(container_elem.getAttribute("aria-relevant")); | 318 base::UTF16ToUTF8(container_elem.getAttribute("aria-relevant")); |
314 } | 319 } |
315 } | 320 } |
316 container_accessible = container_accessible.parentObject(); | 321 container_accessible = container_accessible.parentObject(); |
317 } | 322 } |
318 | 323 |
319 if (!live_atomic.empty()) | 324 if (!live_atomic.empty()) |
320 dst->AddBoolAttribute(dst->ATTR_LIVE_ATOMIC, IsTrue(live_atomic)); | 325 dst->AddBoolAttribute(dst->ATTR_LIVE_ATOMIC, IsTrue(live_atomic)); |
321 if (!live_busy.empty()) | 326 if (!live_busy.empty()) |
322 dst->AddBoolAttribute(dst->ATTR_LIVE_BUSY, IsTrue(live_busy)); | 327 dst->AddBoolAttribute(dst->ATTR_LIVE_BUSY, IsTrue(live_busy)); |
323 if (!live_status.empty()) | 328 if (!live_status.empty()) |
(...skipping 27 matching lines...) Expand all Loading... |
351 src.maxValueForRange()); | 356 src.maxValueForRange()); |
352 dst->AddFloatAttribute(dst->ATTR_MIN_VALUE_FOR_RANGE, | 357 dst->AddFloatAttribute(dst->ATTR_MIN_VALUE_FOR_RANGE, |
353 src.minValueForRange()); | 358 src.minValueForRange()); |
354 } | 359 } |
355 | 360 |
356 if (dst->role == blink::WebAXRoleDocument || | 361 if (dst->role == blink::WebAXRoleDocument || |
357 dst->role == blink::WebAXRoleWebArea) { | 362 dst->role == blink::WebAXRoleWebArea) { |
358 dst->AddStringAttribute(dst->ATTR_HTML_TAG, "#document"); | 363 dst->AddStringAttribute(dst->ATTR_HTML_TAG, "#document"); |
359 const WebDocument& document = src.document(); | 364 const WebDocument& document = src.document(); |
360 if (name.empty()) | 365 if (name.empty()) |
361 name = UTF16ToUTF8(document.title()); | 366 name = base::UTF16ToUTF8(document.title()); |
362 dst->AddStringAttribute(dst->ATTR_DOC_TITLE, UTF16ToUTF8(document.title())); | 367 dst->AddStringAttribute(dst->ATTR_DOC_TITLE, |
| 368 base::UTF16ToUTF8(document.title())); |
363 dst->AddStringAttribute(dst->ATTR_DOC_URL, document.url().spec()); | 369 dst->AddStringAttribute(dst->ATTR_DOC_URL, document.url().spec()); |
364 dst->AddStringAttribute( | 370 dst->AddStringAttribute( |
365 dst->ATTR_DOC_MIMETYPE, | 371 dst->ATTR_DOC_MIMETYPE, |
366 document.isXHTMLDocument() ? "text/xhtml" : "text/html"); | 372 document.isXHTMLDocument() ? "text/xhtml" : "text/html"); |
367 dst->AddBoolAttribute(dst->ATTR_DOC_LOADED, src.isLoaded()); | 373 dst->AddBoolAttribute(dst->ATTR_DOC_LOADED, src.isLoaded()); |
368 dst->AddFloatAttribute(dst->ATTR_DOC_LOADING_PROGRESS, | 374 dst->AddFloatAttribute(dst->ATTR_DOC_LOADING_PROGRESS, |
369 src.estimatedLoadingProgress()); | 375 src.estimatedLoadingProgress()); |
370 | 376 |
371 const WebDocumentType& doctype = document.doctype(); | 377 const WebDocumentType& doctype = document.doctype(); |
372 if (!doctype.isNull()) { | 378 if (!doctype.isNull()) { |
373 dst->AddStringAttribute(dst->ATTR_DOC_DOCTYPE, | 379 dst->AddStringAttribute(dst->ATTR_DOC_DOCTYPE, |
374 UTF16ToUTF8(doctype.name())); | 380 base::UTF16ToUTF8(doctype.name())); |
375 } | 381 } |
376 | 382 |
377 const gfx::Size& scroll_offset = document.frame()->scrollOffset(); | 383 const gfx::Size& scroll_offset = document.frame()->scrollOffset(); |
378 dst->AddIntAttribute(dst->ATTR_SCROLL_X, scroll_offset.width()); | 384 dst->AddIntAttribute(dst->ATTR_SCROLL_X, scroll_offset.width()); |
379 dst->AddIntAttribute(dst->ATTR_SCROLL_Y, scroll_offset.height()); | 385 dst->AddIntAttribute(dst->ATTR_SCROLL_Y, scroll_offset.height()); |
380 | 386 |
381 const gfx::Size& min_offset = document.frame()->minimumScrollOffset(); | 387 const gfx::Size& min_offset = document.frame()->minimumScrollOffset(); |
382 dst->AddIntAttribute(dst->ATTR_SCROLL_X_MIN, min_offset.width()); | 388 dst->AddIntAttribute(dst->ATTR_SCROLL_X_MIN, min_offset.width()); |
383 dst->AddIntAttribute(dst->ATTR_SCROLL_Y_MIN, min_offset.height()); | 389 dst->AddIntAttribute(dst->ATTR_SCROLL_Y_MIN, min_offset.height()); |
384 | 390 |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
471 // TODO(ctguil): We may want to remove this check as webkit stabilizes. | 477 // TODO(ctguil): We may want to remove this check as webkit stabilizes. |
472 if (child.isDetached()) | 478 if (child.isDetached()) |
473 return false; | 479 return false; |
474 | 480 |
475 // Skip children whose parent isn't this - see indirect_child_ids, above. | 481 // Skip children whose parent isn't this - see indirect_child_ids, above. |
476 // As an exception, include children of an iframe element. | 482 // As an exception, include children of an iframe element. |
477 bool is_iframe = false; | 483 bool is_iframe = false; |
478 WebNode node = parent.node(); | 484 WebNode node = parent.node(); |
479 if (!node.isNull() && node.isElementNode()) { | 485 if (!node.isNull() && node.isElementNode()) { |
480 WebElement element = node.to<WebElement>(); | 486 WebElement element = node.to<WebElement>(); |
481 is_iframe = (element.tagName() == ASCIIToUTF16("IFRAME")); | 487 is_iframe = (element.tagName() == base::ASCIIToUTF16("IFRAME")); |
482 } | 488 } |
483 | 489 |
484 return (is_iframe || IsParentUnignoredOf(parent, child)); | 490 return (is_iframe || IsParentUnignoredOf(parent, child)); |
485 } | 491 } |
486 | 492 |
487 } // namespace content | 493 } // namespace content |
OLD | NEW |