зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1700976 - do not prompt for externally-opened web- or extension-handled 'external' protocols, r=zombie
Differential Revision: https://phabricator.services.mozilla.com/D115478
This commit is contained in:
Родитель
fa827a1cbe
Коммит
2d2e51253d
|
@ -69,9 +69,6 @@ add_task(async function test_protocolHandler() {
|
|||
await SpecialPowers.pushPrefEnv({
|
||||
set: [
|
||||
["extensions.allowPrivateBrowsingByDefault", false],
|
||||
// Disabling the external protocol permission prompt. We don't need it
|
||||
// for this test.
|
||||
["security.external_protocol_requires_permission", false],
|
||||
],
|
||||
});
|
||||
let extensionData = {
|
||||
|
@ -101,6 +98,7 @@ add_task(async function test_protocolHandler() {
|
|||
files: {
|
||||
"foo.js": function() {
|
||||
browser.test.sendMessage("test-query", location.search);
|
||||
browser.tabs.getCurrent().then(tab => browser.test.sendMessage("test-tab", tab.id));
|
||||
},
|
||||
"foo.html": `<!DOCTYPE html>
|
||||
<html>
|
||||
|
@ -161,10 +159,62 @@ add_task(async function test_protocolHandler() {
|
|||
|
||||
let query = await extension.awaitMessage("test-query");
|
||||
is(query, "?val=ext%2Bfoo%3Atest", "test query ok");
|
||||
is(id, await extension.awaitMessage("test-tab"), "id should match opened tab");
|
||||
|
||||
extension.sendMessage("close", id);
|
||||
await extension.awaitMessage("closed");
|
||||
|
||||
// Test that handling a URL from the commandline works.
|
||||
chromeScript = SpecialPowers.loadChromeScript(() => {
|
||||
let cmdLineHandler = Cc["@mozilla.org/browser/final-clh;1"].getService(
|
||||
Ci.nsICommandLineHandler
|
||||
);
|
||||
let fakeCmdLine = {
|
||||
length: 1,
|
||||
_arg: "ext+foo:cmdline",
|
||||
|
||||
getArgument(index) {
|
||||
if (index == 0) {
|
||||
return this._arg;
|
||||
}
|
||||
throw Components.Exception("", Cr.NS_ERROR_INVALID_ARG);
|
||||
},
|
||||
|
||||
findFlag() {
|
||||
return -1;
|
||||
},
|
||||
|
||||
handleFlagWithParam() {
|
||||
if (this._argCount) {
|
||||
this._argCount = 0;
|
||||
return this._arg;
|
||||
}
|
||||
|
||||
return "";
|
||||
},
|
||||
|
||||
state: 2,
|
||||
|
||||
STATE_INITIAL_LAUNCH: 0,
|
||||
STATE_REMOTE_AUTO: 1,
|
||||
STATE_REMOTE_EXPLICIT: 2,
|
||||
|
||||
preventDefault: false,
|
||||
|
||||
resolveURI() {
|
||||
return Services.io.newURI(this._arg);
|
||||
},
|
||||
QueryInterface: ChromeUtils.generateQI(["nsICommandLine"]),
|
||||
};
|
||||
cmdLineHandler.handle(fakeCmdLine);
|
||||
});
|
||||
query = await extension.awaitMessage("test-query");
|
||||
is(query, "?val=ext%2Bfoo%3Acmdline", "cmdline query ok");
|
||||
id = await extension.awaitMessage("test-tab");
|
||||
extension.sendMessage("close", id);
|
||||
await extension.awaitMessage("closed");
|
||||
chromeScript.destroy();
|
||||
|
||||
// Test the protocol in a private window, watch for the
|
||||
// console error.
|
||||
consoleMonitor.start([{ message: /NS_ERROR_FILE_NOT_FOUND/ }]);
|
||||
|
|
|
@ -263,7 +263,15 @@ class nsContentDispatchChooser {
|
|||
|
||||
// Force showing the dialog for links passed from outside the application.
|
||||
// This avoids infinite loops, see bug 1678255, bug 1667468, etc.
|
||||
if (aTriggeredExternally && gPrefs.promptForExternal) {
|
||||
if (
|
||||
aTriggeredExternally &&
|
||||
gPrefs.promptForExternal &&
|
||||
// ... unless we intend to open the link with a website or extension:
|
||||
!(
|
||||
aHandler.preferredAction == Ci.nsIHandlerInfo.useHelperApp &&
|
||||
aHandler.preferredApplicationHandler instanceof Ci.nsIWebHandlerApp
|
||||
)
|
||||
) {
|
||||
aHandler.alwaysAskBeforeHandling = true;
|
||||
}
|
||||
|
||||
|
|
|
@ -11,42 +11,45 @@ let gHandlerService = Cc["@mozilla.org/uriloader/handler-service;1"].getService(
|
|||
* Creates dummy protocol handler
|
||||
*/
|
||||
function initTestHandlers() {
|
||||
let handlerInfo = HandlerServiceTestUtils.getBlankHandlerInfo("yoink");
|
||||
let handlerInfoThatAsks = HandlerServiceTestUtils.getBlankHandlerInfo(
|
||||
"should-ask"
|
||||
);
|
||||
|
||||
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);
|
||||
handlerInfo.possibleApplicationHandlers.appendElement(appHandler);
|
||||
handlerInfo.preferredApplicationHandler = appHandler;
|
||||
handlerInfo.preferredAction = handlerInfo.useHelperApp;
|
||||
handlerInfo.alwaysAskBeforeHandling = false;
|
||||
gHandlerService.store(handlerInfo);
|
||||
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(handlerInfo);
|
||||
gHandlerService.remove(webHandlerInfo);
|
||||
gHandlerService.remove(handlerInfoThatAsks);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 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() {
|
||||
await SpecialPowers.pushPrefEnv({
|
||||
set: [["network.protocol-handler.prompt-from-external", true]],
|
||||
});
|
||||
initTestHandlers();
|
||||
|
||||
let cmdLineHandler = Cc["@mozilla.org/browser/final-clh;1"].getService(
|
||||
Ci.nsICommandLineHandler
|
||||
);
|
||||
let fakeCmdLine = {
|
||||
function makeCmdLineHelper(url) {
|
||||
return {
|
||||
length: 1,
|
||||
_arg: "yoink:yoink",
|
||||
_arg: url,
|
||||
|
||||
getArgument(aIndex) {
|
||||
if (aIndex == 0) {
|
||||
|
@ -81,10 +84,31 @@ add_task(async function test_external_asks_anyway() {
|
|||
},
|
||||
QueryInterface: ChromeUtils.generateQI(["nsICommandLine"]),
|
||||
};
|
||||
}
|
||||
|
||||
add_task(async function setup() {
|
||||
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("should-ask:dummy");
|
||||
cmdLineHandler.handle(fakeCmdLine);
|
||||
let dialog = await chooserDialogOpenPromise;
|
||||
ok(dialog, "Should have prompted.");
|
||||
|
@ -99,3 +123,49 @@ add_task(async function test_external_asks_anyway() {
|
|||
// 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
|
||||
);
|
||||
});
|
||||
|
|
Загрузка…
Ссылка в новой задаче