Bug 1747157: Use a non-remote browser to load snippets in the parent process in a11y browser tests instead of a chrome:// page and .innerHTML. r=eeejay

Creating a non-remote browser is obscure, but it turns out that it is possible.
BrowserTestUtils.addTab/gBrowser.addTab takes a forceNotRemote: true option, but even though this doesn't set remote on the browser element, it still sets maychangeremoteness.
To work around this, we create a tab with a blank document and forceNotRemote: true, remove maychangeremoteness and finally set the src to load our document.
We must also set a pref to allow this.
With this patch, the sanitizer will no longer strip elements from our snippets.

Differential Revision: https://phabricator.services.mozilla.com/D135147
This commit is contained in:
James Teh 2022-01-05 23:46:20 +00:00
Родитель bb71ecb332
Коммит ea75bab2da
3 изменённых файлов: 28 добавлений и 32 удалений

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

@ -5,7 +5,6 @@ support-files =
*.jsm *.jsm
head.js head.js
shared-head.js shared-head.js
chrome-document-builder.html
[browser_shutdown_acc_reference.js] [browser_shutdown_acc_reference.js]
skip-if = (os == 'linux' && debug && bits == 64) #Bug 1421307 skip-if = (os == 'linux' && debug && bits == 64) #Bug 1421307

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

@ -1,22 +0,0 @@
<!doctype html>
<html>
<head>
<meta charset="utf-8"/>
<title>Accessibility Test</title>
<script>
/*
* This file is used to load an HTML snippet in the parent process via a
* chrome:// URL. It takes the html as a query string parameter and simply
* replaces the content of the document with that HTML.
*/
'use strict';
window.addEventListener("DOMContentLoaded", function() {
const params = new URLSearchParams(document.location.search);
const html = params.get("html");
// eslint-disable-next-line no-unsanitized/property
document.body.innerHTML = html;
});
</script>
</head>
<body></body>
</html>

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

@ -431,16 +431,10 @@ function accessibleTask(doc, task, options = {}) {
gIsRemoteIframe = options.remoteIframe; gIsRemoteIframe = options.remoteIframe;
gIsIframe = options.iframe || gIsRemoteIframe; gIsIframe = options.iframe || gIsRemoteIframe;
let url; let url;
if (options.chrome) { if (options.chrome && doc.endsWith("html")) {
// Load with a chrome:// URL so this loads as a chrome document in the // Load with a chrome:// URL so this loads as a chrome document in the
// parent process. // parent process.
if (doc.endsWith("html")) {
url = `${CURRENT_DIR}${doc}`; url = `${CURRENT_DIR}${doc}`;
} else {
const urlObj = new URL(`${CURRENT_DIR}chrome-document-builder.html`);
urlObj.searchParams.append("html", doc);
url = urlObj.href;
}
} else if (doc.endsWith("html") && !gIsIframe) { } else if (doc.endsWith("html") && !gIsIframe) {
url = `${CURRENT_CONTENT_DIR}${doc}`; url = `${CURRENT_CONTENT_DIR}${doc}`;
} else { } else {
@ -474,7 +468,22 @@ function accessibleTask(doc, task, options = {}) {
await BrowserTestUtils.withNewTab( await BrowserTestUtils.withNewTab(
{ {
gBrowser, gBrowser,
url, // For chrome, we need a non-remote browser.
opening: !options.chrome
? url
: () => {
// Passing forceNotRemote: true still sets maychangeremoteness,
// which will cause data: URIs to load remotely. There's no way to
// avoid this with gBrowser or BrowserTestUtils. Therefore, we
// load a blank document initially and replace it below.
gBrowser.selectedTab = BrowserTestUtils.addTab(
gBrowser,
"about:blank",
{
forceNotRemote: true,
}
);
},
}, },
async function(browser) { async function(browser) {
registerCleanupFunction(() => { registerCleanupFunction(() => {
@ -486,6 +495,16 @@ function accessibleTask(doc, task, options = {}) {
} }
}); });
if (options.chrome) {
await SpecialPowers.pushPrefEnv({
set: [["security.allow_unsafe_parent_loads", true]],
});
// Ensure this never becomes a remote browser.
browser.removeAttribute("maychangeremoteness");
// Now we can load our page without it becoming remote.
browser.setAttribute("src", url);
}
await SimpleTest.promiseFocus(browser); await SimpleTest.promiseFocus(browser);
await loadContentScripts(browser, "Common.jsm"); await loadContentScripts(browser, "Common.jsm");