294 lines
8.5 KiB
JavaScript
294 lines
8.5 KiB
JavaScript
/* Any copyright is dedicated to the Public Domain.
|
|
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
|
|
|
const { CommandLineHandler } = ChromeUtils.importESModule(
|
|
"moz-src:///browser/components/shell/WindowsSetDefaultAppCmdHandler.sys.mjs"
|
|
);
|
|
|
|
ChromeUtils.defineESModuleGetters(this, {
|
|
BrowserWindowTracker: "resource:///modules/BrowserWindowTracker.sys.mjs",
|
|
SET_DEFAULT_REDIRECT_PREF:
|
|
"moz-src:///browser/components/shell/WindowsSetDefaultRedirect.sys.mjs",
|
|
ShellService: "moz-src:///browser/components/shell/ShellService.sys.mjs",
|
|
WindowsSetDefaultRedirect:
|
|
"moz-src:///browser/components/shell/WindowsSetDefaultRedirect.sys.mjs",
|
|
sinon: "resource://testing-common/Sinon.sys.mjs",
|
|
});
|
|
|
|
Assert.equal(AppConstants.platform, "win", "Platform is Windows");
|
|
|
|
const confusedFoxPath = ShellService.getBundledPdfFile("confused_fox.pdf").path;
|
|
const blankURISpec = Services.io.newFileURI(
|
|
ShellService.getBundledPdfFile("blank.pdf")
|
|
).spec;
|
|
|
|
const workingDir = Services.dirsvc.get("GreD", Ci.nsIFile);
|
|
|
|
// Build a real nsICommandLine from an args array, so we exercise the same
|
|
// flag-parsing the OS-initiated launch goes through
|
|
function makeCmdLine(args, state = Ci.nsICommandLine.STATE_INITIAL_LAUNCH) {
|
|
return Cu.createCommandLine(args, workingDir, state);
|
|
}
|
|
|
|
// Arm the one-shot redirect via the real ShellService helper, the way
|
|
// setAsDefault{*}Handler does right before launching the OS picker. These
|
|
// tests all use file openWithArgs, so default the type.
|
|
function armRedirect(
|
|
openWithArg,
|
|
overrideUri,
|
|
type = WindowsSetDefaultRedirect.TYPE.FILE
|
|
) {
|
|
WindowsSetDefaultRedirect.arm(openWithArg, overrideUri, type);
|
|
}
|
|
|
|
let fakeWin;
|
|
let getTopWindowStub;
|
|
let openWindowStub;
|
|
|
|
add_setup(function () {
|
|
fakeWin = { openTrustedLinkIn: sinon.stub() };
|
|
// Stubbed rather than spied: getTopWindow must return our fake window (and
|
|
// null on demand), and openWindow must not actually open a window in the
|
|
// test harness. We only inspect the calls.
|
|
getTopWindowStub = sinon.stub(BrowserWindowTracker, "getTopWindow");
|
|
openWindowStub = sinon.stub(BrowserWindowTracker, "openWindow");
|
|
});
|
|
|
|
registerCleanupFunction(() => {
|
|
sinon.restore();
|
|
Services.prefs.clearUserPref(SET_DEFAULT_REDIRECT_PREF);
|
|
});
|
|
|
|
function resetState() {
|
|
fakeWin.openTrustedLinkIn.resetHistory();
|
|
getTopWindowStub.reset();
|
|
getTopWindowStub.returns(fakeWin);
|
|
openWindowStub.reset();
|
|
Services.prefs.clearUserPref(SET_DEFAULT_REDIRECT_PREF);
|
|
}
|
|
|
|
add_task(async function test_no_osint_returns_early() {
|
|
resetState();
|
|
armRedirect(confusedFoxPath, blankURISpec);
|
|
const cmdLine = makeCmdLine(["-url", confusedFoxPath]);
|
|
new CommandLineHandler().handle(cmdLine);
|
|
|
|
Assert.equal(
|
|
cmdLine.preventDefault,
|
|
false,
|
|
"preventDefault left untouched without -osint"
|
|
);
|
|
Assert.greaterOrEqual(
|
|
cmdLine.findFlag("url", false),
|
|
0,
|
|
"-url remains for the next handler"
|
|
);
|
|
Assert.ok(
|
|
fakeWin.openTrustedLinkIn.notCalled,
|
|
"No tab opened without -osint"
|
|
);
|
|
Assert.ok(openWindowStub.notCalled, "No window opened without -osint");
|
|
});
|
|
|
|
add_task(async function test_osint_without_url_returns_early() {
|
|
resetState();
|
|
armRedirect(confusedFoxPath, blankURISpec);
|
|
const cmdLine = makeCmdLine(["-osint"]);
|
|
new CommandLineHandler().handle(cmdLine);
|
|
|
|
Assert.equal(
|
|
cmdLine.preventDefault,
|
|
false,
|
|
"preventDefault left untouched without -url"
|
|
);
|
|
Assert.ok(fakeWin.openTrustedLinkIn.notCalled, "No tab opened without -url");
|
|
Assert.ok(openWindowStub.notCalled, "No window opened without -url");
|
|
});
|
|
|
|
add_task(async function test_no_pending_redirect_leaves_arg() {
|
|
// No armed redirect: even a -url that looks like our stub PDF is a real,
|
|
// user-initiated open (e.g. they double-clicked the file), so we must leave
|
|
// it for BrowserContentHandler.
|
|
resetState();
|
|
|
|
const cmdLine = makeCmdLine(["-osint", "-url", confusedFoxPath]);
|
|
new CommandLineHandler().handle(cmdLine);
|
|
|
|
Assert.equal(
|
|
cmdLine.preventDefault,
|
|
false,
|
|
"preventDefault not set when no redirect is pending"
|
|
);
|
|
Assert.greaterOrEqual(
|
|
cmdLine.findFlag("url", false),
|
|
0,
|
|
"-url preserved for BrowserContentHandler"
|
|
);
|
|
Assert.ok(
|
|
fakeWin.openTrustedLinkIn.notCalled,
|
|
"No tab opened when no redirect is pending"
|
|
);
|
|
Assert.ok(
|
|
openWindowStub.notCalled,
|
|
"No window opened when no redirect is pending"
|
|
);
|
|
});
|
|
|
|
add_task(async function test_unrelated_url_arg_is_ignored() {
|
|
resetState();
|
|
armRedirect(confusedFoxPath, blankURISpec);
|
|
|
|
const cmdLine = makeCmdLine([
|
|
"-osint",
|
|
"-url",
|
|
"https://example.com/some-page",
|
|
]);
|
|
new CommandLineHandler().handle(cmdLine);
|
|
|
|
Assert.equal(
|
|
cmdLine.preventDefault,
|
|
false,
|
|
"preventDefault not set for a -url that isn't the pending openWithArg"
|
|
);
|
|
Assert.greaterOrEqual(
|
|
cmdLine.findFlag("url", false),
|
|
0,
|
|
"-url preserved for subsequent handler"
|
|
);
|
|
Assert.ok(
|
|
fakeWin.openTrustedLinkIn.notCalled,
|
|
"No tab opened for an unrelated -url"
|
|
);
|
|
Assert.ok(
|
|
Services.prefs.prefHasUserValue(SET_DEFAULT_REDIRECT_PREF),
|
|
"Pending redirect untouched when the openWithArg doesn't match"
|
|
);
|
|
});
|
|
|
|
add_task(async function test_suppress_only_when_target_null() {
|
|
resetState();
|
|
armRedirect(confusedFoxPath, null);
|
|
|
|
const cmdLine = makeCmdLine(["-osint", "-url", confusedFoxPath]);
|
|
new CommandLineHandler().handle(cmdLine);
|
|
|
|
Assert.equal(
|
|
cmdLine.preventDefault,
|
|
true,
|
|
"openWithArg suppressed so BrowserContentHandler skips it"
|
|
);
|
|
Assert.equal(
|
|
cmdLine.findFlag("url", false),
|
|
-1,
|
|
"-url consumed even with no redirect target"
|
|
);
|
|
Assert.ok(
|
|
fakeWin.openTrustedLinkIn.notCalled,
|
|
"No redirect when target is null"
|
|
);
|
|
Assert.ok(openWindowStub.notCalled, "No fallback window when target is null");
|
|
Assert.ok(
|
|
!Services.prefs.prefHasUserValue(SET_DEFAULT_REDIRECT_PREF),
|
|
"Redirect intent consumed"
|
|
);
|
|
});
|
|
|
|
add_task(async function test_redirects_to_top_window() {
|
|
resetState();
|
|
armRedirect(confusedFoxPath, blankURISpec);
|
|
|
|
const cmdLine = makeCmdLine(["-osint", "-url", confusedFoxPath]);
|
|
new CommandLineHandler().handle(cmdLine);
|
|
|
|
Assert.equal(
|
|
cmdLine.preventDefault,
|
|
true,
|
|
"Default open suppressed for the pending openWithArg"
|
|
);
|
|
Assert.equal(cmdLine.findFlag("url", false), -1, "-url consumed");
|
|
Assert.ok(
|
|
fakeWin.openTrustedLinkIn.calledOnce,
|
|
"Redirected into the top window"
|
|
);
|
|
Assert.deepEqual(fakeWin.openTrustedLinkIn.firstCall.args, [
|
|
blankURISpec,
|
|
"tab",
|
|
]);
|
|
Assert.ok(openWindowStub.notCalled, "No new window when one exists");
|
|
Assert.ok(
|
|
!Services.prefs.prefHasUserValue(SET_DEFAULT_REDIRECT_PREF),
|
|
"Redirect intent is one-shot and cleared after use"
|
|
);
|
|
});
|
|
|
|
add_task(async function test_opens_new_window_when_no_top() {
|
|
resetState();
|
|
getTopWindowStub.returns(null);
|
|
armRedirect(confusedFoxPath, blankURISpec);
|
|
|
|
const cmdLine = makeCmdLine(["-osint", "-url", confusedFoxPath]);
|
|
new CommandLineHandler().handle(cmdLine);
|
|
|
|
Assert.equal(
|
|
cmdLine.preventDefault,
|
|
true,
|
|
"Default open suppressed even when no top window exists"
|
|
);
|
|
Assert.ok(
|
|
fakeWin.openTrustedLinkIn.notCalled,
|
|
"Top-window path skipped when getTopWindow returns null"
|
|
);
|
|
Assert.ok(openWindowStub.calledOnce, "Falls back to openWindow");
|
|
|
|
const opts = openWindowStub.firstCall.args[0];
|
|
Assert.ok(
|
|
opts && opts.args,
|
|
"openWindow called with a {args} options object"
|
|
);
|
|
Assert.ok(
|
|
opts.args instanceof Ci.nsISupportsString,
|
|
"args is an nsISupportsString"
|
|
);
|
|
Assert.equal(
|
|
opts.args.data,
|
|
blankURISpec,
|
|
"nsISupportsString carries the redirect URI"
|
|
);
|
|
Assert.ok(
|
|
!Services.prefs.prefHasUserValue(SET_DEFAULT_REDIRECT_PREF),
|
|
"Redirect intent is one-shot and cleared after use"
|
|
);
|
|
});
|
|
|
|
add_task(async function test_intent_is_one_shot() {
|
|
resetState();
|
|
armRedirect(confusedFoxPath, blankURISpec);
|
|
|
|
new CommandLineHandler().handle(
|
|
makeCmdLine(["-osint", "-url", confusedFoxPath])
|
|
);
|
|
Assert.ok(
|
|
fakeWin.openTrustedLinkIn.calledOnce,
|
|
"First call honors the pending redirect"
|
|
);
|
|
|
|
fakeWin.openTrustedLinkIn.resetHistory();
|
|
const second = makeCmdLine(["-osint", "-url", confusedFoxPath]);
|
|
new CommandLineHandler().handle(second);
|
|
|
|
Assert.equal(
|
|
second.preventDefault,
|
|
false,
|
|
"Second call leaves the openWithArg alone because the intent was consumed"
|
|
);
|
|
Assert.greaterOrEqual(
|
|
second.findFlag("url", false),
|
|
0,
|
|
"-url preserved on the second call (no pending redirect)"
|
|
);
|
|
Assert.ok(
|
|
fakeWin.openTrustedLinkIn.notCalled,
|
|
"Second call does not redirect"
|
|
);
|
|
});
|