Source code

Revision control

Copy as Markdown

Other Tools

Test Info:

/* Any copyright is dedicated to the Public Domain.
"use strict";
let gHandlerService = Cc["@mozilla.org/uriloader/handler-service;1"].getService(
Ci.nsIHandlerService
);
const TEST_PATH = getRootDirectory(gTestPath).replace(
);
/**
* Creates dummy protocol handler
*/
function initTestHandlers() {
let handlerInfoThatAsks =
HandlerServiceTestUtils.getBlankHandlerInfo("local-app-test");
let appHandler = Cc[
"@mozilla.org/uriloader/local-handler-app;1"
].createInstance(Ci.nsILocalHandlerApp);
// This is a dir and not executable, but that's enough for here.
appHandler.executable = Services.dirsvc.get("XCurProcD", Ci.nsIFile);
handlerInfoThatAsks.possibleApplicationHandlers.appendElement(appHandler);
handlerInfoThatAsks.preferredApplicationHandler = appHandler;
handlerInfoThatAsks.preferredAction = handlerInfoThatAsks.useHelperApp;
handlerInfoThatAsks.alwaysAskBeforeHandling = false;
gHandlerService.store(handlerInfoThatAsks);
let webHandlerInfo =
HandlerServiceTestUtils.getBlankHandlerInfo("web+somesite");
let webHandler = Cc[
"@mozilla.org/uriloader/web-handler-app;1"
].createInstance(Ci.nsIWebHandlerApp);
webHandler.name = "Somesite";
webHandler.uriTemplate = "https://example.com/handle_url?u=%s";
webHandlerInfo.possibleApplicationHandlers.appendElement(webHandler);
webHandlerInfo.preferredApplicationHandler = webHandler;
webHandlerInfo.preferredAction = webHandlerInfo.useHelperApp;
webHandlerInfo.alwaysAskBeforeHandling = false;
gHandlerService.store(webHandlerInfo);
registerCleanupFunction(() => {
gHandlerService.remove(webHandlerInfo);
gHandlerService.remove(handlerInfoThatAsks);
});
}
function makeCmdLineHelper(url) {
return Cu.createCommandLine(
["-url", url],
null,
Ci.nsICommandLine.STATE_REMOTE_EXPLICIT
);
}
add_setup(async function () {
await SpecialPowers.pushPrefEnv({
set: [["network.protocol-handler.prompt-from-external", true]],
});
initTestHandlers();
});
/**
* Check that if we get a direct request from another app / the OS to open a
* link, we always prompt, even if we think we know what the correct answer
* is. This is to avoid infinite loops in such situations where the OS and
* Firefox have conflicting ideas about the default handler, or where our
* checks with the OS don't work (Linux and/or Snap, at time of this comment).
*/
add_task(async function test_external_asks_anyway() {
let cmdLineHandler = Cc["@mozilla.org/browser/final-clh;1"].getService(
Ci.nsICommandLineHandler
);
let chooserDialogOpenPromise = waitForProtocolAppChooserDialog(
gBrowser,
true
);
let fakeCmdLine = makeCmdLineHelper("local-app-test:dummy");
cmdLineHandler.handle(fakeCmdLine);
let dialog = await chooserDialogOpenPromise;
ok(dialog, "Should have prompted.");
let dialogClosedPromise = waitForProtocolAppChooserDialog(
gBrowser.selectedBrowser,
false
);
let dialogEl = dialog._frame.contentDocument.querySelector("dialog");
dialogEl.cancelDialog();
await dialogClosedPromise;
// We will have opened a tab; close it.
BrowserTestUtils.removeTab(gBrowser.selectedTab);
});
/**
* Like the previous test, but avoid asking for web and extension handlers,
* as we can open those ourselves without looping.
*/
add_task(async function test_web_app_doesnt_ask() {
// Listen for a dialog open and fail the test if it does:
let dialogOpenListener = () => ok(false, "Shouldn't have opened a dialog!");
document.documentElement.addEventListener("dialogopen", dialogOpenListener);
registerCleanupFunction(() =>
document.documentElement.removeEventListener(
"dialogopen",
dialogOpenListener
)
);
// Set up a promise for a tab to open with the right URL:
const kURL = "web+somesite:dummy";
const kLoadedURL =
"https://example.com/handle_url?u=" + encodeURIComponent(kURL);
let tabPromise = BrowserTestUtils.waitForNewTab(gBrowser, kLoadedURL);
// Load the URL:
let cmdLineHandler = Cc["@mozilla.org/browser/final-clh;1"].getService(
Ci.nsICommandLineHandler
);
let fakeCmdLine = makeCmdLineHelper(kURL);
cmdLineHandler.handle(fakeCmdLine);
// Check that the tab loaded. If instead the dialog opened, the dialogopen handler
// will fail the test.
let tab = await tabPromise;
is(
tab.linkedBrowser.currentURI.spec,
kLoadedURL,
"Should have opened the right URL."
);
BrowserTestUtils.removeTab(tab);
// We do this both here and in cleanup so it's easy to add tasks to this test,
// and so we clean up correctly if the test aborts before we get here.
document.documentElement.removeEventListener(
"dialogopen",
dialogOpenListener
);
});
add_task(async function external_https_redirect_doesnt_ask() {
Services.perms.addFromPrincipal(
Services.scriptSecurityManager.createContentPrincipalFromOrigin(
),
"open-protocol-handler^local-app-test",
Services.perms.ALLOW_ACTION
);
// Listen for a dialog open and fail the test if it does:
let dialogOpenListener = () => ok(false, "Shouldn't have opened a dialog!");
document.documentElement.addEventListener("dialogopen", dialogOpenListener);
registerCleanupFunction(() => {
document.documentElement.removeEventListener(
"dialogopen",
dialogOpenListener
);
Services.perms.removeAll();
});
let initialTab = gBrowser.selectedTab;
gHandlerService.wrappedJSObject.mockProtocolHandler("local-app-test");
registerCleanupFunction(() =>
gHandlerService.wrappedJSObject.mockProtocolHandler()
);
// Set up a promise for an app to have launched with the right URI:
let loadPromise = TestUtils.topicObserved("mocked-protocol-handler");
// Load the URL:
const kURL = "local-app-test:redirect";
let cmdLineHandler = Cc["@mozilla.org/browser/final-clh;1"].getService(
Ci.nsICommandLineHandler
);
let fakeCmdLine = makeCmdLineHelper(
TEST_PATH + "redirect_helper.sjs?uri=" + encodeURIComponent(kURL)
);
cmdLineHandler.handle(fakeCmdLine);
// Check that the mock app was launched. If the dialog showed instead,
// the test will fail.
let [uri] = await loadPromise;
is(uri.spec, "local-app-test:redirect", "Should have seen correct URI.");
// We might have opened a blank tab, see bug 1718104 and friends.
if (gBrowser.selectedTab != initialTab) {
BrowserTestUtils.removeTab(gBrowser.selectedTab);
}
// We do this both here and in cleanup so it's easy to add tasks to this test,
// and so we clean up correctly if the test aborts before we get here.
document.documentElement.removeEventListener(
"dialogopen",
dialogOpenListener
);
gHandlerService.wrappedJSObject.mockProtocolHandler();
});