OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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/blink_ax_tree_source.h" | 5 #include "content/renderer/accessibility/blink_ax_tree_source.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 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
53 // |ancestor| is the *first* ancestor that isn't marked as | 53 // |ancestor| is the *first* ancestor that isn't marked as |
54 // accessibilityIsIgnored(). | 54 // accessibilityIsIgnored(). |
55 bool IsParentUnignoredOf(WebAXObject ancestor, | 55 bool IsParentUnignoredOf(WebAXObject ancestor, |
56 WebAXObject child) { | 56 WebAXObject child) { |
57 WebAXObject parent = child.parentObject(); | 57 WebAXObject parent = child.parentObject(); |
58 while (!parent.isDetached() && parent.accessibilityIsIgnored()) | 58 while (!parent.isDetached() && parent.accessibilityIsIgnored()) |
59 parent = parent.parentObject(); | 59 parent = parent.parentObject(); |
60 return parent.equals(ancestor); | 60 return parent.equals(ancestor); |
61 } | 61 } |
62 | 62 |
63 bool IsTrue(std::string html_value) { | |
64 return LowerCaseEqualsASCII(html_value, "true"); | |
65 } | |
66 | |
67 std::string GetEquivalentAriaRoleString(const ui::AXRole role) { | 63 std::string GetEquivalentAriaRoleString(const ui::AXRole role) { |
68 switch (role) { | 64 switch (role) { |
69 case ui::AX_ROLE_ARTICLE: | 65 case ui::AX_ROLE_ARTICLE: |
70 return "article"; | 66 return "article"; |
71 case ui::AX_ROLE_BANNER: | 67 case ui::AX_ROLE_BANNER: |
72 return "banner"; | 68 return "banner"; |
73 case ui::AX_ROLE_BUTTON: | 69 case ui::AX_ROLE_BUTTON: |
74 return "button"; | 70 return "button"; |
75 case ui::AX_ROLE_COMPLEMENTARY: | 71 case ui::AX_ROLE_COMPLEMENTARY: |
76 return "complementary"; | 72 return "complementary"; |
(...skipping 229 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
306 if (dst->role == ui::AX_ROLE_LIST_BOX_OPTION && | 302 if (dst->role == ui::AX_ROLE_LIST_BOX_OPTION && |
307 src.isSelectedOptionActive()) { | 303 src.isSelectedOptionActive()) { |
308 dst->state |= (1 << ui::AX_STATE_FOCUSED); | 304 dst->state |= (1 << ui::AX_STATE_FOCUSED); |
309 } | 305 } |
310 | 306 |
311 if (src.canvasHasFallbackContent()) | 307 if (src.canvasHasFallbackContent()) |
312 dst->AddBoolAttribute(ui::AX_ATTR_CANVAS_HAS_FALLBACK, true); | 308 dst->AddBoolAttribute(ui::AX_ATTR_CANVAS_HAS_FALLBACK, true); |
313 | 309 |
314 WebNode node = src.node(); | 310 WebNode node = src.node(); |
315 bool is_iframe = false; | 311 bool is_iframe = false; |
316 std::string live_atomic; | |
317 std::string live_busy; | |
318 std::string live_status; | |
319 std::string live_relevant; | |
320 | 312 |
321 if (!node.isNull() && node.isElementNode()) { | 313 if (!node.isNull() && node.isElementNode()) { |
322 WebElement element = node.to<WebElement>(); | 314 WebElement element = node.to<WebElement>(); |
323 is_iframe = (element.tagName() == ASCIIToUTF16("IFRAME")); | 315 is_iframe = (element.tagName() == ASCIIToUTF16("IFRAME")); |
324 | 316 |
325 if (LowerCaseEqualsASCII(element.getAttribute("aria-expanded"), "true")) | 317 if (LowerCaseEqualsASCII(element.getAttribute("aria-expanded"), "true")) |
326 dst->state |= (1 << ui::AX_STATE_EXPANDED); | 318 dst->state |= (1 << ui::AX_STATE_EXPANDED); |
327 | 319 |
328 // TODO(ctguil): The tagName in WebKit is lower cased but | 320 // TODO(ctguil): The tagName in WebKit is lower cased but |
329 // HTMLElement::nodeName calls localNameUpper. Consider adding | 321 // HTMLElement::nodeName calls localNameUpper. Consider adding |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
364 // ARIA role. | 356 // ARIA role. |
365 if (element.hasAttribute("role")) { | 357 if (element.hasAttribute("role")) { |
366 dst->AddStringAttribute(ui::AX_ATTR_ROLE, | 358 dst->AddStringAttribute(ui::AX_ATTR_ROLE, |
367 UTF16ToUTF8(element.getAttribute("role"))); | 359 UTF16ToUTF8(element.getAttribute("role"))); |
368 } else { | 360 } else { |
369 std::string role = GetEquivalentAriaRoleString(dst->role); | 361 std::string role = GetEquivalentAriaRoleString(dst->role); |
370 if (!role.empty()) | 362 if (!role.empty()) |
371 dst->AddStringAttribute(ui::AX_ATTR_ROLE, role); | 363 dst->AddStringAttribute(ui::AX_ATTR_ROLE, role); |
372 } | 364 } |
373 | 365 |
374 // Live region attributes | |
375 live_atomic = UTF16ToUTF8(element.getAttribute("aria-atomic")); | |
376 live_busy = UTF16ToUTF8(element.getAttribute("aria-busy")); | |
377 live_status = UTF16ToUTF8(element.getAttribute("aria-live")); | |
378 live_relevant = UTF16ToUTF8(element.getAttribute("aria-relevant")); | |
379 | |
380 // Browser plugin (used in a <webview>). | 366 // Browser plugin (used in a <webview>). |
381 if (node_to_browser_plugin_instance_id_map_) { | 367 if (node_to_browser_plugin_instance_id_map_) { |
382 BrowserPlugin* browser_plugin = BrowserPlugin::GetFromNode(element); | 368 BrowserPlugin* browser_plugin = BrowserPlugin::GetFromNode(element); |
383 if (browser_plugin) { | 369 if (browser_plugin) { |
384 (*node_to_browser_plugin_instance_id_map_)[dst->id] = | 370 (*node_to_browser_plugin_instance_id_map_)[dst->id] = |
385 browser_plugin->browser_plugin_instance_id(); | 371 browser_plugin->browser_plugin_instance_id(); |
386 dst->AddBoolAttribute(ui::AX_ATTR_IS_AX_TREE_HOST, true); | 372 dst->AddBoolAttribute(ui::AX_ATTR_IS_AX_TREE_HOST, true); |
387 } | 373 } |
388 } | 374 } |
389 } | 375 } |
390 | 376 |
391 // Walk up the parent chain to set live region attributes of containers | 377 if (src.isInLiveRegion()) { |
392 std::string container_live_atomic; | 378 dst->AddBoolAttribute(ui::AX_ATTR_LIVE_ATOMIC, src.liveRegionAtomic()); |
393 std::string container_live_busy; | 379 dst->AddBoolAttribute(ui::AX_ATTR_LIVE_BUSY, src.liveRegionBusy()); |
394 std::string container_live_status; | 380 dst->AddStringAttribute(ui::AX_ATTR_LIVE_STATUS, |
395 std::string container_live_relevant; | 381 UTF16ToUTF8(src.liveRegionStatus())); |
396 WebAXObject container_accessible = src; | 382 dst->AddStringAttribute(ui::AX_ATTR_LIVE_RELEVANT, |
397 while (!container_accessible.isDetached()) { | 383 UTF16ToUTF8(src.liveRegionRelevant())); |
398 WebNode container_node = container_accessible.node(); | |
399 if (!container_node.isNull() && container_node.isElementNode()) { | |
400 WebElement container_elem = container_node.to<WebElement>(); | |
401 if (container_elem.hasAttribute("aria-atomic") && | |
402 container_live_atomic.empty()) { | |
403 container_live_atomic = | |
404 UTF16ToUTF8(container_elem.getAttribute("aria-atomic")); | |
405 } | |
406 if (container_elem.hasAttribute("aria-busy") && | |
407 container_live_busy.empty()) { | |
408 container_live_busy = | |
409 UTF16ToUTF8(container_elem.getAttribute("aria-busy")); | |
410 } | |
411 if (container_elem.hasAttribute("aria-live") && | |
412 container_live_status.empty()) { | |
413 container_live_status = | |
414 UTF16ToUTF8(container_elem.getAttribute("aria-live")); | |
415 } | |
416 if (container_elem.hasAttribute("aria-relevant") && | |
417 container_live_relevant.empty()) { | |
418 container_live_relevant = | |
419 UTF16ToUTF8(container_elem.getAttribute("aria-relevant")); | |
420 } | |
421 } | |
422 container_accessible = container_accessible.parentObject(); | |
423 } | |
424 | |
425 if (!live_atomic.empty()) | |
426 dst->AddBoolAttribute(ui::AX_ATTR_LIVE_ATOMIC, IsTrue(live_atomic)); | |
427 if (!live_busy.empty()) | |
428 dst->AddBoolAttribute(ui::AX_ATTR_LIVE_BUSY, IsTrue(live_busy)); | |
429 if (!live_status.empty()) | |
430 dst->AddStringAttribute(ui::AX_ATTR_LIVE_STATUS, live_status); | |
431 if (!live_relevant.empty()) | |
432 dst->AddStringAttribute(ui::AX_ATTR_LIVE_RELEVANT, live_relevant); | |
433 | |
434 if (!container_live_atomic.empty()) { | |
435 dst->AddBoolAttribute(ui::AX_ATTR_CONTAINER_LIVE_ATOMIC, | 384 dst->AddBoolAttribute(ui::AX_ATTR_CONTAINER_LIVE_ATOMIC, |
436 IsTrue(container_live_atomic)); | 385 src.containerLiveRegionAtomic()); |
437 } | |
438 if (!container_live_busy.empty()) { | |
439 dst->AddBoolAttribute(ui::AX_ATTR_CONTAINER_LIVE_BUSY, | 386 dst->AddBoolAttribute(ui::AX_ATTR_CONTAINER_LIVE_BUSY, |
440 IsTrue(container_live_busy)); | 387 src.containerLiveRegionBusy()); |
441 } | |
442 if (!container_live_status.empty()) { | |
443 dst->AddStringAttribute(ui::AX_ATTR_CONTAINER_LIVE_STATUS, | 388 dst->AddStringAttribute(ui::AX_ATTR_CONTAINER_LIVE_STATUS, |
444 container_live_status); | 389 UTF16ToUTF8(src.containerLiveRegionStatus())); |
445 } | |
446 if (!container_live_relevant.empty()) { | |
447 dst->AddStringAttribute(ui::AX_ATTR_CONTAINER_LIVE_RELEVANT, | 390 dst->AddStringAttribute(ui::AX_ATTR_CONTAINER_LIVE_RELEVANT, |
448 container_live_relevant); | 391 UTF16ToUTF8(src.containerLiveRegionRelevant())); |
449 } | 392 } |
450 | 393 |
451 if (dst->role == ui::AX_ROLE_PROGRESS_INDICATOR || | 394 if (dst->role == ui::AX_ROLE_PROGRESS_INDICATOR || |
452 dst->role == ui::AX_ROLE_SCROLL_BAR || | 395 dst->role == ui::AX_ROLE_SCROLL_BAR || |
453 dst->role == ui::AX_ROLE_SLIDER || | 396 dst->role == ui::AX_ROLE_SLIDER || |
454 dst->role == ui::AX_ROLE_SPIN_BUTTON) { | 397 dst->role == ui::AX_ROLE_SPIN_BUTTON) { |
455 dst->AddFloatAttribute(ui::AX_ATTR_VALUE_FOR_RANGE, src.valueForRange()); | 398 dst->AddFloatAttribute(ui::AX_ATTR_VALUE_FOR_RANGE, src.valueForRange()); |
456 dst->AddFloatAttribute(ui::AX_ATTR_MAX_VALUE_FOR_RANGE, | 399 dst->AddFloatAttribute(ui::AX_ATTR_MAX_VALUE_FOR_RANGE, |
457 src.maxValueForRange()); | 400 src.maxValueForRange()); |
458 dst->AddFloatAttribute(ui::AX_ATTR_MIN_VALUE_FOR_RANGE, | 401 dst->AddFloatAttribute(ui::AX_ATTR_MIN_VALUE_FOR_RANGE, |
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
611 AddIntListAttributeFromWebObjects(ui::AX_ATTR_OWNS_IDS, owns, dst); | 554 AddIntListAttributeFromWebObjects(ui::AX_ATTR_OWNS_IDS, owns, dst); |
612 } | 555 } |
613 | 556 |
614 blink::WebDocument BlinkAXTreeSource::GetMainDocument() const { | 557 blink::WebDocument BlinkAXTreeSource::GetMainDocument() const { |
615 if (render_frame_ && render_frame_->GetWebFrame()) | 558 if (render_frame_ && render_frame_->GetWebFrame()) |
616 return render_frame_->GetWebFrame()->document(); | 559 return render_frame_->GetWebFrame()->document(); |
617 return WebDocument(); | 560 return WebDocument(); |
618 } | 561 } |
619 | 562 |
620 } // namespace content | 563 } // namespace content |
OLD | NEW |