forked from mirrors/gecko-dev
		
	This should make a bit clearer that it is only starting the load, not waiting for its completion. Differential Revision: https://phabricator.services.mozilla.com/D188213
		
			
				
	
	
		
			410 lines
		
	
	
	
		
			11 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			410 lines
		
	
	
	
		
			11 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
"use strict";
 | 
						|
 | 
						|
const COOP_PREF = "browser.tabs.remote.useCrossOriginOpenerPolicy";
 | 
						|
 | 
						|
async function setPref() {
 | 
						|
  await SpecialPowers.pushPrefEnv({
 | 
						|
    set: [[COOP_PREF, true]],
 | 
						|
  });
 | 
						|
}
 | 
						|
 | 
						|
async function unsetPref() {
 | 
						|
  await SpecialPowers.pushPrefEnv({
 | 
						|
    set: [[COOP_PREF, false]],
 | 
						|
  });
 | 
						|
}
 | 
						|
 | 
						|
function httpURL(filename, host = "https://example.com") {
 | 
						|
  let root = getRootDirectory(gTestPath).replace(
 | 
						|
    "chrome://mochitests/content",
 | 
						|
    host
 | 
						|
  );
 | 
						|
  return root + filename;
 | 
						|
}
 | 
						|
 | 
						|
async function performLoad(browser, opts, action) {
 | 
						|
  let loadedPromise = BrowserTestUtils.browserStopped(
 | 
						|
    browser,
 | 
						|
    opts.url,
 | 
						|
    opts.maybeErrorPage
 | 
						|
  );
 | 
						|
  await action();
 | 
						|
  await loadedPromise;
 | 
						|
}
 | 
						|
 | 
						|
async function test_coop(
 | 
						|
  start,
 | 
						|
  target,
 | 
						|
  expectedProcessSwitch,
 | 
						|
  startRemoteTypeCheck,
 | 
						|
  targetRemoteTypeCheck
 | 
						|
) {
 | 
						|
  return BrowserTestUtils.withNewTab(
 | 
						|
    {
 | 
						|
      gBrowser,
 | 
						|
      url: start,
 | 
						|
      waitForStateStop: true,
 | 
						|
    },
 | 
						|
    async function (_browser) {
 | 
						|
      info(`test_coop: Test tab ready: ${start}`);
 | 
						|
 | 
						|
      let browser = gBrowser.selectedBrowser;
 | 
						|
      let firstRemoteType = browser.remoteType;
 | 
						|
      let firstBC = browser.browsingContext;
 | 
						|
 | 
						|
      info(`firstBC: ${firstBC.id} remoteType: ${firstRemoteType}`);
 | 
						|
 | 
						|
      if (startRemoteTypeCheck) {
 | 
						|
        startRemoteTypeCheck(firstRemoteType);
 | 
						|
      }
 | 
						|
 | 
						|
      await performLoad(
 | 
						|
        browser,
 | 
						|
        {
 | 
						|
          url: target,
 | 
						|
          maybeErrorPage: false,
 | 
						|
        },
 | 
						|
        async () => BrowserTestUtils.startLoadingURIString(browser, target)
 | 
						|
      );
 | 
						|
 | 
						|
      info(`Navigated to: ${target}`);
 | 
						|
      browser = gBrowser.selectedBrowser;
 | 
						|
      let secondRemoteType = browser.remoteType;
 | 
						|
      let secondBC = browser.browsingContext;
 | 
						|
 | 
						|
      info(`secondBC: ${secondBC.id} remoteType: ${secondRemoteType}`);
 | 
						|
      if (targetRemoteTypeCheck) {
 | 
						|
        targetRemoteTypeCheck(secondRemoteType);
 | 
						|
      }
 | 
						|
      if (expectedProcessSwitch) {
 | 
						|
        Assert.notEqual(firstBC.id, secondBC.id, `from: ${start} to ${target}`);
 | 
						|
      } else {
 | 
						|
        Assert.equal(firstBC.id, secondBC.id, `from: ${start} to ${target}`);
 | 
						|
      }
 | 
						|
    }
 | 
						|
  );
 | 
						|
}
 | 
						|
 | 
						|
