Source code

Revision control

Copy as Markdown

Other Tools

Test Info:

/* Any copyright is dedicated to the Public Domain.
const { ComponentUtils } = ChromeUtils.importESModule(
"resource://gre/modules/ComponentUtils.sys.mjs"
);
const ROOT = getRootDirectory(gTestPath).replace(
);
const PAGE_URL = ROOT + "download_page.html";
const SJS_URL = ROOT + "download.sjs";
const HELPERAPP_DIALOG_CONTRACT_ID = "@mozilla.org/helperapplauncherdialog;1";
const HELPERAPP_DIALOG_CID = Components.ID(
Cc[HELPERAPP_DIALOG_CONTRACT_ID].number
);
const MOCK_HELPERAPP_DIALOG_CID = Components.ID(
"{2f372b6f-56c9-46d5-af0d-9f09bb69860c}"
);
let registrar = Components.manager.QueryInterface(Ci.nsIComponentRegistrar);
let curSaveResolve = null;
function HelperAppLauncherDialog() {}
HelperAppLauncherDialog.prototype = {
show(aLauncher) {
ok(false, "Shouldn't be showing the helper app dialog");
executeSoon(() => {
aLauncher.cancel(Cr.NS_ERROR_ABORT);
});
},
promptForSaveToFileAsync(aLauncher, aWindowContext) {
ok(true, "Shouldn't be showing the helper app dialog");
curSaveResolve(aWindowContext);
executeSoon(() => {
aLauncher.cancel(Cr.NS_ERROR_ABORT);
});
},
QueryInterface: ChromeUtils.generateQI(["nsIHelperAppLauncherDialog"]),
};
function promiseSave() {
return new Promise(resolve => {
curSaveResolve = resolve;
});
}
let mockHelperAppService;
add_setup(async function () {
// Replace the real helper app dialog with our own.
mockHelperAppService = ComponentUtils.generateSingletonFactory(
HelperAppLauncherDialog
);
registrar.registerFactory(
MOCK_HELPERAPP_DIALOG_CID,
"",
HELPERAPP_DIALOG_CONTRACT_ID,
mockHelperAppService
);
// Ensure we always prompt for these downloads.
const HandlerService = Cc[
"@mozilla.org/uriloader/handler-service;1"
].getService(Ci.nsIHandlerService);
const MIMEService = Cc["@mozilla.org/mime;1"].getService(Ci.nsIMIMEService);
const mimeInfo = MIMEService.getFromTypeAndExtension(
"application/octet-stream",
"bin"
);
mimeInfo.alwaysAskBeforeHandling = false;
mimeInfo.preferredAction = Ci.nsIHandlerInfo.saveToDisk;
HandlerService.store(mimeInfo);
registerCleanupFunction(() => {
HandlerService.remove(mimeInfo);
});
});
add_task(async function simple_navigation() {
// Tests that simple navigation gives us the right windowContext (that is,
// the window that we're using).
await BrowserTestUtils.withNewTab(
{ gBrowser, url: PAGE_URL },
async function (browser) {
let saveHappened = promiseSave();
await BrowserTestUtils.synthesizeMouseAtCenter(
"#regular_load",
{},
browser
);
let windowContext = await saveHappened;
is(windowContext, browser.ownerGlobal, "got the right windowContext");
}
);
});
// Given a browser pointing to download_page.html, clicks on the link that
// opens with target="_blank" (i.e. a new tab) and ensures that we
// automatically open and close that tab.
async function testNewTab(browser) {
let saveHappened = promiseSave();
let tabOpened = BrowserTestUtils.waitForEvent(
gBrowser.tabContainer,
"TabOpen"
).then(event => {
return [event.target, BrowserTestUtils.waitForTabClosing(event.target)];
});
await BrowserTestUtils.synthesizeMouseAtCenter("#target_blank", {}, browser);
let windowContext = await saveHappened;
is(windowContext, browser.ownerGlobal, "got the right windowContext");
let [tab, closingPromise] = await tabOpened;
await closingPromise;
is(tab.linkedBrowser, null, "tab was opened and closed");
}
add_task(async function target_blank() {
// Tests that a link with target=_blank opens a new tab and closes it,
// returning the window that we're using for navigation.
await BrowserTestUtils.withNewTab(
{ gBrowser, url: PAGE_URL },
async function (browser) {
await testNewTab(browser);
}
);
});
add_task(async function target_blank_no_opener() {
// Tests that a link with target=_blank and no opener opens a new tab
// and closes it, returning the window that we're using for navigation.
await BrowserTestUtils.withNewTab(
{ gBrowser, url: PAGE_URL },
async function (browser) {
let saveHappened = promiseSave();
let tabOpened = BrowserTestUtils.waitForEvent(
gBrowser.tabContainer,
"TabOpen"
).then(event => {
return [event.target, BrowserTestUtils.waitForTabClosing(event.target)];
});
await BrowserTestUtils.synthesizeMouseAtCenter(
"#target_blank_no_opener",
{},
browser
);
let windowContext = await saveHappened;
is(windowContext, browser.ownerGlobal, "got the right windowContext");
let [tab, closingPromise] = await tabOpened;
await closingPromise;
is(tab.linkedBrowser, null, "tab was opened and closed");
}
);
});
add_task(async function open_in_new_tab_no_opener() {
// Tests that a link with target=_blank and no opener opens a new tab
// and closes it, returning the window that we're using for navigation.
await BrowserTestUtils.withNewTab(
{ gBrowser, url: PAGE_URL },
async function (browser) {
let saveHappened = promiseSave();
let tabOpened = BrowserTestUtils.waitForEvent(
gBrowser.tabContainer,
"TabOpen"
).then(event => {
return [event.target, BrowserTestUtils.waitForTabClosing(event.target)];
});
await BrowserTestUtils.synthesizeMouseAtCenter(
"#open_in_new_tab_no_opener",
{},
browser
);
let windowContext = await saveHappened;
is(windowContext, browser.ownerGlobal, "got the right windowContext");
let [tab, closingPromise] = await tabOpened;
await closingPromise;
is(tab.linkedBrowser, null, "tab was opened and closed");
}
);
});
add_task(async function new_window() {
// Tests that a link that forces us to open a new window (by specifying a
// width and a height in window.open) opens a new window for the load,
// realizes that we need to close that window and returns the *original*
// window as the window context.
await BrowserTestUtils.withNewTab(
{ gBrowser, url: PAGE_URL },
async function (browser) {
let saveHappened = promiseSave();
let windowOpened = BrowserTestUtils.waitForNewWindow();
await BrowserTestUtils.synthesizeMouseAtCenter(
"#new_window",
{},
browser
);
let win = await windowOpened;
// Now allow request to complete:
fetch(SJS_URL + "?finish");
let windowContext = await saveHappened;
is(windowContext, browser.ownerGlobal, "got the right windowContext");
// The window should close on its own. If not, this test will time out.
await BrowserTestUtils.domWindowClosed(win);
ok(win.closed, "window was opened and closed");
is(
await fetch(SJS_URL + "?reset").then(r => r.text()),
"OK",
"Test reseted"
);
}
);
});
add_task(async function new_window_no_opener() {
// Tests that a link that forces us to open a new window (by specifying a
// width and a height in window.open) opens a new window for the load,
// realizes that we need to close that window and returns the *original*
// window as the window context.
await BrowserTestUtils.withNewTab(
{ gBrowser, url: PAGE_URL },
async function (browser) {
let saveHappened = promiseSave();
let windowOpened = BrowserTestUtils.waitForNewWindow();
await BrowserTestUtils.synthesizeMouseAtCenter(
"#new_window_no_opener",
{},
browser
);
let win = await windowOpened;
// Now allow request to complete:
fetch(SJS_URL + "?finish");
await saveHappened;
// The window should close on its own. If not, this test will time out.
await BrowserTestUtils.domWindowClosed(win);
ok(win.closed, "window was opened and closed");
is(
await fetch(SJS_URL + "?reset").then(r => r.text()),
"OK",
"Test reseted"
);
}
);
});
add_task(async function nested_window_opens() {
// Tests that the window auto-closing feature works if the download is
// initiated by a window that, itself, has an opener (see bug 1373109).
await BrowserTestUtils.withNewTab(
{ gBrowser, url: PAGE_URL },
async function (outerBrowser) {
let secondTabPromise = BrowserTestUtils.waitForNewTab(
gBrowser,
`${PAGE_URL}?newwin`,
true
);
BrowserTestUtils.synthesizeMouseAtCenter(
"#open_in_new_tab",
{},
outerBrowser
);
let secondTab = await secondTabPromise;
let nestedBrowser = secondTab.linkedBrowser;
await SpecialPowers.spawn(nestedBrowser, [], function () {
ok(content.opener, "this window has an opener");
});
await testNewTab(nestedBrowser);
isnot(
secondTab.linkedBrowser,
null,
"the page that triggered the download is still open"
);
BrowserTestUtils.removeTab(secondTab);
}
);
});
add_task(async function cleanup() {
// Unregister our factory from XPCOM and restore the original CID.
registrar.unregisterFactory(MOCK_HELPERAPP_DIALOG_CID, mockHelperAppService);
registrar.registerFactory(
HELPERAPP_DIALOG_CID,
"",
HELPERAPP_DIALOG_CONTRACT_ID,
null
);
});