Bug 1850631 - Call nsIDefaultAgent directly to set default. r=nrishel,nalexander
Differential Revision: https://phabricator.services.mozilla.com/D187853
This commit is contained in:
@@ -9,9 +9,7 @@ const lazy = {};
|
||||
|
||||
ChromeUtils.defineESModuleGetters(lazy, {
|
||||
NimbusFeatures: "resource://nimbus/ExperimentAPI.sys.mjs",
|
||||
Subprocess: "resource://gre/modules/Subprocess.sys.mjs",
|
||||
WindowsRegistry: "resource://gre/modules/WindowsRegistry.sys.mjs",
|
||||
setTimeout: "resource://gre/modules/Timer.sys.mjs",
|
||||
});
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(
|
||||
@@ -128,20 +126,6 @@ let ShellServiceInternal = {
|
||||
return false;
|
||||
},
|
||||
|
||||
/*
|
||||
* Invoke the Windows Default Browser agent with the given options.
|
||||
*
|
||||
* Separated for easy stubbing in tests.
|
||||
*/
|
||||
_callExternalDefaultBrowserAgent(options = {}) {
|
||||
const wdba = Services.dirsvc.get("XREExeF", Ci.nsIFile);
|
||||
wdba.leafName = "default-browser-agent.exe";
|
||||
return lazy.Subprocess.call({
|
||||
...options,
|
||||
command: options.command || wdba.path,
|
||||
});
|
||||
},
|
||||
|
||||
/*
|
||||
* Check if UserChoice is impossible.
|
||||
*
|
||||
@@ -267,13 +251,6 @@ let ShellServiceInternal = {
|
||||
|
||||
lazy.log.info("Setting Firefox as default using UserChoice");
|
||||
|
||||
// We launch the WDBA to handle the registry writes, see
|
||||
// SetDefaultBrowserUserChoice() in
|
||||
// toolkit/mozapps/defaultagent/SetDefaultBrowser.cpp.
|
||||
// This is external in case an overzealous antimalware product decides to
|
||||
// quarrantine any program that writes UserChoice, though this has not
|
||||
// occurred during extensive testing.
|
||||
|
||||
let telemetryResult = "ErrOther";
|
||||
|
||||
try {
|
||||
@@ -289,22 +266,26 @@ let ShellServiceInternal = {
|
||||
const aumi = lazy.XreDirProvider.getInstallHash();
|
||||
|
||||
telemetryResult = "ErrLaunchExe";
|
||||
const exeArgs = ["set-default-browser-user-choice", aumi];
|
||||
const extraFileExtensions = [];
|
||||
if (
|
||||
lazy.NimbusFeatures.shellService.getVariable("setDefaultPDFHandler")
|
||||
) {
|
||||
if (this._shouldSetDefaultPDFHandler()) {
|
||||
lazy.log.info("Setting Firefox as default PDF handler");
|
||||
exeArgs.push(".pdf", "FirefoxPDF");
|
||||
extraFileExtensions.push(".pdf", "FirefoxPDF");
|
||||
} else {
|
||||
lazy.log.info("Not setting Firefox as default PDF handler");
|
||||
}
|
||||
}
|
||||
const exeProcess = await this._callExternalDefaultBrowserAgent({
|
||||
arguments: exeArgs,
|
||||
});
|
||||
telemetryResult = "ErrOther";
|
||||
await this._handleWDBAResult(exeProcess);
|
||||
try {
|
||||
this.defaultAgent.setDefaultBrowserUserChoice(
|
||||
aumi,
|
||||
extraFileExtensions
|
||||
);
|
||||
} catch (err) {
|
||||
telemetryResult = "ErrOther";
|
||||
this._handleWDBAResult(err.result || Cr.NS_ERROR_FAILURE);
|
||||
}
|
||||
telemetryResult = "Success";
|
||||
} catch (ex) {
|
||||
if (ex instanceof WDBAError) {
|
||||
@@ -327,22 +308,19 @@ let ShellServiceInternal = {
|
||||
throw new Error("Windows-only");
|
||||
}
|
||||
|
||||
// See comment in setAsDefaultUserChoice for an explanation of why we shell
|
||||
// out to WDBA.
|
||||
let telemetryResult = "ErrOther";
|
||||
|
||||
try {
|
||||
const aumi = lazy.XreDirProvider.getInstallHash();
|
||||
const exeProcess = await this._callExternalDefaultBrowserAgent({
|
||||
arguments: [
|
||||
"set-default-extension-handlers-user-choice",
|
||||
aumi,
|
||||
try {
|
||||
this.defaultAgent.setDefaultExtensionHandlersUserChoice(aumi, [
|
||||
".pdf",
|
||||
"FirefoxPDF",
|
||||
],
|
||||
});
|
||||
telemetryResult = "ErrOther";
|
||||
await this._handleWDBAResult(exeProcess);
|
||||
]);
|
||||
} catch (err) {
|
||||
telemetryResult = "ErrOther";
|
||||
this._handleWDBAResult(err.result || Cr.NS_ERROR_FAILURE);
|
||||
}
|
||||
telemetryResult = "Success";
|
||||
} catch (ex) {
|
||||
if (ex instanceof WDBAError) {
|
||||
@@ -505,23 +483,10 @@ let ShellServiceInternal = {
|
||||
}
|
||||
},
|
||||
|
||||
async _handleWDBAResult(exeProcess, exeWaitTimeoutMs = 2000) {
|
||||
const STILL_ACTIVE = 0x103;
|
||||
|
||||
const exeWaitPromise = exeProcess.wait();
|
||||
const timeoutPromise = new Promise(function (resolve) {
|
||||
lazy.setTimeout(
|
||||
() => resolve({ exitCode: STILL_ACTIVE }),
|
||||
exeWaitTimeoutMs
|
||||
);
|
||||
});
|
||||
|
||||
const { exitCode } = await Promise.race([exeWaitPromise, timeoutPromise]);
|
||||
|
||||
_handleWDBAResult(exitCode) {
|
||||
if (exitCode != Cr.NS_OK) {
|
||||
const telemetryResult =
|
||||
new Map([
|
||||
[STILL_ACTIVE, "ErrExeTimeout"],
|
||||
[Cr.NS_ERROR_WDBA_NO_PROGID, "ErrExeProgID"],
|
||||
[Cr.NS_ERROR_WDBA_HASH_CHECK, "ErrExeHash"],
|
||||
[Cr.NS_ERROR_WDBA_REJECTED, "ErrExeRejected"],
|
||||
@@ -534,6 +499,7 @@ let ShellServiceInternal = {
|
||||
};
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetters(ShellServiceInternal, {
|
||||
defaultAgent: ["@mozilla.org/default-agent;1", "nsIDefaultAgent"],
|
||||
shellService: ["@mozilla.org/browser/shell-service;1", "nsIShellService"],
|
||||
macDockSupport: ["@mozilla.org/widget/macdocksupport;1", "nsIMacDockSupport"],
|
||||
});
|
||||
|
||||
@@ -8,19 +8,13 @@ ChromeUtils.defineESModuleGetters(this, {
|
||||
sinon: "resource://testing-common/Sinon.sys.mjs",
|
||||
});
|
||||
|
||||
const _handleWDBAResultStub = sinon
|
||||
.stub(ShellService, "_handleWDBAResult")
|
||||
.callsFake(async () => {
|
||||
throw new Error("from _handleWDBAResultStub");
|
||||
});
|
||||
const setDefaultBrowserUserChoiceStub = () => {
|
||||
throw Components.Exception("", Cr.NS_ERROR_WDBA_NO_PROGID);
|
||||
};
|
||||
|
||||
const _callExternalDefaultBrowserAgentStub = sinon
|
||||
.stub(ShellService, "_callExternalDefaultBrowserAgent")
|
||||
.callsFake(async () => ({
|
||||
async wait() {
|
||||
return { exitCode: 0 };
|
||||
},
|
||||
}));
|
||||
const defaultAgentStub = sinon
|
||||
.stub(ShellService, "defaultAgent")
|
||||
.value({ setDefaultBrowserUserChoice: setDefaultBrowserUserChoiceStub });
|
||||
|
||||
const _userChoiceImpossibleTelemetryResultStub = sinon
|
||||
.stub(ShellService, "_userChoiceImpossibleTelemetryResult")
|
||||
@@ -35,8 +29,7 @@ const shellStub = sinon
|
||||
.value({ setDefaultBrowser: setDefaultStub });
|
||||
|
||||
registerCleanupFunction(() => {
|
||||
_handleWDBAResultStub.restore();
|
||||
_callExternalDefaultBrowserAgentStub.restore();
|
||||
defaultAgentStub.restore();
|
||||
_userChoiceImpossibleTelemetryResultStub.restore();
|
||||
userChoiceStub.restore();
|
||||
shellStub.restore();
|
||||
@@ -136,10 +129,13 @@ add_task(async function ensure_fallback() {
|
||||
|
||||
Assert.ok(userChoiceStub.called, "Set default with user choice called");
|
||||
|
||||
let thrown = false;
|
||||
await userChoicePromise.catch(() => (thrown = true));
|
||||
let message = "";
|
||||
await userChoicePromise.catch(err => (message = err.message || ""));
|
||||
|
||||
Assert.ok(thrown, "Set default with user choice threw an error");
|
||||
Assert.ok(
|
||||
message.includes("ErrExeProgID"),
|
||||
"Set default with user choice threw an expected error"
|
||||
);
|
||||
Assert.ok(setDefaultStub.called, "Fallbacked to plain set default");
|
||||
|
||||
await doCleanup();
|
||||
|
||||
@@ -4,10 +4,22 @@
|
||||
ChromeUtils.defineESModuleGetters(this, {
|
||||
ExperimentAPI: "resource://nimbus/ExperimentAPI.sys.mjs",
|
||||
ExperimentFakes: "resource://testing-common/NimbusTestUtils.sys.mjs",
|
||||
MockRegistrar: "resource://testing-common/MockRegistrar.sys.mjs",
|
||||
NimbusFeatures: "resource://nimbus/ExperimentAPI.sys.mjs",
|
||||
sinon: "resource://testing-common/Sinon.sys.mjs",
|
||||
});
|
||||
|
||||
const mockedDefaultAgent = {
|
||||
setDefaultBrowserUserChoice: sinon.stub(),
|
||||
setDefaultExtensionHandlersUserChoice: sinon.stub(),
|
||||
QueryInterface: ChromeUtils.generateQI(["nsIDefaultAgent"]),
|
||||
};
|
||||
|
||||
const defaultAgentCID = MockRegistrar.register(
|
||||
"@mozilla.org/default-agent;1",
|
||||
mockedDefaultAgent
|
||||
);
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(
|
||||
this,
|
||||
"XreDirProvider",
|
||||
@@ -15,14 +27,6 @@ XPCOMUtils.defineLazyServiceGetter(
|
||||
"nsIXREDirProvider"
|
||||
);
|
||||
|
||||
const _callExternalDefaultBrowserAgentStub = sinon
|
||||
.stub(ShellService, "_callExternalDefaultBrowserAgent")
|
||||
.callsFake(async () => ({
|
||||
async wait() {
|
||||
return { exitCode: 0 };
|
||||
},
|
||||
}));
|
||||
|
||||
const _userChoiceImpossibleTelemetryResultStub = sinon
|
||||
.stub(ShellService, "_userChoiceImpossibleTelemetryResult")
|
||||
.callsFake(() => null);
|
||||
@@ -37,7 +41,7 @@ const shellStub = sinon.stub(ShellService, "shellService").value({
|
||||
});
|
||||
|
||||
registerCleanupFunction(() => {
|
||||
_callExternalDefaultBrowserAgentStub.restore();
|
||||
MockRegistrar.unregister(defaultAgentCID);
|
||||
_userChoiceImpossibleTelemetryResultStub.restore();
|
||||
shellStub.restore();
|
||||
|
||||
@@ -74,21 +78,15 @@ add_task(async function remoteEnableWithPDF() {
|
||||
true
|
||||
);
|
||||
|
||||
_callExternalDefaultBrowserAgentStub.resetHistory();
|
||||
mockedDefaultAgent.setDefaultBrowserUserChoice.resetHistory();
|
||||
ShellService.setDefaultBrowser();
|
||||
|
||||
const aumi = XreDirProvider.getInstallHash();
|
||||
Assert.ok(_callExternalDefaultBrowserAgentStub.called);
|
||||
Assert.deepEqual(_callExternalDefaultBrowserAgentStub.firstCall.args, [
|
||||
{
|
||||
arguments: [
|
||||
"set-default-browser-user-choice",
|
||||
aumi,
|
||||
".pdf",
|
||||
"FirefoxPDF",
|
||||
],
|
||||
},
|
||||
]);
|
||||
Assert.ok(mockedDefaultAgent.setDefaultBrowserUserChoice.called);
|
||||
Assert.deepEqual(
|
||||
mockedDefaultAgent.setDefaultBrowserUserChoice.firstCall.args,
|
||||
[aumi, [".pdf", "FirefoxPDF"]]
|
||||
);
|
||||
|
||||
await doCleanup();
|
||||
});
|
||||
@@ -125,22 +123,13 @@ add_task(async function remoteEnableWithPDF_testOnlyReplaceBrowsers() {
|
||||
for (let progId of ["", "MSEdgePDF"]) {
|
||||
queryCurrentDefaultHandlerForStub.callsFake(() => progId);
|
||||
|
||||
_callExternalDefaultBrowserAgentStub.resetHistory();
|
||||
mockedDefaultAgent.setDefaultBrowserUserChoice.resetHistory();
|
||||
ShellService.setDefaultBrowser();
|
||||
|
||||
Assert.ok(_callExternalDefaultBrowserAgentStub.called);
|
||||
Assert.ok(mockedDefaultAgent.setDefaultBrowserUserChoice.called);
|
||||
Assert.deepEqual(
|
||||
_callExternalDefaultBrowserAgentStub.firstCall.args,
|
||||
[
|
||||
{
|
||||
arguments: [
|
||||
"set-default-browser-user-choice",
|
||||
aumi,
|
||||
".pdf",
|
||||
"FirefoxPDF",
|
||||
],
|
||||
},
|
||||
],
|
||||
mockedDefaultAgent.setDefaultBrowserUserChoice.firstCall.args,
|
||||
[aumi, [".pdf", "FirefoxPDF"]],
|
||||
`Will take default from missing association or known browser with ProgID '${progId}'`
|
||||
);
|
||||
}
|
||||
@@ -148,13 +137,13 @@ add_task(async function remoteEnableWithPDF_testOnlyReplaceBrowsers() {
|
||||
// But not from a non-browser.
|
||||
queryCurrentDefaultHandlerForStub.callsFake(() => "Acrobat.Document.DC");
|
||||
|
||||
_callExternalDefaultBrowserAgentStub.resetHistory();
|
||||
mockedDefaultAgent.setDefaultBrowserUserChoice.resetHistory();
|
||||
ShellService.setDefaultBrowser();
|
||||
|
||||
Assert.ok(_callExternalDefaultBrowserAgentStub.called);
|
||||
Assert.ok(mockedDefaultAgent.setDefaultBrowserUserChoice.called);
|
||||
Assert.deepEqual(
|
||||
_callExternalDefaultBrowserAgentStub.firstCall.args,
|
||||
[{ arguments: ["set-default-browser-user-choice", aumi] }],
|
||||
mockedDefaultAgent.setDefaultBrowserUserChoice.firstCall.args,
|
||||
[aumi, []],
|
||||
`Will not take default from non-browser`
|
||||
);
|
||||
|
||||
@@ -180,14 +169,15 @@ add_task(async function remoteEnableWithoutPDF() {
|
||||
false
|
||||
);
|
||||
|
||||
_callExternalDefaultBrowserAgentStub.resetHistory();
|
||||
mockedDefaultAgent.setDefaultBrowserUserChoice.resetHistory();
|
||||
ShellService.setDefaultBrowser();
|
||||
|
||||
const aumi = XreDirProvider.getInstallHash();
|
||||
Assert.ok(_callExternalDefaultBrowserAgentStub.called);
|
||||
Assert.deepEqual(_callExternalDefaultBrowserAgentStub.firstCall.args, [
|
||||
{ arguments: ["set-default-browser-user-choice", aumi] },
|
||||
]);
|
||||
Assert.ok(mockedDefaultAgent.setDefaultBrowserUserChoice.called);
|
||||
Assert.deepEqual(
|
||||
mockedDefaultAgent.setDefaultBrowserUserChoice.firstCall.args,
|
||||
[aumi, []]
|
||||
);
|
||||
|
||||
await doCleanup();
|
||||
});
|
||||
@@ -211,10 +201,10 @@ add_task(async function remoteDisable() {
|
||||
true
|
||||
);
|
||||
|
||||
_callExternalDefaultBrowserAgentStub.resetHistory();
|
||||
mockedDefaultAgent.setDefaultBrowserUserChoice.resetHistory();
|
||||
ShellService.setDefaultBrowser();
|
||||
|
||||
Assert.ok(_callExternalDefaultBrowserAgentStub.notCalled);
|
||||
Assert.ok(mockedDefaultAgent.setDefaultBrowserUserChoice.notCalled);
|
||||
Assert.ok(setDefaultStub.called);
|
||||
|
||||
await doCleanup();
|
||||
@@ -224,12 +214,7 @@ add_task(async function test_setAsDefaultPDFHandler_knownBrowser() {
|
||||
const sandbox = sinon.createSandbox();
|
||||
|
||||
const aumi = XreDirProvider.getInstallHash();
|
||||
const expectedArguments = [
|
||||
"set-default-extension-handlers-user-choice",
|
||||
aumi,
|
||||
".pdf",
|
||||
"FirefoxPDF",
|
||||
];
|
||||
const expectedArguments = [aumi, [".pdf", "FirefoxPDF"]];
|
||||
|
||||
try {
|
||||
const pdfHandlerResult = { registered: true, knownBrowser: true };
|
||||
@@ -240,51 +225,51 @@ add_task(async function test_setAsDefaultPDFHandler_knownBrowser() {
|
||||
info("Testing setAsDefaultPDFHandler(true) when knownBrowser = true");
|
||||
ShellService.setAsDefaultPDFHandler(true);
|
||||
Assert.ok(
|
||||
_callExternalDefaultBrowserAgentStub.called,
|
||||
mockedDefaultAgent.setDefaultExtensionHandlersUserChoice.called,
|
||||
"Called default browser agent"
|
||||
);
|
||||
Assert.deepEqual(
|
||||
_callExternalDefaultBrowserAgentStub.firstCall.args,
|
||||
[{ arguments: expectedArguments }],
|
||||
mockedDefaultAgent.setDefaultExtensionHandlersUserChoice.firstCall.args,
|
||||
expectedArguments,
|
||||
"Called default browser agent with expected arguments"
|
||||
);
|
||||
_callExternalDefaultBrowserAgentStub.resetHistory();
|
||||
mockedDefaultAgent.setDefaultExtensionHandlersUserChoice.resetHistory();
|
||||
|
||||
info("Testing setAsDefaultPDFHandler(false) when knownBrowser = true");
|
||||
ShellService.setAsDefaultPDFHandler(false);
|
||||
Assert.ok(
|
||||
_callExternalDefaultBrowserAgentStub.called,
|
||||
mockedDefaultAgent.setDefaultExtensionHandlersUserChoice.called,
|
||||
"Called default browser agent"
|
||||
);
|
||||
Assert.deepEqual(
|
||||
_callExternalDefaultBrowserAgentStub.firstCall.args,
|
||||
[{ arguments: expectedArguments }],
|
||||
mockedDefaultAgent.setDefaultExtensionHandlersUserChoice.firstCall.args,
|
||||
expectedArguments,
|
||||
"Called default browser agent with expected arguments"
|
||||
);
|
||||
_callExternalDefaultBrowserAgentStub.resetHistory();
|
||||
mockedDefaultAgent.setDefaultExtensionHandlersUserChoice.resetHistory();
|
||||
|
||||
pdfHandlerResult.knownBrowser = false;
|
||||
|
||||
info("Testing setAsDefaultPDFHandler(true) when knownBrowser = false");
|
||||
ShellService.setAsDefaultPDFHandler(true);
|
||||
Assert.ok(
|
||||
_callExternalDefaultBrowserAgentStub.notCalled,
|
||||
mockedDefaultAgent.setDefaultExtensionHandlersUserChoice.notCalled,
|
||||
"Did not call default browser agent"
|
||||
);
|
||||
_callExternalDefaultBrowserAgentStub.resetHistory();
|
||||
mockedDefaultAgent.setDefaultExtensionHandlersUserChoice.resetHistory();
|
||||
|
||||
info("Testing setAsDefaultPDFHandler(false) when knownBrowser = false");
|
||||
ShellService.setAsDefaultPDFHandler(false);
|
||||
Assert.ok(
|
||||
_callExternalDefaultBrowserAgentStub.called,
|
||||
mockedDefaultAgent.setDefaultExtensionHandlersUserChoice.called,
|
||||
"Called default browser agent"
|
||||
);
|
||||
Assert.deepEqual(
|
||||
_callExternalDefaultBrowserAgentStub.firstCall.args,
|
||||
[{ arguments: expectedArguments }],
|
||||
mockedDefaultAgent.setDefaultExtensionHandlersUserChoice.firstCall.args,
|
||||
expectedArguments,
|
||||
"Called default browser agent with expected arguments"
|
||||
);
|
||||
_callExternalDefaultBrowserAgentStub.resetHistory();
|
||||
mockedDefaultAgent.setDefaultExtensionHandlersUserChoice.resetHistory();
|
||||
} finally {
|
||||
sandbox.restore();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user