319 lines
11 KiB
JavaScript
319 lines
11 KiB
JavaScript
/* Any copyright is dedicated to the Public Domain.
|
|
http://creativecommons.org/publicdomain/zero/1.0/ */
|
|
|
|
"use strict";
|
|
|
|
// Tag every new WindowGlobalParent with an expando indicating whether or not
|
|
// they were an initial document when they were created for the duration of this
|
|
// test.
|
|
function wasInitialDocumentObserver(subject) {
|
|
subject._test_wasInitialDocument = subject.isInitialDocument;
|
|
}
|
|
Services.obs.addObserver(wasInitialDocumentObserver, "window-global-created");
|
|
SimpleTest.registerCleanupFunction(function () {
|
|
Services.obs.removeObserver(
|
|
wasInitialDocumentObserver,
|
|
"window-global-created"
|
|
);
|
|
});
|
|
|
|
add_task(async function new_about_blank_tab() {
|
|
await BrowserTestUtils.withNewTab("about:blank", async browser => {
|
|
is(
|
|
browser.browsingContext.currentWindowGlobal.isInitialDocument,
|
|
false,
|
|
"After loading an actual, final about:blank in the tab, the field is false"
|
|
);
|
|
});
|
|
});
|
|
|
|
add_task(async function iframe_initial_about_blank() {
|
|
await BrowserTestUtils.withNewTab(
|
|
// eslint-disable-next-line @microsoft/sdl/no-insecure-url
|
|
"http://example.com/document-builder.sjs?html=com",
|
|
async browser => {
|
|
info("Create an iframe without any explicit location");
|
|
await SpecialPowers.spawn(browser, [], async () => {
|
|
const iframe = content.document.createElement("iframe");
|
|
// Add the iframe to the DOM tree in order to be able to have its browsingContext
|
|
content.document.body.appendChild(iframe);
|
|
const { browsingContext } = iframe;
|
|
|
|
is(
|
|
iframe.contentDocument.isInitialDocument,
|
|
true,
|
|
"The field is true on just-created iframes"
|
|
);
|
|
let beforeLoadPromise = SpecialPowers.spawnChrome(
|
|
[browsingContext],
|
|
bc => [
|
|
bc.currentWindowGlobal.isInitialDocument,
|
|
bc.currentWindowGlobal._test_wasInitialDocument,
|
|
]
|
|
);
|
|
|
|
await new Promise(resolve => {
|
|
iframe.addEventListener("load", resolve, { once: true });
|
|
});
|
|
is(
|
|
iframe.contentDocument.isInitialDocument,
|
|
false,
|
|
"The field is false after having loaded the final about:blank document"
|
|
);
|
|
let afterLoadPromise = SpecialPowers.spawnChrome(
|
|
[browsingContext],
|
|
bc => [
|
|
bc.currentWindowGlobal.isInitialDocument,
|
|
bc.currentWindowGlobal._test_wasInitialDocument,
|
|
]
|
|
);
|
|
|
|
// Wait to await the parent process promises, so we can't miss the "load" event.
|
|
let [beforeIsInitial, beforeWasInitial] = await beforeLoadPromise;
|
|
is(beforeIsInitial, true, "before load is initial in parent");
|
|
is(beforeWasInitial, true, "before load was initial in parent");
|
|
let [afterIsInitial, afterWasInitial] = await afterLoadPromise;
|
|
is(afterIsInitial, false, "after load is not initial in parent");
|
|
is(afterWasInitial, true, "after load was initial in parent");
|
|
iframe.remove();
|
|
});
|
|
|
|
info("Create an iframe with a cross origin location");
|
|
const iframeBC = await SpecialPowers.spawn(browser, [], async () => {
|
|
const iframe = content.document.createElement("iframe");
|
|
await new Promise(resolve => {
|
|
iframe.addEventListener("load", resolve, { once: true });
|
|
iframe.src =
|
|
// eslint-disable-next-line @microsoft/sdl/no-insecure-url
|
|
"http://example.org/document-builder.sjs?html=org-iframe";
|
|
content.document.body.appendChild(iframe);
|
|
});
|
|
|
|
return iframe.browsingContext;
|
|
});
|
|
|
|
is(
|
|
iframeBC.currentWindowGlobal.isInitialDocument,
|
|
false,
|
|
"The field is true after having loaded the final document"
|
|
);
|
|
}
|
|
);
|
|
});
|
|
|
|
add_task(async function window_open() {
|
|
async function testWindowOpen({ browser, args, isCrossOrigin, willLoad }) {
|
|
info(`Open popup with ${JSON.stringify(args)}`);
|
|
const onNewTab = BrowserTestUtils.waitForNewTab(
|
|
gBrowser,
|
|
args[0] || "about:blank"
|
|
);
|
|
await SpecialPowers.spawn(
|
|
browser,
|
|
[args, isCrossOrigin, willLoad],
|
|
async (args, crossOrigin, willLoad) => {
|
|
const win = content.window.open(...args);
|
|
is(
|
|
win.document.isInitialDocument,
|
|
true,
|
|
"The field is true right after calling window.open()"
|
|
);
|
|
let beforeLoadPromise = SpecialPowers.spawnChrome(
|
|
[win.browsingContext],
|
|
bc => [
|
|
bc.currentWindowGlobal.isInitialDocument,
|
|
bc.currentWindowGlobal._test_wasInitialDocument,
|
|
]
|
|
);
|
|
|
|
// In cross origin, it is harder to watch for new document load, and if
|
|
// no argument is passed no load will happen.
|
|
if (!crossOrigin && willLoad) {
|
|
await new Promise(r =>
|
|
win.addEventListener("load", r, { once: true })
|
|
);
|
|
is(
|
|
win.document.isInitialDocument,
|
|
false,
|
|
"The field becomes false right after the popup document is loaded"
|
|
);
|
|
}
|
|
|
|
// Perform the await after the load to avoid missing it.
|
|
let [beforeIsInitial, beforeWasInitial] = await beforeLoadPromise;
|
|
is(beforeIsInitial, true, "before load is initial in parent");
|
|
is(beforeWasInitial, true, "before load was initial in parent");
|
|
}
|
|
);
|
|
const newTab = await onNewTab;
|
|
const windowGlobal =
|
|
newTab.linkedBrowser.browsingContext.currentWindowGlobal;
|
|
if (willLoad) {
|
|
is(
|
|
windowGlobal.isInitialDocument,
|
|
false,
|
|
"The field is false in the parent process after having loaded the final document"
|
|
);
|
|
} else {
|
|
is(
|
|
windowGlobal.isInitialDocument,
|
|
true,
|
|
"The field remains true in the parent process as nothing will be loaded"
|
|
);
|
|
}
|
|
BrowserTestUtils.removeTab(newTab);
|
|
}
|
|
|
|
await BrowserTestUtils.withNewTab(
|
|
// eslint-disable-next-line @microsoft/sdl/no-insecure-url
|
|
"http://example.com/document-builder.sjs?html=com",
|
|
async browser => {
|
|
info("Use window.open() with cross-origin document");
|
|
await testWindowOpen({
|
|
browser,
|
|
// eslint-disable-next-line @microsoft/sdl/no-insecure-url
|
|
args: ["http://example.org/document-builder.sjs?html=org-popup"],
|
|
isCrossOrigin: true,
|
|
willLoad: true,
|
|
});
|
|
|
|
info("Use window.open() with same-origin document");
|
|
await testWindowOpen({
|
|
browser,
|
|
// eslint-disable-next-line @microsoft/sdl/no-insecure-url
|
|
args: ["http://example.com/document-builder.sjs?html=com-popup"],
|
|
isCrossOrigin: false,
|
|
willLoad: true,
|
|
});
|
|
|
|
info("Use window.open() with final about:blank document");
|
|
await testWindowOpen({
|
|
browser,
|
|
args: ["about:blank"],
|
|
isCrossOrigin: false,
|
|
willLoad: true,
|
|
});
|
|
|
|
info("Use window.open() with no argument");
|
|
await testWindowOpen({
|
|
browser,
|
|
args: [],
|
|
isCrossOrigin: false,
|
|
willLoad: false,
|
|
});
|
|
}
|
|
);
|
|
});
|
|
|
|
add_task(async function document_open() {
|
|
await BrowserTestUtils.withNewTab(
|
|
// eslint-disable-next-line @microsoft/sdl/no-insecure-url
|
|
"http://example.com/document-builder.sjs?html=com",
|
|
async browser => {
|
|
is(browser.browsingContext.currentWindowGlobal.isInitialDocument, false);
|
|
await SpecialPowers.spawn(browser, [], async () => {
|
|
const iframe = content.document.createElement("iframe");
|
|
// Add the iframe to the DOM tree in order to be able to have its browsingContext
|
|
content.document.body.appendChild(iframe);
|
|
const { browsingContext } = iframe;
|
|
|
|
// Check the state before the call in both parent and content.
|
|
is(
|
|
iframe.contentDocument.isInitialDocument,
|
|
true,
|
|
"Is an initial document before calling document.open"
|
|
);
|
|
let beforeOpenParentPromise = SpecialPowers.spawnChrome(
|
|
[browsingContext],
|
|
bc => [
|
|
bc.currentWindowGlobal.isInitialDocument,
|
|
bc.currentWindowGlobal._test_wasInitialDocument,
|
|
bc.currentWindowGlobal.innerWindowId,
|
|
]
|
|
);
|
|
|
|
// Run the `document.open` call with reduced permissions.
|
|
iframe.contentWindow.eval(`
|
|
document.open();
|
|
document.write("new document");
|
|
document.close();
|
|
`);
|
|
|
|
is(
|
|
iframe.contentDocument.isInitialDocument,
|
|
false,
|
|
"Is no longer an initial document after calling document.open"
|
|
);
|
|
let [afterIsInitial, afterWasInitial, afterID] =
|
|
await SpecialPowers.spawnChrome([browsingContext], bc => [
|
|
bc.currentWindowGlobal.isInitialDocument,
|
|
bc.currentWindowGlobal._test_wasInitialDocument,
|
|
bc.currentWindowGlobal.innerWindowId,
|
|
]);
|
|
let [beforeIsInitial, beforeWasInitial, beforeID] =
|
|
await beforeOpenParentPromise;
|
|
is(beforeIsInitial, true, "Should be initial before in the parent");
|
|
is(beforeWasInitial, true, "Was initial before in the parent");
|
|
is(afterIsInitial, false, "Should not be initial after in the parent");
|
|
is(afterWasInitial, true, "Was initial after in the parent");
|
|
is(beforeID, afterID, "Should be the same WindowGlobalParent");
|
|
});
|
|
}
|
|
);
|
|
});
|
|
|
|
add_task(async function windowless_browser() {
|
|
info("Create a Windowless browser");
|
|
const browser = Services.appShell.createWindowlessBrowser(false);
|
|
const { browsingContext } = browser;
|
|
is(
|
|
browsingContext.currentWindowGlobal.isInitialDocument,
|
|
true,
|
|
"The field is true for a freshly created WindowlessBrowser"
|
|
);
|
|
is(
|
|
browser.currentURI.spec,
|
|
"about:blank",
|
|
"The location is immediately set to about:blank"
|
|
);
|
|
|
|
const principal = Services.scriptSecurityManager.getSystemPrincipal();
|
|
browser.docShell.createAboutBlankDocumentViewer(principal, principal);
|
|
is(
|
|
browsingContext.currentWindowGlobal.isInitialDocument,
|
|
false,
|
|
"The field becomes false when creating an artificial blank document"
|
|
);
|
|
|
|
info("Load a final about:blank document in it");
|
|
const onLocationChange = new Promise(resolve => {
|
|
let wpl = {
|
|
QueryInterface: ChromeUtils.generateQI([
|
|
"nsIWebProgressListener",
|
|
"nsISupportsWeakReference",
|
|
]),
|
|
onLocationChange() {
|
|
browsingContext.webProgress.removeProgressListener(
|
|
wpl,
|
|
Ci.nsIWebProgress.NOTIFY_ALL
|
|
);
|
|
resolve();
|
|
},
|
|
};
|
|
browsingContext.webProgress.addProgressListener(
|
|
wpl,
|
|
Ci.nsIWebProgress.NOTIFY_ALL
|
|
);
|
|
});
|
|
browser.loadURI(Services.io.newURI("about:blank"), {
|
|
triggeringPrincipal: principal,
|
|
});
|
|
info("Wait for the location change");
|
|
await onLocationChange;
|
|
is(
|
|
browsingContext.currentWindowGlobal.isInitialDocument,
|
|
false,
|
|
"The field is false after the location change event"
|
|
);
|
|
browser.close();
|
|
});
|