Diff
Modified: trunk/LayoutTests/ChangeLog (184675 => 184676)
--- trunk/LayoutTests/ChangeLog 2015-05-20 23:34:48 UTC (rev 184675)
+++ trunk/LayoutTests/ChangeLog 2015-05-20 23:42:08 UTC (rev 184676)
@@ -1,3 +1,15 @@
+2015-05-20 Chris Fleizach <[email protected]>
+
+ AX: improve list heuristics (presentational use versus actual lists)
+ https://bugs.webkit.org/show_bug.cgi?id=134187
+
+ Reviewed by Darin Adler.
+
+ * accessibility/list-detection-expected.txt:
+ * accessibility/list-detection.html:
+ * accessibility/list-detection2-expected.txt: Added.
+ * accessibility/list-detection2.html: Added.
+
2015-05-20 Antti Koivisto <[email protected]>
REGRESSION (r172591): Can no longer style <optgroup> with colors (LayoutTests/fast/forms/select/optgroup-rendering.html)
Modified: trunk/LayoutTests/accessibility/list-detection-expected.txt (184675 => 184676)
--- trunk/LayoutTests/accessibility/list-detection-expected.txt 2015-05-20 23:34:48 UTC (rev 184675)
+++ trunk/LayoutTests/accessibility/list-detection-expected.txt 2015-05-20 23:42:08 UTC (rev 184676)
@@ -35,8 +35,8 @@
PASS axElement.role == 'AXRole: AXList' is true
-Unordered list with more than 1 item and no style is a list.
-PASS axElement.role == 'AXRole: AXList' is true
+Unordered list with more than 1 item and no style is not a list.
+PASS axElement.role == 'AXRole: AXList' is false
Unordered list with 1 item and no style is not list.
Modified: trunk/LayoutTests/accessibility/list-detection.html (184675 => 184676)
--- trunk/LayoutTests/accessibility/list-detection.html 2015-05-20 23:34:48 UTC (rev 184675)
+++ trunk/LayoutTests/accessibility/list-detection.html 2015-05-20 23:42:08 UTC (rev 184676)
@@ -40,7 +40,7 @@
<li>item</li>
</ul>
-<ul id="list9" style="list-style-type: none;" test-description="Unordered list with more than 1 item and no style is a list." is-list="true">
+<ul id="list9" style="list-style-type: none;" test-description="Unordered list with more than 1 item and no style is not a list." is-list="false">
<li>item</li>
<li>item</li>
</ul>
Added: trunk/LayoutTests/accessibility/list-detection2-expected.txt (0 => 184676)
--- trunk/LayoutTests/accessibility/list-detection2-expected.txt (rev 0)
+++ trunk/LayoutTests/accessibility/list-detection2-expected.txt 2015-05-20 23:42:08 UTC (rev 184676)
@@ -0,0 +1,25 @@
+This tests that heurisitics for determining meaningful lists versus presentational lists result in the same computed role, regardless of platform.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS successfullyParsed is true
+
+TEST COMPLETE
+PASS: ul[role="list"] w/ explicit role and displayed inline -> list.
+PASS: ul[role="list"] w/ explicit role but no markers -> list.
+PASS: ul w/ default list markers -> list.
+PASS: ol w/ default list counters -> list.
+PASS: ul w/ list-style-image -> list.
+PASS: ul w/ image content on ::before -> list.
+PASS: ul w/ image content on inline ::before -> list.
+PASS: ul w/ bullet content on ::before -> list.
+PASS: ul w/ bullet content on inline ::before -> list.
+PASS: ol w/ counter content on ::before -> list.
+PASS: ol w/ counter content on inline ::before -> list.
+PASS: ul w/ background image (NOT A LIST) -> group.
+PASS: ul w/ background on ::before (NOT A LIST) -> group.
+PASS: ul w/o explicit role and displayed inline, which defaults to no markers (NOT A LIST) -> group.
+PASS: ol w/o explicit role and displayed inline, which defaults to no markers (NOT A LIST) -> group.
+PASS: ul w/o explicit role and no markers (NOT A LIST) -> group.
+
Added: trunk/LayoutTests/accessibility/list-detection2.html (0 => 184676)
--- trunk/LayoutTests/accessibility/list-detection2.html (rev 0)
+++ trunk/LayoutTests/accessibility/list-detection2.html 2015-05-20 23:42:08 UTC (rev 184676)
@@ -0,0 +1,203 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>List; presentation heuristics</title>
+ <meta charset="utf-8">
+ <style type="text/css">
+ html, body {
+ font-size: 100%;
+ }
+ h1 {
+ font-size: 1em;
+ }
+ .inline, .inline li {
+ display: inline;
+ }
+ .nomarkers {
+ list-style: none;
+ }
+ .imagemarkers {
+ list-style-image: url(data:image/gif;base64,R0lGODlhEAARAJECAOHh4UpKSgAAAAAAACH5BAEAAAIALAAAAAAQABEAAAIllB8Zx63b4otSUWcvyuz5D4biSD7AiZroWSXa5r7CJNOvra1RAQA7);
+ }
+ .imagemarkersbefore li::before {
+ content: url(data:image/gif;base64,R0lGODlhEAARAJECAOHh4UpKSgAAAAAAACH5BAEAAAIALAAAAAAQABEAAAIllB8Zx63b4otSUWcvyuz5D4biSD7AiZroWSXa5r7CJNOvra1RAQA7) " ";
+ }
+ .bulletmarkersbefore li::before {
+ content: "• ";
+ }
+ .countermarkersbefore {
+ counter-reset: number;
+ list-style-type: none;
+ }
+ .countermarkersbefore li::before {
+ counter-increment: number;
+ content: counters(number,".") ". ";
+ }
+ .backgroundmarkers li {
+ padding-left: 30px;
+ background: transparent url(data:image/gif;base64,R0lGODlhEAARAJECAOHh4UpKSgAAAAAAACH5BAEAAAIALAAAAAAQABEAAAIllB8Zx63b4otSUWcvyuz5D4biSD7AiZroWSXa5r7CJNOvra1RAQA7) left center no-repeat;
+ }
+ .backgroundmarkersbefore li::before {
+ display: inline-block;
+ content: " ";
+ width: 17px;
+ height: 17px;
+ background: transparent url(data:image/gif;base64,R0lGODlhEAARAJECAOHh4UpKSgAAAAAAACH5BAEAAAIALAAAAAAQABEAAAIllB8Zx63b4otSUWcvyuz5D4biSD7AiZroWSXa5r7CJNOvra1RAQA7) left center no-repeat;
+ }
+</style>
+</head>
+<body _onload_="runTest();">
+<script src=""
+
+<div id="examples">
+
+ <!-- @data-role is the expectation -->
+
+ <h1>list because of explicit role, despite style and lack of list markers</h1>
+ <ul role="list" data-role="list" class="ex inline" data-note=" w/ explicit role and displayed inline">
+ <li>foo</li>
+ <li>bar</li>
+ <li>baz</li>
+ </ul>
+ <ul role="list" data-role="list" class="ex nomarkers" data-note=" w/ explicit role but no markers">
+ <li>foo</li>
+ <li>bar</li>
+ <li>baz</li>
+ </ul>
+
+ <h1>list because of rendered list markers (exposed as AXListMarker)</h1>
+ <ul data-role="list" class="ex" data-note=" w/ default list markers">
+ <li>foo</li>
+ <li>bar</li>
+ <li>baz</li>
+ </ul>
+ <ol data-role="list" class="ex" data-note=" w/ default list counters">
+ <li>foo</li>
+ <li>bar</li>
+ <li>baz</li>
+ </ol>
+ <ul data-role="list" class="ex imagemarkers" data-note=" w/ list-style-image">
+ <li>foo</li>
+ <li>bar</li>
+ <li>baz</li>
+ </ul>
+
+ <h1>list because these list markers consist of CSS-generated content on ::before pseudo element. Note: WebKit is not exposing these as AXListMarker; need another bug for that.</h1>
+ <ul data-role="list" class="ex nomarkers imagemarkersbefore" data-note=" w/ image content on ::before">
+ <li>foo</li>
+ <li>bar</li>
+ <li>baz</li>
+ </ul>
+ <ul data-role="list" class="ex nomarkers inline imagemarkersbefore" data-note=" w/ image content on inline ::before">
+ <li>foo</li>
+ <li>bar</li>
+ <li>baz</li>
+ </ul>
+ <ul data-role="list" class="ex nomarkers bulletmarkersbefore" data-note=" w/ bullet content on ::before">
+ <li>foo</li>
+ <li>bar</li>
+ <li>baz</li>
+ </ul>
+ <ul data-role="list" class="ex nomarkers inline bulletmarkersbefore" data-note=" w/ bullet content on inline ::before">
+ <li>foo</li>
+ <li>bar</li>
+ <li>baz</li>
+ </ul>
+ <ol data-role="list" class="ex nomarkers countermarkersbefore" data-note=" w/ counter content on ::before">
+ <li>foo</li>
+ <li>bar</li>
+ <li>baz</li>
+ </ol>
+ <ol data-role="list" class="ex nomarkers inline countermarkersbefore" data-note=" w/ counter content on inline ::before">
+ <li>foo</li>
+ <li>bar</li>
+ <li>baz</li>
+ </ol>
+
+ <p>Since many web pages suffer from "list-itis" and some users have noted that they don't want to hear about so many lists, any UL or OL that does not match one of the above heuristics should not be exposed as a list. Chances are that they are just presentational lists using the elements for the sake of a styling hook.</p>
+
+
+ <h1>EXPLICIT FAILURE CASES: These next examples are <strong>NOT</strong> lists because these "list markers" are faked as background images. One is even a background image on a ::before pseudo-element, but that does not count as a listmarker. List markers should only be inferred by the <code>content</code> property or the <code>list-style</code> properties.</h1>
+ <ul data-role="group" class="ex nomarkers backgroundmarkers" data-note=" w/ background image (NOT A LIST)">
+ <li>foo</li>
+ <li>bar</li>
+ <li>baz</li>
+ </ul>
+ <ul data-role="group" class="ex nomarkers backgroundmarkersbefore" data-note=" w/ background on ::before (NOT A LIST)">
+ <li>foo</li>
+ <li>bar</li>
+ <li>baz</li>
+ </ul>
+
+ <h1>EXPLICIT FAILURE CASES: These next examples are <strong>NOT</strong> there is no explicit role or any style or list markers to indicate this is actually intended as a list.</h1>
+ <ul data-role="group" class="ex inline" data-note=" w/o explicit role and displayed inline, which defaults to no markers (NOT A LIST)">
+ <li>foo</li>
+ <li>bar</li>
+ <li>baz</li>
+ </ul>
+ <ol data-role="group" class="ex inline" data-note=" w/o explicit role and displayed inline, which defaults to no markers (NOT A LIST)">
+ <li>foo</li>
+ <li>bar</li>
+ <li>baz</li>
+ </ol>
+ <ul data-role="group" class="ex nomarkers" data-note=" w/o explicit role and no markers (NOT A LIST)">
+ <li>foo</li>
+ <li>bar</li>
+ <li>baz</li>
+ </ul>
+
+
+</div>
+
+<div id="console"></div>
+<script>
+function runTest() {
+ if (window.testRunner && window.accessibilityController) {
+ description("This tests that heurisitics for determining meaningful lists versus presentational lists result in the same computed role, regardless of platform.")
+ var examples = document.querySelectorAll(".ex");
+ var el, contentAttrRoleString, axElement, computedAriaRole, output, expectedRole, expectation, result, note;
+ for (var i = 0, c = examples.length; i < c; i++) {
+ el = examples[i];
+ el.id = "ex" + i
+
+ axElement = accessibilityController.accessibleElementById(el.id);
+ if (!axElement)
+ continue;
+
+ computedAriaRole = axElement.computedRoleString;
+
+ contentAttrRoleString = el.getAttribute("role");
+ note = el.getAttribute("data-note")
+ output = el.tagName.toLowerCase() + (contentAttrRoleString ? ("[role=\""+contentAttrRoleString+"\"]") : "") + (note ? note : "");
+ output += " -> ";
+ output += computedAriaRole;
+ output += ". ";
+
+ expectedRole = "";
+ if (el.hasAttribute("data-role")) {
+ expectedRole = el.getAttribute("data-role");
+ }
+
+ expectation = expectedRole;
+ matchedResults = (computedAriaRole == expectedRole)
+
+ result = document.getElementById('console');
+ if (matchedResults) {
+ result.innerText += "PASS: " + output + "\n";
+ } else {
+ result.innerText += "FAIL: " + output + "Expected: " + expectation + ".\n";
+ }
+ }
+
+ // Once tests are complete, hide all the example markup.
+ examples = document.querySelectorAll(".ex, #examples");
+ for (var i = 0, c = examples.length; i < c; i++)
+ examples[i].style.display = "none";
+ }
+}
+</script>
+<script src=""
+</body>
+</html>
+
+
Modified: trunk/Source/WebCore/ChangeLog (184675 => 184676)
--- trunk/Source/WebCore/ChangeLog 2015-05-20 23:34:48 UTC (rev 184675)
+++ trunk/Source/WebCore/ChangeLog 2015-05-20 23:42:08 UTC (rev 184676)
@@ -1,3 +1,22 @@
+2015-05-20 Chris Fleizach <[email protected]>
+
+ AX: improve list heuristics (presentational use versus actual lists)
+ https://bugs.webkit.org/show_bug.cgi?id=134187
+
+ Reviewed by Darin Adler.
+
+ Improve heuristics for list detection by:
+ 1. Not exposing lists without list markers (unless explicitly marked as lists)
+ 2. Recognizing css: before-content as list markers
+
+ Test: accessibility/list-detection2.html
+
+ * accessibility/AccessibilityList.cpp:
+ (WebCore::AccessibilityList::isDescriptionList):
+ (WebCore::AccessibilityList::childHasPseudoVisibleListItemMarkers):
+ (WebCore::AccessibilityList::determineAccessibilityRole):
+ * accessibility/AccessibilityList.h:
+
2015-05-20 Antti Koivisto <[email protected]>
REGRESSION (r172591): Can no longer style <optgroup> with colors (LayoutTests/fast/forms/select/optgroup-rendering.html)
Modified: trunk/Source/WebCore/accessibility/AccessibilityList.cpp (184675 => 184676)
--- trunk/Source/WebCore/accessibility/AccessibilityList.cpp 2015-05-20 23:34:48 UTC (rev 184675)
+++ trunk/Source/WebCore/accessibility/AccessibilityList.cpp 2015-05-20 23:42:08 UTC (rev 184676)
@@ -32,6 +32,7 @@
#include "AXObjectCache.h"
#include "HTMLElement.h"
#include "HTMLNames.h"
+#include "PseudoElement.h"
#include "RenderListItem.h"
#include "RenderObject.h"
#include "RenderStyle.h"
@@ -97,6 +98,28 @@
return node && node->hasTagName(dlTag);
}
+bool AccessibilityList::childHasPseudoVisibleListItemMarkers(RenderObject* listItem)
+{
+ // Check if the list item has a pseudo-element that should be accessible (e.g. an image or text)
+ Element* listItemElement = downcast<Element>(listItem->node());
+ if (!listItemElement || !listItemElement->beforePseudoElement())
+ return false;
+
+ AccessibilityObject* axObj = axObjectCache()->getOrCreate(listItemElement->beforePseudoElement()->renderer());
+ if (!axObj)
+ return false;
+
+ if (!axObj->accessibilityIsIgnored())
+ return true;
+
+ for (const auto& child : axObj->children()) {
+ if (!child->accessibilityIsIgnored())
+ return true;
+ }
+
+ return false;
+}
+
AccessibilityRole AccessibilityList::determineAccessibilityRole()
{
m_ariaRole = determineAriaRoleAttribute();
@@ -131,21 +154,33 @@
listItemCount++;
else if (child->roleValue() == ListItemRole) {
RenderObject* listItem = child->renderer();
- if (listItem && listItem->isListItem()) {
- if (listItem->style().listStyleType() != NoneListStyle || listItem->style().listStyleImage())
+ if (!listItem)
+ continue;
+
+ // Rendered list items always count.
+ if (listItem->isListItem()) {
+ if (!hasVisibleMarkers && (listItem->style().listStyleType() != NoneListStyle || listItem->style().listStyleImage() || childHasPseudoVisibleListItemMarkers(listItem)))
hasVisibleMarkers = true;
listItemCount++;
+ } else if (listItem->node() && listItem->node()->hasTagName(liTag)) {
+ // Inline elements that are in a list with an explicit role should also count.
+ if (m_ariaRole == ListRole)
+ listItemCount++;
+
+ if (childHasPseudoVisibleListItemMarkers(listItem)) {
+ hasVisibleMarkers = true;
+ listItemCount++;
+ }
}
}
}
- bool unorderedList = isUnorderedList();
// Non <ul> lists and ARIA lists only need to have one child.
- // <ul> lists need to have 1 child, or visible markers.
- if (!unorderedList || ariaRoleAttribute() != UnknownRole) {
+ // <ul>, <ol> lists need to have visible markers.
+ if (ariaRoleAttribute() != UnknownRole) {
if (!listItemCount)
role = GroupRole;
- } else if (unorderedList && listItemCount <= 1 && !hasVisibleMarkers)
+ } else if (!hasVisibleMarkers)
role = GroupRole;
return role;
Modified: trunk/Source/WebCore/accessibility/AccessibilityList.h (184675 => 184676)
--- trunk/Source/WebCore/accessibility/AccessibilityList.h 2015-05-20 23:34:48 UTC (rev 184675)
+++ trunk/Source/WebCore/accessibility/AccessibilityList.h 2015-05-20 23:42:08 UTC (rev 184676)
@@ -49,6 +49,7 @@
virtual bool isList() const override { return true; }
virtual bool computeAccessibilityIsIgnored() const override;
virtual AccessibilityRole determineAccessibilityRole() override;
+ bool childHasPseudoVisibleListItemMarkers(RenderObject*);
};
} // namespace WebCore