function waitForDownloadWindow() {
 | 
						|
  return new Promise(resolve => {
 | 
						|
    var listener = {
 | 
						|
      onOpenWindow: aXULWindow => {
 | 
						|
        info("Download window shown...");
 | 
						|
        Services.wm.removeListener(listener);
 | 
						|
 | 
						|
        function downloadOnLoad() {
 | 
						|
          domwindow.removeEventListener("load", downloadOnLoad, true);
 | 
						|
 | 
						|
          is(
 | 
						|
            domwindow.document.location.href,
 | 
						|
            "chrome://mozapps/content/downloads/unknownContentType.xhtml",
 | 
						|
            "Download page appeared"
 | 
						|
          );
 | 
						|
          resolve(domwindow);
 | 
						|
        }
 | 
						|
 | 
						|
        var domwindow = aXULWindow.docShell.domWindow;
 | 
						|
        domwindow.addEventListener("load", downloadOnLoad, true);
 | 
						|
      },
 | 
						|
      onCloseWindow: aXULWindow => {},
 | 
						|
    };
 | 
						|
 | 
						|
    Services.wm.addListener(listener);
 | 
						|
  });
 | 
						|
}
 | 
						|
 | 
						|
async function waitForDownloadUI() {
 | 
						|
  return BrowserTestUtils.waitForEvent(DownloadsPanel.panel, "popupshown");
 | 
						|
}
 | 
						|
 | 
						|
async function cleanupDownloads(downloadList) {
 | 
						|
  info("cleaning up downloads");
 | 
						|
  let [download] = await downloadList.getAll();
 | 
						|
  await downloadList.remove(download);
 | 
						|
  await download.finalize(true);
 | 
						|
 | 
						|
  try {
 | 
						|
    if (Services.appinfo.OS === "WINNT") {
 | 
						|
      // We need to make the file writable to delete it on Windows.
 | 
						|
      await IOUtils.setPermissions(download.target.path, 0o600);
 | 
						|
    }
 | 
						|
    await IOUtils.remove(download.target.path);
 | 
						|
  } catch (error) {
 | 
						|
    info("The file " + download.target.path + " is not removed, " + error);
 | 
						|
  }
 | 
						|
 | 
						|
  if (DownloadsPanel.panel.state !== "closed") {
 | 
						|
    let hiddenPromise = BrowserTestUtils.waitForEvent(
 | 
						|
      DownloadsPanel.panel,
 | 
						|
      "popuphidden"
 | 
						|
    );
 | 
						|
    DownloadsPanel.hidePanel();
 | 
						|
    await hiddenPromise;
 | 
						|
  }
 | 
						|
  is(
 | 
						|
    DownloadsPanel.panel.state,
 | 
						|
    "closed",
 | 
						|
    "Check that the download panel is closed"
 | 
						|
  );
 | 
						|
}
 | 
						|
 | 
						|
async function test_download_from(initCoop, downloadCoop) {
 | 
						|
  return BrowserTestUtils.withNewTab("about:blank", async function (_browser) {
 | 
						|
    info(`test_download: Test tab ready`);
 | 
						|
 | 
						|
    let start = httpURL(
 | 
						|
      "coop_header.sjs?downloadPage&coop=" + initCoop,
 | 
						|
      "https://example.com"
 | 
						|
    );
 | 
						|
    await performLoad(
 | 
						|
      _browser,
 | 
						|
      {
 | 
						|
        url: start,
 | 
						|
        maybeErrorPage: false,
 | 
						|
      },
 | 
						|
      async () => {
 | 
						|
        info(`test_download: Loading download page ${start}`);
 | 
						|
        return BrowserTestUtils.startLoadingURIString(_browser, start);
 | 
						|
      }
 | 
						|
    );
 | 
						|
 | 
						|
    info(`test_download: Download page ready ${start}`);
 | 
						|
    info(`Downloading ${downloadCoop}`);
 | 
						|
 | 
						|
    let expectDialog = Services.prefs.getBoolPref(
 | 
						|
      "browser.download.always_ask_before_handling_new_types",
 | 
						|
      false
 | 
						|
    );
 | 
						|
    let resultPromise = expectDialog
 | 
						|
      ? waitForDownloadWindow()
 | 
						|
      : waitForDownloadUI();
 | 
						|
    let browser = gBrowser.selectedBrowser;
 | 
						|
    SpecialPowers.spawn(browser, [downloadCoop], downloadCoop => {
 | 
						|
      content.document.getElementById(downloadCoop).click();
 | 
						|
    });
 | 
						|
 | 
						|
    // if the download page doesn't appear, the promise leads a timeout.
 | 
						|
    if (expectDialog) {
 | 
						|
      let win = await resultPromise;
 | 
						|
      await BrowserTestUtils.closeWindow(win);
 | 
						|
    } else {
 | 
						|
      // verify link target will get automatically downloaded
 | 
						|
      await resultPromise;
 | 
						|
      let downloadList = await Downloads.getList(Downloads.PUBLIC);
 | 
						|
      is((await downloadList.getAll()).length, 1, "Target was downloaded");
 | 
						|
      await cleanupDownloads(downloadList);
 | 
						|
      is((await downloadList.getAll()).length, 0, "Downloads were cleaned up");
 | 
						|
    }
 | 
						|
  });
 | 
						|
}
 | 
						|
 | 
						|
