mirror of
				https://github.com/mozilla/gecko-dev.git
				synced 2025-11-04 02:09:05 +02:00 
			
		
		
		
	
		
			
				
	
	
		
			279 lines
		
	
	
	
		
			8.4 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			279 lines
		
	
	
	
		
			8.4 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
/* 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 () => {
 | 
						|
        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 => {
 | 
						|
          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 }) {
 | 
						|
        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.startLoadingURIString(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");
 | 
						|
  });
 | 
						|
});
 |