Bug 1540904 - added full page API for accessibility walker actor. r=pbro

Differential Revision: https://phabricator.services.mozilla.com/D26458

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Yura Zenevich 2019-04-10 18:36:02 +00:00
Родитель 2c9b6e5406
Коммит 4c0b4af80b
6 изменённых файлов: 227 добавлений и 1 удалений

Просмотреть файл

@ -122,6 +122,27 @@ function isStale(accessible) {
return !!(extraState.value & Ci.nsIAccessibleStates.EXT_STATE_STALE);
}
/**
* Get accessibility audit starting with the passed accessible object as a root.
*
* @param {Object} acc
* AccessibileActor to be used as the root for the audit.
* @param {Map} report
* An accumulator map to be used to store audit information.
*/
function getAudit(acc, report) {
if (acc.isDefunct) {
return;
}
// Audit returns a promise, save the actual value in the report.
report.set(acc, acc.audit().then(result => report.set(acc, result)));
for (const child of acc.children()) {
getAudit(child, report);
}
}
/**
* The AccessibleWalkerActor stores a cache of AccessibleActors that represent
* accessible objects in a given document.
@ -367,6 +388,30 @@ const AccessibleWalkerActor = ActorClassWithSpec(accessibleWalkerSpec, {
{ accessible: parent, children: parent.children() }));
},
/**
* Run accessibility audit and return relevant ancestries for AccessibleActors
* that have non-empty audit checks.
*
* @return {Promise}
* A promise that resolves when the audit is complete and all relevant
* ancestries are calculated.
*/
async audit() {
const doc = await this.getDocument();
const report = new Map();
getAudit(doc, report);
await Promise.all(report.values());
const ancestries = [];
for (const [acc, audit] of report.entries()) {
if (audit && Object.values(audit).filter(check => check != null).length > 0) {
ancestries.push(this.getAncestry(acc));
}
}
return Promise.all(ancestries);
},
onHighlighterEvent: function(data) {
this.emit("highlighter-event", data);
},

Просмотреть файл

@ -5,6 +5,7 @@ support-files =
head.js
animation.html
animation-data.html
doc_accessibility_audit.html
doc_accessibility_infobar.html
doc_accessibility.html
doc_allocations.html
@ -47,6 +48,7 @@ skip-if = (os == 'win' && processor == 'aarch64') # bug 1533184
skip-if = (os == 'win' && processor == 'aarch64') # bug 1533184
[browser_accessibility_simple.js]
skip-if = (os == 'win' && processor == 'aarch64') # bug 1533184
[browser_accessibility_walker_audit.js]
[browser_accessibility_walker.js]
skip-if = (os == 'win' && processor == 'aarch64') # bug 1533487
[browser_actor_error.js]

Просмотреть файл

@ -0,0 +1,163 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
// Checks for the AccessibleWalkerActor audit.
add_task(async function() {
const {target, accessibility} =
await initAccessibilityFrontForUrl(MAIN_DOMAIN + "doc_accessibility_audit.html");
const accessibles = [{
name: "",
role: "document",
value: "",
description: "",
keyboardShortcut: "",
childCount: 2,
domNodeType: 9,
indexInParent: 0,
states: [
"focused", "readonly", "focusable", "active", "opaque", "enabled", "sensitive",
],
actions: [],
attributes: {
display: "block",
"explicit-name": "true",
"margin-bottom": "8px",
"margin-left": "8px",
"margin-right": "8px",
"margin-top": "8px",
tag: "body",
"text-align": "start",
"text-indent": "0px",
},
checks: {
"CONTRAST": null,
},
}, {
name: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do " +
"eiusmod tempor incididunt ut labore et dolore magna aliqua.",
role: "heading",
value: "",
description: "",
keyboardShortcut: "",
childCount: 1,
domNodeType: 1,
indexInParent: 0,
states: [ "selectable text", "opaque", "enabled", "sensitive" ],
actions: [],
attributes: {
display: "block",
formatting: "block",
id: "h1",
level: "1",
"margin-bottom": "21.4333px",
"margin-left": "0px",
"margin-right": "0px",
"margin-top": "21.4333px",
tag: "h1",
"text-align": "start",
"text-indent": "0px",
},
checks: {
"CONTRAST": null,
},
}, {
name: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do " +
"eiusmod tempor incididunt ut labore et dolore magna aliqua.",
role: "text leaf",
value: "",
description: "",
keyboardShortcut: "",
childCount: 0,
domNodeType: 3,
indexInParent: 0,
states: [ "opaque", "enabled", "sensitive" ],
actions: [],
attributes: { "explicit-name": "true" },
checks: {
"CONTRAST": {
"value": 21,
"color": [0, 0, 0, 1],
"backgroundColor": [255, 255, 255, 1],
"isLargeText": true,
},
},
}, {
name: "",
role: "paragraph",
value: "",
description: "",
keyboardShortcut: "",
childCount: 1,
domNodeType: 1,
indexInParent: 1,
states: [ "selectable text", "opaque", "enabled", "sensitive" ],
actions: [ "Press" ],
attributes: {
display: "block",
formatting: "block",
id: "p",
"margin-bottom": "16px",
"margin-left": "0px",
"margin-right": "0px",
"margin-top": "16px",
tag: "p",
"text-align": "start",
"text-indent": "0px",
},
checks: {
"CONTRAST": null,
},
}, {
name: "Accessible Paragraph",
role: "text leaf",
value: "",
description: "",
keyboardShortcut: "",
childCount: 0,
domNodeType: 3,
indexInParent: 0,
states: [ "opaque", "enabled", "sensitive" ],
actions: [],
attributes: { "explicit-name": "true" },
checks: {
"CONTRAST": {
"value": 21,
"color": [0, 0, 0, 1],
"backgroundColor": [255, 255, 255, 1],
"isLargeText": false,
},
},
}];
function findAccessible(name, role) {
return accessibles.find(accessible =>
accessible.name === name && accessible.role === role);
}
const a11yWalker = await accessibility.getWalker();
ok(a11yWalker, "The AccessibleWalkerFront was returned");
await accessibility.enable();
info("Checking AccessibleWalker audit functionality");
const ancestries = await a11yWalker.audit();
for (const ancestry of ancestries) {
for (const { accessible, children } of ancestry) {
checkA11yFront(accessible,
findAccessible(accessibles.name, accessibles.role));
for (const child of children) {
checkA11yFront(child,
findAccessible(child.name, child.role));
}
}
}
await accessibility.disable();
await waitForA11yShutdown();
await target.destroy();
gBrowser.removeCurrentTab();
});

Просмотреть файл

@ -0,0 +1,10 @@
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<h1 id="h1">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</h1>
<p id="p">Accessible Paragraph</p>
</body>
</html>

Просмотреть файл

@ -272,7 +272,7 @@ function checkA11yFront(front, expected, expectedFront) {
}
for (const key in expected) {
if (["actions", "states", "attributes"].includes(key)) {
if (["actions", "states", "attributes", "checks"].includes(key)) {
SimpleTest.isDeeply(front[key], expected[key],
`Accessible Front has correct ${key}`);
} else {

Просмотреть файл

@ -162,6 +162,12 @@ const accessibleWalkerSpec = generateActorSpec({
ancestry: RetVal("array:accessibleWithChildren"),
},
},
audit: {
request: {},
response: {
audit: RetVal("array:array:accessibleWithChildren"),
},
},
highlightAccessible: {
request: {
accessible: Arg(0, "accessible"),