summaryrefslogtreecommitdiffstats
path: root/toolkit/components/remotebrowserutils/tests/browser/browser_documentChannel.js
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--toolkit/components/remotebrowserutils/tests/browser/browser_documentChannel.js280
1 files changed, 280 insertions, 0 deletions
diff --git a/toolkit/components/remotebrowserutils/tests/browser/browser_documentChannel.js b/toolkit/components/remotebrowserutils/tests/browser/browser_documentChannel.js
new file mode 100644
index 0000000000..362bc9ee6d
--- /dev/null
+++ b/toolkit/components/remotebrowserutils/tests/browser/browser_documentChannel.js
@@ -0,0 +1,280 @@
+/* eslint-env webextensions */
+"use strict";
+
+const PRINT_POSTDATA = httpURL("print_postdata.sjs");
+const FILE_DUMMY = fileURL("dummy_page.html");
+const DATA_URL = "data:text/html,Hello%2C World!";
+const DATA_STRING = "Hello, World!";
+
+async function performLoad(browser, opts, action) {
+ let loadedPromise = BrowserTestUtils.browserLoaded(
+ browser,
+ false,
+ opts.url,
+ opts.maybeErrorPage
+ );
+ await action();
+ await loadedPromise;
+}
+
+const EXTENSION_DATA = {
+ manifest: {
+ name: "Simple extension test",
+ version: "1.0",
+ manifest_version: 2,
+ description: "",
+
+ permissions: ["proxy", "webRequest", "webRequestBlocking", "<all_urls>"],
+ },
+
+ files: {
+ "dummy.html": "<html>webext dummy</html>",
+ "redirect.html": "<html>webext redirect</html>",
+ },
+
+ extUrl: "",
+
+ async background() {
+ browser.test.log("background script running");
+ browser.webRequest.onAuthRequired.addListener(
+ async details => {
+ browser.test.log("webRequest onAuthRequired");
+
+ // A blocking request that returns a promise exercises a codepath that
+ // sets the notificationCallbacks on the channel to a JS object that we
+ // can't do directly QueryObject on with expected results.
+ // This triggered a crash which was fixed in bug 1528188.
+ return new Promise((resolve, reject) => {
+ setTimeout(resolve, 0);
+ });
+ },
+ { urls: ["*://*/*"] },
+ ["blocking"]
+ );
+ browser.webRequest.onBeforeRequest.addListener(
+ async details => {
+ browser.test.log("webRequest onBeforeRequest");
+ let isRedirect =
+ details.originUrl == browser.runtime.getURL("redirect.html") &&
+ details.url.endsWith("print_postdata.sjs");
+ let url = this.extUrl ? this.extUrl : details.url + "?redirected";
+ return isRedirect ? { redirectUrl: url } : {};
+ },
+ { urls: ["*://*/*"] },
+ ["blocking"]
+ );
+ browser.test.onMessage.addListener(async ({ method, url }) => {
+ if (method == "setRedirectUrl") {
+ this.extUrl = url;
+ }
+ browser.test.sendMessage("done");
+ });
+ },
+};
+
+async function withExtensionDummy(callback) {
+ let extension = ExtensionTestUtils.loadExtension(EXTENSION_DATA);
+ await extension.startup();
+ let rv = await callback(`moz-extension://${extension.uuid}/`, extension);
+ await extension.unload();
+ return rv;
+}
+
+async function postFrom(start, target) {
+ return BrowserTestUtils.withNewTab(
+ {
+ gBrowser,
+ url: start,
+ },
+ async function (browser) {
+ info("Test tab ready: postFrom " + start);
+
+ // Create the form element in our loaded URI.
+ await SpecialPowers.spawn(browser, [{ target }], function ({ target }) {
+ // eslint-disable-next-line no-unsanitized/property
+ content.document.body.innerHTML = `
+ <form method="post" action="${target}">
+ <input type="text" name="initialRemoteType" value="${Services.appinfo.remoteType}">
+ <input type="submit" id="submit">
+ </form>`;
+ });
+
+ // Perform a form POST submit load.
+ info("Performing POST submission");
+ await performLoad(
+ browser,
+ {
+ url(url) {
+ let enable =
+ url.startsWith(PRINT_POSTDATA) ||
+ url == target ||
+ url == DATA_URL;
+ if (!enable) {
+ info(`url ${url} is invalid to perform load`);
+ }
+ return enable;
+ },
+ maybeErrorPage: true,
+ },
+ async () => {
+ await SpecialPowers.spawn(browser, [], () => {
+ content.document.querySelector("#submit").click();
+ });
+ }
+ );
+
+ // Check that the POST data was submitted.
+ info("Fetching results");
+ return SpecialPowers.spawn(browser, [], () => {
+ return {
+ remoteType: Services.appinfo.remoteType,
+ location: "" + content.location.href,
+ body: content.document.body.textContent,
+ };
+ });
+ }
+ );
+}
+
+async function loadAndGetProcessID(browser, target) {
+ info(`Performing GET load: ${target}`);
+ await performLoad(
+ browser,
+ {
+ maybeErrorPage: true,
+ },
+ () => {
+ BrowserTestUtils.loadURIString(browser, target);
+ }
+ );
+
+ info(`Navigated to: ${target}`);
+ browser = gBrowser.selectedBrowser;
+ let processID = await SpecialPowers.spawn(browser, [], () => {
+ return Services.appinfo.processID;
+ });
+ return processID;
+}
+
+async function testLoadAndRedirect(
+ target,
+ expectedProcessSwitch,
+ testRedirect
+) {
+ let start = httpURL(`dummy_page.html`);
+ return BrowserTestUtils.withNewTab(
+ {
+ gBrowser,
+ url: start,
+ },
+ async function (_browser) {
+ info("Test tab ready: getFrom " + start);
+
+ let browser = gBrowser.selectedBrowser;
+ let firstProcessID = await SpecialPowers.spawn(browser, [], () => {
+ return Services.appinfo.processID;
+ });
+
+ info(`firstProcessID: ${firstProcessID}`);
+
+ let secondProcessID = await loadAndGetProcessID(browser, target);
+
+ info(`secondProcessID: ${secondProcessID}`);
+ Assert.equal(firstProcessID != secondProcessID, expectedProcessSwitch);
+
+ if (!testRedirect) {
+ return;
+ }
+
+ let thirdProcessID = await loadAndGetProcessID(browser, add307(target));
+
+ info(`thirdProcessID: ${thirdProcessID}`);
+ Assert.equal(firstProcessID != thirdProcessID, expectedProcessSwitch);
+ Assert.ok(secondProcessID == thirdProcessID);
+ }
+ );
+}
+
+add_task(async function test_enabled() {
+ // Force only one webIsolated content process to ensure same-origin loads
+ // always end in the same process.
+ await SpecialPowers.pushPrefEnv({
+ set: [["dom.ipc.processCount.webIsolated", 1]],
+ });
+
+ // URIs should correctly switch processes & the POST
+ // should succeed.
+ info("ENABLED -- FILE -- raw URI load");
+ let resp = await postFrom(FILE_DUMMY, PRINT_POSTDATA);
+ ok(E10SUtils.isWebRemoteType(resp.remoteType), "process switch");
+ is(resp.location, PRINT_POSTDATA, "correct location");
+ is(resp.body, "initialRemoteType=file", "correct POST body");
+
+ info("ENABLED -- FILE -- 307-redirect URI load");
+ let resp307 = await postFrom(FILE_DUMMY, add307(PRINT_POSTDATA));
+ ok(E10SUtils.isWebRemoteType(resp307.remoteType), "process switch");
+ is(resp307.location, PRINT_POSTDATA, "correct location");
+ is(resp307.body, "initialRemoteType=file", "correct POST body");
+
+ // Same with extensions
+ await withExtensionDummy(async extOrigin => {
+ info("ENABLED -- EXTENSION -- raw URI load");
+ let respExt = await postFrom(extOrigin + "dummy.html", PRINT_POSTDATA);
+ ok(E10SUtils.isWebRemoteType(respExt.remoteType), "process switch");
+ is(respExt.location, PRINT_POSTDATA, "correct location");
+ is(respExt.body, "initialRemoteType=extension", "correct POST body");
+
+ info("ENABLED -- EXTENSION -- extension-redirect URI load");
+ let respExtRedirect = await postFrom(
+ extOrigin + "redirect.html",
+ PRINT_POSTDATA
+ );
+ ok(E10SUtils.isWebRemoteType(respExtRedirect.remoteType), "process switch");
+ is(
+ respExtRedirect.location,
+ PRINT_POSTDATA + "?redirected",
+ "correct location"
+ );
+ is(
+ respExtRedirect.body,
+ "initialRemoteType=extension?redirected",
+ "correct POST body"
+ );
+
+ info("ENABLED -- EXTENSION -- 307-redirect URI load");
+ let respExt307 = await postFrom(
+ extOrigin + "dummy.html",
+ add307(PRINT_POSTDATA)
+ );
+ ok(E10SUtils.isWebRemoteType(respExt307.remoteType), "process switch");
+ is(respExt307.location, PRINT_POSTDATA, "correct location");
+ is(respExt307.body, "initialRemoteType=extension", "correct POST body");
+ });
+});
+
+async function sendMessage(ext, method, url) {
+ ext.sendMessage({ method, url });
+ await ext.awaitMessage("done");
+}
+
+// TODO: Currently no test framework for ftp://.
+add_task(async function test_protocol() {
+ // TODO: Processes should be switched due to navigation of different origins.
+ await testLoadAndRedirect("data:,foo", false, true);
+
+ // Redirecting to file:// is not allowed.
+ await testLoadAndRedirect(FILE_DUMMY, true, false);
+
+ await withExtensionDummy(async (extOrigin, extension) => {
+ await sendMessage(extension, "setRedirectUrl", DATA_URL);
+
+ let respExtRedirect = await postFrom(
+ extOrigin + "redirect.html",
+ PRINT_POSTDATA
+ );
+
+ ok(E10SUtils.isWebRemoteType(respExtRedirect.remoteType), "process switch");
+ is(respExtRedirect.location, DATA_URL, "correct location");
+ is(respExtRedirect.body, DATA_STRING, "correct POST body");
+ });
+});