Source code

Revision control

Copy as Markdown

Other Tools

Test Info: Errors

/* Any copyright is dedicated to the Public Domain.
"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
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
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
async browser => {
info("Use window.open() with cross-origin document");
await testWindowOpen({
browser,
// eslint-disable-next-line @microsoft/sdl/no-insecure-url
isCrossOrigin: true,
willLoad: true,
});
info("Use window.open() with same-origin document");
await testWindowOpen({
browser,
// eslint-disable-next-line @microsoft/sdl/no-insecure-url
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
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();
});