Files
Andrew McCreight b0e75f3d66 Bug 2065492 - Only register in updateAppInfo once. r=xpcom-reviewers,nika
Currently, updateAppInfo will see if there's a current factory registered for
app info, then unregister it using the testing-only CID. Because nobody else is
using that CID, this unregister can never succeed unless it was registered by
a previous call to updateAppInfo. This is okay in practice because you can override
a static factory and nobody else in the tests that use this is registering an
app info factory via another means.

My patch simplifies this process by tracking whether updateAppInfo has already
registered a factory so it only does it once. The factory can stay the same
even if the app info instance does not because the createInstance method of
the factory always uses the current value of currentAppInfo, so it'll be updated
as the app info changes.

My goal here is to remove the call to getClassObjectByContractID, which is an odd
API I am trying to remove.

Differential Revision: https://phabricator.services.mozilla.com/D320421
2026-08-22 01:28:58 +00:00

131 lines
3.7 KiB
JavaScript

/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
let origPlatformInfo = Cc["@mozilla.org/xre/app-info;1"].getService(
Ci.nsIPlatformInfo
);
// eslint-disable-next-line mozilla/use-services
let origRuntime = Cc["@mozilla.org/xre/app-info;1"].getService(
Ci.nsIXULRuntime
);
/**
* Create new XULAppInfo instance with specified options.
*
* options is a object with following keys:
* ID: nsIXULAppInfo.ID
* name: nsIXULAppInfo.name
* version: nsIXULAppInfo.version
* platformVersion: nsIXULAppInfo.platformVersion
* OS: nsIXULRuntime.OS
* appBuildID: nsIXULRuntime.appBuildID
* lastAppBuildID: nsIXULRuntime.lastAppBuildID
* lastAppVersion: nsIXULRuntime.lastAppVersion
*
* crashReporter: nsICrashReporter interface is implemented if true
*/
export var newAppInfo = function (options = {}) {
let appInfo = {
// nsIXULAppInfo
vendor: "Mozilla",
name: options.name ?? "xpcshell",
ID: options.ID ?? "xpcshell@tests.mozilla.org",
version: options.version ?? "1",
appBuildID: options.appBuildID ?? "20160315",
// nsIPlatformInfo
platformVersion: options.platformVersion ?? "p-ver",
platformBuildID: origPlatformInfo.platformBuildID,
// nsIXULRuntime
...Ci.nsIXULRuntime,
inSafeMode: false,
logConsoleErrors: true,
OS: options.OS ?? "XPCShell",
XPCOMABI: "noarch-spidermonkey",
invalidateCachesOnRestart() {},
processType: origRuntime.processType,
uniqueProcessID: origRuntime.uniqueProcessID,
fissionAutostart: origRuntime.fissionAutostart,
browserTabsRemoteAutostart: origRuntime.browserTabsRemoteAutostart,
get maxWebProcessCount() {
return origRuntime.maxWebProcessCount;
},
get launcherProcessState() {
return origRuntime.launcherProcessState;
},
// nsIWinAppHelper
get userCanElevate() {
return false;
},
};
appInfo.lastAppBuildID = options.lastAppBuildID ?? appInfo.appBuildID;
appInfo.lastAppVersion = options.lastAppVersion ?? appInfo.version;
let interfaces = [
Ci.nsIXULAppInfo,
Ci.nsIPlatformInfo,
Ci.nsIXULRuntime,
Ci.nsICrashReporter,
];
if ("nsIWinAppHelper" in Ci) {
interfaces.push(Ci.nsIWinAppHelper);
}
// nsICrashReporter
appInfo.annotations = {};
appInfo.annotateCrashReport = function (key, data) {
if (options.crashReporter) {
this.annotations[key] = data;
} else {
throw Components.Exception("", Cr.NS_ERROR_NOT_INITIALIZED);
}
};
appInfo.QueryInterface = ChromeUtils.generateQI(interfaces);
return appInfo;
};
var currentAppInfo = newAppInfo();
var registered = false;
/**
* Obtain a reference to the current object used to define XULAppInfo.
*/
export var getAppInfo = function () {
return currentAppInfo;
};
/**
* Update the current application info.
*
* See newAppInfo for options.
*
* To change the current XULAppInfo, simply call this function. This assumes
* that nobody else has dynamically registered an app info factory.
*/
export var updateAppInfo = function (options) {
currentAppInfo = newAppInfo(options);
Services.appinfo = currentAppInfo;
if (!registered) {
registered = true;
let factory = {
createInstance(iid) {
return currentAppInfo.QueryInterface(iid);
},
};
let registrar = Components.manager.QueryInterface(Ci.nsIComponentRegistrar);
let cid = Components.ID("{fbfae60b-64a4-44ef-a911-08ceb70b9f31}");
let contractID = "@mozilla.org/xre/app-info;1";
registrar.registerFactory(cid, "XULAppInfo", contractID, factory);
}
};