Bug 1954448: Add a contentSetup argument to addAccessibleTask to facilitate content setup before a test starts. r=tschuster,eeejay

After bug 1953866, it will no longer be possible to have inline `<script>` elements in any document which runs in a chrome context.
Several accessibility tests currently rely on this to set things up which can't be done in pure HTML/CSS, but which need to be done before the content is initially added to the accessibility tree so that we can explicitly test the initial state (vs the state after it is mutated).
To work around this, a content task can be specified using the contentSetup argument to addAccessibleTask.
This causes the following to happen:

1. aria-hidden="true" is set on the body, preventing the initial accessibility tree update from including any content.
2. contentTask is executed in the context of the document.
3. aria-hidden is removed from the body, so that all of the content (including any changes made by contentSetup) is processed by accessibility.
4. A reorder event is awaited on the body, so that we can guarantee that (3) is complete.

Subsequent patches will adjust existing tests as needed.

Differential Revision: https://phabricator.services.mozilla.com/D242489
This commit is contained in:
James Teh
2025-03-24 23:28:33 +00:00
parent eedc7abba3
commit 7e98770397

View File

@@ -348,6 +348,12 @@ function wrapWithIFrame(doc, options = {}) {
id: DEFAULT_IFRAME_DOC_BODY_ID, id: DEFAULT_IFRAME_DOC_BODY_ID,
...iframeDocBodyAttrs, ...iframeDocBodyAttrs,
}; };
if (options.contentSetup) {
// Hide the body initially so we can ensure that any changes made by
// contentSetup are included when the body's content is initially added to
// the accessibility tree.
iframeDocBodyAttrs["aria-hidden"] = "true";
}
if (options.remoteIframe) { if (options.remoteIframe) {
// eslint-disable-next-line @microsoft/sdl/no-insecure-url // eslint-disable-next-line @microsoft/sdl/no-insecure-url
const srcURL = new URL(`http://example.net/document-builder.sjs`); const srcURL = new URL(`http://example.net/document-builder.sjs`);
@@ -418,6 +424,11 @@ function snippetToURL(doc, options = {}) {
if (gIsIframe) { if (gIsIframe) {
doc = wrapWithIFrame(doc, options); doc = wrapWithIFrame(doc, options);
} else if (options.contentSetup) {
// Hide the body initially so we can ensure that any changes made by
// contentSetup are included when the body's content is initially added to
// the accessibility tree.
attrs["aria-hidden"] = "true";
} }
const encodedDoc = encodeURIComponent( const encodedDoc = encodeURIComponent(
@@ -595,6 +606,21 @@ function accessibleTask(doc, task, options = {}) {
} }
} }
if (options.contentSetup) {
info("Executing contentSetup");
const ready = waitForEvent(EVENT_REORDER, currentContentDoc());
await invokeContentTask(browser, [], options.contentSetup);
// snippetToURL set aria-hidden on the body. We now Remove aria-hidden
// and wait for a reorder on the body. This guarantees that any
// changes made by contentSetup are included when the body's content
// is initially added to the accessibility tree and that the
// accessibility tree is up to date.
await invokeContentTask(browser, [], () => {
content.document.body.removeAttribute("aria-hidden");
});
await ready;
info("contentSetup done");
}
await loadContentScripts(browser, { await loadContentScripts(browser, {
script: "Common.sys.mjs", script: "Common.sys.mjs",
symbol: "CommonUtils", symbol: "CommonUtils",
@@ -670,6 +696,22 @@ function accessibleTask(doc, task, options = {}) {
* - {CacheDomain} cacheDomains * - {CacheDomain} cacheDomains
* The set of cache domains that should be present at the start of the * The set of cache domains that should be present at the start of the
* test. If not set, all cache domains will be present. * test. If not set, all cache domains will be present.
* - {Function|AsyncFunction} contentSetup
* An optional task to run to set up the content document before the
* test starts. If this test is to be run as a chrome document in the
* parent process (chrome: true), This should be used instead of an
* inline <script> element in the test snippet, since inline script is
* not allowed in such documents. This task is ultimately executed
* using SpecialPowers.spawn. Any updates to the content within the
* body will be included when the content is initially added to the
* accessibility tree. The accessibility tree is guaranteed to be up
* to date when the test starts. This will not work correctly for
* changes to the html or body elements themselves. Note that you will
* need to define this exactly as follows:
* contentSetup: async function contentSetup() { ... }
* async contentSetup() will fail when the task is serialized.
* contentSetup: async function() will be changed to
* async contentSetup() by the linter and likewise fail.
*/ */
function addAccessibleTask(doc, task, options = {}) { function addAccessibleTask(doc, task, options = {}) {
const { const {