// Check that multiple navigations of the same tab will only switch processes
 | 
						|
// when it's expected.
 | 
						|
add_task(async function test_multiple_nav_process_switches() {
 | 
						|
  await setPref();
 | 
						|
  await BrowserTestUtils.withNewTab(
 | 
						|
    {
 | 
						|
      gBrowser,
 | 
						|
      url: httpURL("coop_header.sjs", "https://example.org"),
 | 
						|
      waitForStateStop: true,
 | 
						|
    },
 | 
						|
    async function (browser) {
 | 
						|
      let prevBC = browser.browsingContext;
 | 
						|
 | 
						|
      let target = httpURL("coop_header.sjs?.", "https://example.org");
 | 
						|
      await performLoad(
 | 
						|
        browser,
 | 
						|
        {
 | 
						|
          url: target,
 | 
						|
          maybeErrorPage: false,
 | 
						|
        },
 | 
						|
        async () => BrowserTestUtils.startLoadingURIString(browser, target)
 | 
						|
      );
 | 
						|
 | 
						|
      Assert.equal(prevBC, browser.browsingContext);
 | 
						|
      prevBC = browser.browsingContext;
 | 
						|
 | 
						|
      target = httpURL(
 | 
						|
        "coop_header.sjs?coop=same-origin",
 | 
						|
        "https://example.org"
 | 
						|
      );
 | 
						|
      await performLoad(
 | 
						|
        browser,
 | 
						|
        {
 | 
						|
          url: target,
 | 
						|
          maybeErrorPage: false,
 | 
						|
        },
 | 
						|
        async () => BrowserTestUtils.startLoadingURIString(browser, target)
 | 
						|
      );
 | 
						|
 | 
						|
      Assert.notEqual(prevBC, browser.browsingContext);
 | 
						|
      prevBC = browser.browsingContext;
 | 
						|
 | 
						|
      target = httpURL(
 | 
						|
        "coop_header.sjs?coop=same-origin",
 | 
						|
        "https://example.com"
 | 
						|
      );
 | 
						|
      await performLoad(
 | 
						|
        browser,
 | 
						|
        {
 | 
						|
          url: target,
 | 
						|
          maybeErrorPage: false,
 | 
						|
        },
 | 
						|
        async () => BrowserTestUtils.startLoadingURIString(browser, target)
 | 
						|
      );
 | 
						|
 | 
						|
      Assert.notEqual(prevBC, browser.browsingContext);
 | 
						|
      prevBC = browser.browsingContext;
 | 
						|
 | 
						|
      target = httpURL(
 | 
						|
        "coop_header.sjs?coop=same-origin&index=4",
 | 
						|
        "https://example.com"
 | 
						|
      );
 | 
						|
      await performLoad(
 | 
						|
        browser,
 | 
						|
        {
 | 
						|
          url: target,
 | 
						|
          maybeErrorPage: false,
 | 
						|
        },
 | 
						|
        async () => BrowserTestUtils.startLoadingURIString(browser, target)
 | 
						|
      );
 | 
						|
 | 
						|
      Assert.equal(prevBC, browser.browsingContext);
 | 
						|
    }
 | 
						|
  );
 | 
						|
});
 | 
						|
 | 
						|
add_task(async function test_disabled() {
 | 
						|
  await unsetPref();
 | 
						|
  await test_coop(
 | 
						|
    httpURL("coop_header.sjs", "https://example.com"),
 | 
						|
    httpURL("coop_header.sjs", "https://example.com"),
 | 
						|
    false
 | 
						|
  );
 | 
						|
  await test_coop(
 | 
						|
    httpURL("coop_header.sjs?coop=same-origin", "http://example.com"),
 | 
						|
    httpURL("coop_header.sjs", "http://example.com"),
 | 
						|
    false
 | 
						|
  );
 | 
						|
  await test_coop(
 | 
						|
    httpURL("coop_header.sjs", "http://example.com"),
 | 
						|
    httpURL("coop_header.sjs?coop=same-origin", "http://example.com"),
 | 
						|
    false
 | 
						|
  );
 | 
						|
});
 | 
						|
 | 
						|
