Source code
Revision control
Copy as Markdown
Other Tools
Test Info:
/* Any copyright is dedicated to the Public Domain.
"use strict";
const { nsContentDispatchChooser } = ChromeUtils.importESModule(
"resource://gre/modules/ContentDispatchChooser.sys.mjs"
);
ChromeUtils.defineESModuleGetters(this, {
});
const HANDLER_NAME = "Test Webmail";
const URI_TEMPLATE =
"blank_webmail.html?to=%s";
const MAILTO = "mailto:test@example.com";
const EXPECTED_URL =
"blank_webmail.html?to=" +
encodeURIComponent(MAILTO);
function getMailtoInfoWithWebHandler() {
const protoSvc = Cc[
"@mozilla.org/uriloader/external-protocol-service;1"
].getService(Ci.nsIExternalProtocolService);
const info = protoSvc.getProtocolHandlerInfo("mailto");
// The shipped handler list seeds mailto with real web mailers (e.g. Gmail).
// The picker loads each web handler's favicon from its origin, which under
// test is a forbidden non-local connection that crashes the parent process,
// and also makes this test depend on the ambient (region/locale-specific)
// list. Drop the seeded handlers so only our local test handler remains.
const handlers = info.possibleApplicationHandlers;
for (let i = handlers.length - 1; i >= 0; i--) {
handlers.removeElementAt(i);
}
const webHandler = Cc[
"@mozilla.org/uriloader/web-handler-app;1"
].createInstance(Ci.nsIWebHandlerApp);
webHandler.name = HANDLER_NAME;
webHandler.uriTemplate = URI_TEMPLATE;
info.possibleApplicationHandlers.appendElement(webHandler);
// The picker is only shown when "always ask" is configured for mailto.
info.alwaysAskBeforeHandling = true;
return info;
}
function rowByName(win, name) {
return [...win.document.querySelectorAll("#items richlistitem")].find(
item => item.getAttribute("name") === name
);
}
function dialogButton(win, type) {
return win.document.querySelector("dialog").getButton(type);
}
add_setup(async function () {
// The picker is gated behind the "dialog" variable of the "mailto" Nimbus
// feature, so enroll to enable it for the duration of this test.
const nimbusCleanup = await NimbusTestUtils.enrollWithFeatureConfig({
featureId: "mailto",
value: { dialog: true },
});
registerCleanupFunction(async () => {
await nimbusCleanup();
});
});
// Selecting a web mailer and confirming with "Set as default" should open it in
// a new foreground tab with the mailto: URI substituted into the handler's
// template, and close the picker dialog.
add_task(async function test_picker_opens_webmailer_in_new_foreground_tab() {
const browser = gBrowser.selectedBrowser;
const principal = Services.scriptSecurityManager.createContentPrincipal(
{}
);
const mailtoInfo = getMailtoInfoWithWebHandler();
const chooser = new nsContentDispatchChooser();
// handleURI resolves only once the picker is dismissed, so don't await it
// until after we have interacted with the dialog.
const handlePromise = chooser.handleURI(
mailtoInfo,
Services.io.newURI(MAILTO),
principal,
browser.browsingContext,
false
);
const [dialogWin] = await TestUtils.topicObserved("subdialog-loaded");
await TestUtils.waitForCondition(
() => rowByName(dialogWin, HANDLER_NAME),
"Picker row for the configured web handler is rendered"
);
const row = rowByName(dialogWin, HANDLER_NAME);
Assert.ok(row, "Found the web mailer row in the picker");
const newTabPromise = BrowserTestUtils.waitForNewTab(
gBrowser,
EXPECTED_URL,
true
);
// Select the web mailer, then confirm with the "Set as default" button.
dialogWin.document.getElementById("items").selectedItem = row;
dialogButton(dialogWin, "accept").click();
const newTab = await newTabPromise;
await handlePromise;
Assert.equal(
gBrowser.selectedTab,
newTab,
"The new web mailer tab is selected (opened in the foreground)"
);
Assert.equal(
newTab.linkedBrowser.currentURI.spec,
EXPECTED_URL,
"The mailto: URI was substituted into the handler's URI template"
);
Assert.ok(
!browser.documentGlobal.gDialogBox?.isOpen,
"The picker dialog was closed after a selection"
);
BrowserTestUtils.removeTab(newTab);
});
// Clicking "Not now" should dismiss the picker without launching anything or
// opening a tab.
add_task(async function test_dismiss_picker_launches_nothing() {
const initialTabCount = gBrowser.tabs.length;
const browser = gBrowser.selectedBrowser;
const principal = Services.scriptSecurityManager.createContentPrincipal(
{}
);
const mailtoInfo = getMailtoInfoWithWebHandler();
const chooser = new nsContentDispatchChooser();
const handlePromise = chooser.handleURI(
mailtoInfo,
Services.io.newURI(MAILTO),
principal,
browser.browsingContext,
false
);
const [dialogWin] = await TestUtils.topicObserved("subdialog-loaded");
await TestUtils.waitForCondition(
() => dialogButton(dialogWin, "cancel"),
"The 'Not now' button is rendered"
);
dialogButton(dialogWin, "cancel").click();
await handlePromise;
Assert.equal(
gBrowser.tabs.length,
initialTabCount,
"No new tab is opened when the picker is dismissed"
);
Assert.ok(
!browser.documentGlobal.gDialogBox?.isOpen,
"The picker dialog was closed"
);
});