Bug 1151648: Construct accessible objects for SVG elements which have title or desc. r=MarcoZ

According to SVG Accessibility API Mappings, an SVG element which has title or desc element must be exposed.
https://w3c.github.io/svg-aam/#include_elements
Previously, we didn't expose <g> elements at all even if they had a title/desc, and we unconditionally exposed some other SVG elements even when they didn't.

Original patch by Takeshi Kurosawa.

Differential Revision: https://phabricator.services.mozilla.com/D77763
This commit is contained in:
James Teh 2020-06-02 06:59:31 +00:00
parent 34d39dc550
commit bfaf8c5057
3 changed files with 128 additions and 11 deletions

View File

@ -147,6 +147,20 @@ static bool MustBeAccessible(nsIContent* aContent, DocAccessible* aDocument) {
return false;
}
/**
* Return true if the SVG element should be accessible
*/
static bool MustSVGElementBeAccessible(nsIContent* aContent) {
// https://w3c.github.io/svg-aam/#include_elements
for (nsIContent* childElm = aContent->GetFirstChild(); childElm;
childElm = childElm->GetNextSibling()) {
if (childElm->IsAnyOfSVGElements(nsGkAtoms::title, nsGkAtoms::desc)) {
return true;
}
}
return false;
}
/**
* Used by XULMap.h to map both menupopup and popup elements
*/
@ -1140,7 +1154,7 @@ Accessible* nsAccessibilityService::CreateAccessible(nsINode* aNode,
if (!newAcc) {
if (content->IsSVGElement()) {
SVGGeometryFrame* geometryFrame = do_QueryFrame(frame);
if (geometryFrame) {
if (geometryFrame && MustSVGElementBeAccessible(content)) {
// A graphic elements: rect, circle, ellipse, line, path, polygon,
// polyline and image. A 'use' and 'text' graphic elements require
// special support.
@ -1149,6 +1163,9 @@ Accessible* nsAccessibilityService::CreateAccessible(nsINode* aNode,
newAcc = new HyperTextAccessibleWrap(content->AsElement(), document);
} else if (content->IsSVGElement(nsGkAtoms::svg)) {
newAcc = new EnumRoleAccessible<roles::DIAGRAM>(content, document);
} else if (content->IsSVGElement(nsGkAtoms::g) &&
MustSVGElementBeAccessible(content)) {
newAcc = new EnumRoleAccessible<roles::GROUPING>(content, document);
}
} else if (content->IsMathMLElement()) {

View File

@ -16,6 +16,7 @@
<script type="application/javascript">
function doTests() {
testRole("svg", ROLE_DIAGRAM);
testRole("g", ROLE_GROUPING);
testRole("rect", ROLE_GRAPHIC);
testRole("circle", ROLE_GRAPHIC);
testRole("ellipse", ROLE_GRAPHIC);
@ -47,21 +48,40 @@
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" id="svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="g">
<title>g</title>
</g>
<rect width="300" height="100" id="rect"
style="fill:rgb(0,0,255);stroke-width:1;stroke:rgb(0,0,0)"/>
style="fill:rgb(0,0,255);stroke-width:1;stroke:rgb(0,0,0)">
<title>rect</title>
</rect>
<circle cx="100" cy="50" r="40" stroke="black" id="circle"
stroke-width="2" fill="red"/>
stroke-width="2" fill="red">
<title>circle</title>
</circle>
<ellipse cx="300" cy="80" rx="100" ry="50" id="ellipse"
style="fill:yellow;stroke:purple;stroke-width:2"/>
style="fill:yellow;stroke:purple;stroke-width:2">
<title>ellipse</title>
</ellipse>
<line x1="0" y1="0" x2="200" y2="200" id="line"
style="stroke:rgb(255,0,0);stroke-width:2"/>
style="stroke:rgb(255,0,0);stroke-width:2">
<title>line</title>
</line>
<polygon points="200,10 250,190 160,210" id="polygon"
style="fill:lime;stroke:purple;stroke-width:1"/>
style="fill:lime;stroke:purple;stroke-width:1">
<title>polygon</title>
</polygon>
<polyline points="20,20 40,25 60,40 80,120 120,140 200,180" id="polyline"
style="fill:none;stroke:black;stroke-width:3" />
<path d="M150 0 L75 200 L225 200 Z" id="path"/>
style="fill:none;stroke:black;stroke-width:3" >
<title>polyline</title>
</polyline>
<path d="M150 0 L75 200 L225 200 Z" id="path">
<title>path</title>
</path>
<image x1="25" y1="80" width="50" height="20" id="image"
xlink:href="../moz.png"/>
xlink:href="../moz.png">
<title>image</title>
</image>
</svg>
</body>

View File

@ -13,6 +13,7 @@
<script type="application/javascript">
function doTest() {
// svgText
var accTree = {
role: ROLE_DIAGRAM,
children: [
@ -26,7 +27,55 @@
},
],
};
testAccessibleTree("svgItem", accTree);
testAccessibleTree("svgText", accTree);
// svg1
accTree = {
role: ROLE_DIAGRAM,
children: []
};
testAccessibleTree("svg1", accTree);
// svg2
accTree = {
role: ROLE_DIAGRAM,
children: [
{
role: ROLE_GROUPING,
children: []
}
]
};
testAccessibleTree("svg2", accTree);
// svg3
accTree = {
role: ROLE_DIAGRAM,
children: [
{
role: ROLE_GRAPHIC,
children: []
}
]
};
testAccessibleTree("svg3", accTree);
// svg4
accTree = {
role: ROLE_DIAGRAM,
children: [
{
role: ROLE_GROUPING,
children: [
{
role: ROLE_GRAPHIC,
children: []
}
]
}
]
};
testAccessibleTree("svg4", accTree);
SimpleTest.finish();
}
@ -40,8 +89,39 @@
<div id="content" style="display: none"></div>
<pre id="test">
</pre>
<svg id="svgItem">
<svg id="svgText">
<text>This is some text</text>
</svg>
<!-- no accessible objects -->
<svg id="svg1">
<g id="g1">
<rect width="300" height="100" id="rect1" style="fill:#00f" />
</g>
</svg>
<svg id="svg2">
<g id="g2">
<title>g</title>
<rect width="300" height="100" id="rect2" style="fill:#00f" />
</g>
</svg>
<svg id="svg3">
<g id="g3">
<rect width="300" height="100" id="rect3" style="fill:#00f">
<title>rect</title>
</rect>
</g>
</svg>
<svg id="svg4">
<g id="g4">
<title>g</title>
<rect width="300" height="100" id="rect4" style="fill:#00f">
<title>rect</title>
</rect>
</g>
</svg>
</body>
</html>