add_task(async function test_enabled() {
 | 
						|
  await setPref();
 | 
						|
 | 
						|
  function checkIsCoopRemoteType(remoteType) {
 | 
						|
    Assert.ok(
 | 
						|
      remoteType.startsWith(E10SUtils.WEB_REMOTE_COOP_COEP_TYPE_PREFIX),
 | 
						|
      `${remoteType} expected to be coop`
 | 
						|
    );
 | 
						|
  }
 | 
						|
 | 
						|
  function checkIsNotCoopRemoteType(remoteType) {
 | 
						|
    if (gFissionBrowser) {
 | 
						|
      Assert.ok(
 | 
						|
        remoteType.startsWith("webIsolated="),
 | 
						|
        `${remoteType} expected to start with webIsolated=`
 | 
						|
      );
 | 
						|
    } else {
 | 
						|
      Assert.equal(
 | 
						|
        remoteType,
 | 
						|
        E10SUtils.WEB_REMOTE_TYPE,
 | 
						|
        `${remoteType} expected to be web`
 | 
						|
      );
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  await test_coop(
 | 
						|
    httpURL("coop_header.sjs", "https://example.com"),
 | 
						|
    httpURL("coop_header.sjs", "https://example.com"),
 | 
						|
    false,
 | 
						|
    checkIsNotCoopRemoteType,
 | 
						|
    checkIsNotCoopRemoteType
 | 
						|
  );
 | 
						|
  await test_coop(
 | 
						|
    httpURL("coop_header.sjs", "https://example.com"),
 | 
						|
    httpURL("coop_header.sjs?coop=same-origin", "https://example.org"),
 | 
						|
    true,
 | 
						|
    checkIsNotCoopRemoteType,
 | 
						|
    checkIsNotCoopRemoteType
 | 
						|
  );
 | 
						|
  await test_coop(
 | 
						|
    httpURL("coop_header.sjs?coop=same-origin&index=1", "https://example.com"),
 | 
						|
    httpURL("coop_header.sjs?coop=same-origin&index=1", "https://example.org"),
 | 
						|
    true,
 | 
						|
    checkIsNotCoopRemoteType,
 | 
						|
    checkIsNotCoopRemoteType
 | 
						|
  );
 | 
						|
  await test_coop(
 | 
						|
    httpURL("coop_header.sjs", "https://example.com"),
 | 
						|
    httpURL(
 | 
						|
      "coop_header.sjs?coop=same-origin&coep=require-corp",
 | 
						|
      "https://example.com"
 | 
						|
    ),
 | 
						|
    true,
 | 
						|
    checkIsNotCoopRemoteType,
 | 
						|
    checkIsCoopRemoteType
 | 
						|
  );
 | 
						|
  await test_coop(
 | 
						|
    httpURL(
 | 
						|
      "coop_header.sjs?coop=same-origin&coep=require-corp&index=2",
 | 
						|
      "https://example.com"
 | 
						|
    ),
 | 
						|
    httpURL(
 | 
						|
      "coop_header.sjs?coop=same-origin&coep=require-corp&index=3",
 | 
						|
      "https://example.com"
 | 
						|
    ),
 | 
						|
    false,
 | 
						|
    checkIsCoopRemoteType,
 | 
						|
    checkIsCoopRemoteType
 | 
						|
  );
 | 
						|
  await test_coop(
 | 
						|
    httpURL(
 | 
						|
      "coop_header.sjs?coop=same-origin&coep=require-corp&index=4",
 | 
						|
      "https://example.com"
 | 
						|
    ),
 | 
						|
    httpURL("coop_header.sjs", "https://example.com"),
 | 
						|
    true,
 | 
						|
    checkIsCoopRemoteType,
 | 
						|
    checkIsNotCoopRemoteType
 | 
						|
  );
 | 
						|
  await test_coop(
 | 
						|
    httpURL(
 | 
						|
      "coop_header.sjs?coop=same-origin&coep=require-corp&index=5",
 | 
						|
      "https://example.com"
 | 
						|
    ),
 | 
						|
    httpURL(
 | 
						|
      "coop_header.sjs?coop=same-origin&coep=require-corp&index=6",
 | 
						|
      "https://example.org"
 | 
						|
    ),
 | 
						|
    true,
 | 
						|
    checkIsCoopRemoteType,
 | 
						|
    checkIsCoopRemoteType
 | 
						|
  );
 | 
						|
});
 | 
						|
 | 
						|
add_task(async function test_download() {
 | 
						|
  requestLongerTimeout(4);
 | 
						|
  await setPref();
 | 
						|
 | 
						|
  let initCoopArray = ["", "same-origin"];
 | 
						|
 | 
						|
  let downloadCoopArray = [
 | 
						|
    "no-coop",
 | 
						|
    "same-origin",
 | 
						|
    "same-origin-allow-popups",
 | 
						|
  ];
 | 
						|
 | 
						|
  // If the coop mismatch between current page and download link, clicking the
 | 
						|
  // download link will make the page empty and popup the download window. That
 | 
						|
  // forces us to reload the page every time.
 | 
						|
  for (var initCoop of initCoopArray) {
 | 
						|
    for (var downloadCoop of downloadCoopArray) {
 | 
						|
      await test_download_from(initCoop, downloadCoop);
 | 
						|
    }
 | 
						|
  }
 | 
						|
});
 |