diff options
Diffstat (limited to 'uriloader/exthandler/tests/mochitest/browser_protocol_ask_dialog_external.js')
-rw-r--r-- | uriloader/exthandler/tests/mochitest/browser_protocol_ask_dialog_external.js | 199 |
1 files changed, 199 insertions, 0 deletions
diff --git a/uriloader/exthandler/tests/mochitest/browser_protocol_ask_dialog_external.js b/uriloader/exthandler/tests/mochitest/browser_protocol_ask_dialog_external.js new file mode 100644 index 0000000000..591f1afbc5 --- /dev/null +++ b/uriloader/exthandler/tests/mochitest/browser_protocol_ask_dialog_external.js @@ -0,0 +1,199 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +let gHandlerService = Cc["@mozilla.org/uriloader/handler-service;1"].getService( + Ci.nsIHandlerService +); + +const TEST_PATH = getRootDirectory(gTestPath).replace( + "chrome://mochitests/content", + "https://example.com" +); + +/** + * 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( + "https://example.com" + ), + "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(); +}); |