Exception in BootstrapLoader.js with Nightly 142.0a1 from 2025-06-25
Starting with Firefox Nightly 142.0a1 from 2025-06-25 there is new error BootstrapLoader.js
1751116296574 addons.xpi WARN Exception running bootstrap method startup on {dc572301-7619-498c-a57d-39143191b318}: TypeError: Components.manager.addBootstrappedManifestLocation is not a function(chrome://userchromejs/content/BootstrapLoader.js:389:30) JS Stack trace: [email protected]:389:30
[email protected]:2067:33
[email protected]:2183:34
[email protected]:2813:41
[email protected]:228:31
[email protected]:537:17
[email protected]:750:14
[email protected]:3702:26
[email protected]:73:29
Components.manager.addBootstrappedManifestLocation is not a function Components.manager.removeBootstrappedManifestLocation is not a function
Bug 1953136 Get rid of nsIComponentManager.addBootstrappedManifestLocation
@117649 can you look for replacement?
Starting with Firefox Nightly 142.0a1 from 2025-06-25 there is new error BootstrapLoader.js
1751116296574 addons.xpi WARN Exception running bootstrap method startup on {dc572301-7619-498c-a57d-39143191b318}: TypeError: Components.manager.addBootstrappedManifestLocation is not a function(chrome://userchromejs/content/BootstrapLoader.js:389:30) JS Stack trace: [email protected]:389:30 [email protected]:2067:33 [email protected]:2183:34 [email protected]:2813:41 [email protected]:228:31 [email protected]:537:17 [email protected]:750:14 [email protected]:3702:26 [email protected]:73:29Components.manager.addBootstrappedManifestLocation is not a function Components.manager.removeBootstrappedManifestLocation is not a function
Bug 1953136 Get rid of nsIComponentManager.addBootstrappedManifestLocation
@117649 can you look for replacement?
Just saw this. And I feel...... nothing. Guess is because Mozilla is never disappointing on disappoint.
Anyway I was thought about such contingency but way pale in comparison to this.
Looks like Mozilla is not getting rid of all built-in addons so there is still a way to register a path in jar://.
We could check XPIDatabase.sys.mjs XPIInstall.sys.mjs XPIProvider.sys.mjs to see if its possible to be used.
If its required we may be able to replace these modules in XPIExports.sys.mjs with our own to load our addon using remaining ways.
@117649,
look at Extension.sys.mjs
I think we can use aomStartup.registerChrome
but we will need to convert addon/chrome.manifest to chromeEntries array
const chromeEntries = [
['content', 'tabmixplus', 'chrome/content/'],
['content', 'tabmix-prefs', 'defaults/preferences/'],
['content', 'tabmix-resource', 'modules/'],
['content', 'tabmix-skin', 'chrome/skin/'],
['locale', 'tabmixplus', 'en-US', 'chrome/locale/en-US/'],
]
@evilpie, any advice?
without nsIComponentManager.addBootstrappedManifestLocation all legacy extension will stop working on Firefox 142
@117649, look at
Extension.sys.mjsI think we can useaomStartup.registerChromebut we will need to convertaddon/chrome.manifesttochromeEntriesarrayconst chromeEntries = [ ['content', 'tabmixplus', 'chrome/content/'], ['content', 'tabmix-prefs', 'defaults/preferences/'], ['content', 'tabmix-resource', 'modules/'], ['content', 'tabmix-skin', 'chrome/skin/'], ['locale', 'tabmixplus', 'en-US', 'chrome/locale/en-US/'], ]
https://searchfox.org/mozilla-central/source/toolkit/mozapps/extensions/test/xpcshell/test_registerchrome.js This show it take a "chrome.manifest" but I don't sure what contents is in it.
@onemen https://searchfox.org/mozilla-central/source/toolkit/mozapps/extensions/amIAddonManagerStartup.idl#39
https://searchfox.org/mozilla-central/source/build/docs/chrome-registration.rst
If I'm not misunderstand we may use override to restore some path structure but that override is per file level meaning if override from a folder to another folder you'll be take to that folder but access file in it with that override uri will fail.
@onemen I think I may see 2 relatively simple ways so far.
1st: Use renumerateJARSubtree registerChrome to restore our old chrome path structure at best. No idea if that is fully possible.
2nd: Use autoRegister for load and temp file for unload.
https://searchfox.org/mozilla-central/source/toolkit/content/tests/chrome/RegisterUnregisterChrome.js#106
@117649
test this utils.zip
I replaced Components.manager.addBootstrappedManifestLocation(file) with:
const addonManagerStartup = Cc["@mozilla.org/addons/addon-manager-startup;1"]
.getService(Ci.amIAddonManagerStartup);
const manifestURI = getURIForResourceInFile(file, 'chrome.manifest');
const chromeEntries = await parseManifestEntries(manifestURI)
this.chromeRegistryHandle = addonManagerStartup.registerChrome(manifestURI, chromeEntries);
parseManifestEntries is in new file ParseManifestEntries.sys.mjs
notice that amIAddonManagerStartup.registerChrome does not support skin entry from chrome.manifest
/**
* Registers a set of dynamic chrome registry entries, and returns an object
* with a `destruct()` method which must be called in order to unregister
* the entries.
*
* @param manifestURI The base manifest URI for the entries. URL values are
* resolved relative to this URI.
* @param entries An array of arrays, each containing a registry entry as it
* would appar in a chrome.manifest file. Only the following entry
* types are currently accepted:
*
* - "locale" A locale package entry. Must be a 4-element array.
* - "override" A URL override entry. Must be a 3-element array.
*/
In Tab Mix Plus I had to replace all skin entries with one content entries
+ content tabmix-skin chrome/skin/
- skin tabmixplus classic/1.0 chrome/skin/
- skin tabmix-version tabmixplus chrome/skin/app_version/91/ platformversion>=91
- skin tabmix-version tabmixplus chrome/skin/app_version/119/ platformversion>=119
- skin tabmix-os classic/1.0 chrome://tabmix-version/skin/win/ os=WINNT
- skin tabmix-os classic/1.0 chrome://tabmix-version/skin/mac/ os=Darwin
- skin tabmix-os classic/1.0 chrome://tabmix-version/skin/linux/ os=Linux
In
Tab Mix PlusI had to replace allskinentries with onecontententries
- content tabmix-skin chrome/skin/
skin tabmixplus classic/1.0 chrome/skin/
skin tabmix-version tabmixplus chrome/skin/app_version/91/ platformversion>=91
skin tabmix-version tabmixplus chrome/skin/app_version/119/ platformversion>=119
skin tabmix-os classic/1.0 chrome://tabmix-version/skin/win/ os=WINNT
skin tabmix-os classic/1.0 chrome://tabmix-version/skin/mac/ os=Darwin
skin tabmix-os classic/1.0 chrome://tabmix-version/skin/linux/ os=Linux
@onemen I'll try autoRegister first when I'm free, TMP aside it's better not to require any change on all of the legacy addons.
And you should also try override:
override
~~~~~~~~
In some cases an extension or embedder may wish to override a chrome
file provided by the application or XULRunner. In order to allow for
this, the chrome registration manifest allows for "override"
instructions:
.. code:: text
override chrome://package/type/original-uri.whatever new-resolved-URI [flags]
Note: overrides are not recursive (so overriding
chrome://foo/content/bar/ with file:///home/john/blah/ will not usually
do what you want or expect it to do). Also, the path inside overridden
files is relative to the overridden path, not the original one (this can
be annoying and/or useful in CSS files, for example).
.. _chrome_manifest_resource:
Last time I tried I believe you can do something like:
content addonid /
content addonscope chrome/content
override chrome://addonscope/skin/boo.css chrome://addonid/content/chrome/skin/boo.css
Then went on map every file in chrome/skin .
@onemen I have partially success with the autoRegister.
Tested on 141 by use a chrome.manifest FILE with absolute path I can register an addon's chrome path when addon is disabled.
content easydragtogo jar:file:///C:/Users/l/AppData/Roaming/Mozilla/Firefox/Profiles/5qsr10oq.dev-edition-default-1608570548307/extensions/[email protected]!/chrome/content/
content _easydragtogo jar:file:///C:/Users/l/AppData/Roaming/Mozilla/Firefox/Profiles/5qsr10oq.dev-edition-default-1608570548307/extensions/[email protected]!/
skin easydragtogo classic/1.0 jar:file:///C:/Users/l/AppData/Roaming/Mozilla/Firefox/Profiles/5qsr10oq.dev-edition-default-1608570548307/extensions/[email protected]!/chrome/skin/classic/
locale easydragtogo en-US jar:file:///C:/Users/l/AppData/Roaming/Mozilla/Firefox/Profiles/5qsr10oq.dev-edition-default-1608570548307/extensions/[email protected]!/chrome/locale/en-US/
locale easydragtogo zh-CN jar:file:///C:/Users/l/AppData/Roaming/Mozilla/Firefox/Profiles/5qsr10oq.dev-edition-default-1608570548307/extensions/[email protected]!/chrome/locale/zh-CN/
locale easydragtogo zh-TW jar:file:///C:/Users/l/AppData/Roaming/Mozilla/Firefox/Profiles/5qsr10oq.dev-edition-default-1608570548307/extensions/[email protected]!/chrome/locale/zh-TW/
locale easydragtogo de jar:file:///C:/Users/l/AppData/Roaming/Mozilla/Firefox/Profiles/5qsr10oq.dev-edition-default-1608570548307/extensions/[email protected]!/chrome/locale/de/
All it take is a temp file to hold the manifest contents. After add or remove content to it we could use
Cc["@mozilla.org/chrome/chrome-registry;1"].getService(
Ci.nsIXULChromeRegistry
).checkForNewChrome()
to let the edits take effect.
test this utils.zip
I replaced
Components.manager.addBootstrappedManifestLocation(file)with:const addonManagerStartup = Cc["@mozilla.org/addons/addon-manager-startup;1"] .getService(Ci.amIAddonManagerStartup); const manifestURI = getURIForResourceInFile(file, 'chrome.manifest'); const chromeEntries = await parseManifestEntries(manifestURI) this.chromeRegistryHandle = addonManagerStartup.registerChrome(manifestURI, chromeEntries);
parseManifestEntriesis in new fileParseManifestEntries.sys.mjsnotice that
amIAddonManagerStartup.registerChromedoes not supportskinentry fromchrome.manifest/** * Registers a set of dynamic chrome registry entries, and returns an object * with a `destruct()` method which must be called in order to unregister * the entries. * * @param manifestURI The base manifest URI for the entries. URL values are * resolved relative to this URI. * @param entries An array of arrays, each containing a registry entry as it * would appar in a chrome.manifest file. Only the following entry * types are currently accepted: * * - "locale" A locale package entry. Must be a 4-element array. * - "override" A URL override entry. Must be a 3-element array. */In
Tab Mix PlusI had to replace allskinentries with onecontententries
- content tabmix-skin chrome/skin/
skin tabmixplus classic/1.0 chrome/skin/
skin tabmix-version tabmixplus chrome/skin/app_version/91/ platformversion>=91
skin tabmix-version tabmixplus chrome/skin/app_version/119/ platformversion>=119
skin tabmix-os classic/1.0 chrome://tabmix-version/skin/win/ os=WINNT
skin tabmix-os classic/1.0 chrome://tabmix-version/skin/mac/ os=Darwin
skin tabmix-os classic/1.0 chrome://tabmix-version/skin/linux/ os=Linux
@onemen Don't do this.
Use autoRegister() parse relative path to absolute path and write to temp file for load and unload.
Don't change any bit on addon's side. Don't change any bit on addon's side.
@onemen Use this
Put into the utils and replace bootstraploader. Mind the file name.
No change to the addons.
You'll need a path under utils called addonManifest to host the manifest files.
Temporary files will be deleted on app exit.
@117649
On My Windows 11 pc, when Firefox start cold, and {dc572301-7619-498c-a57d-39143191b318}.manifest does not exist
i get this error:
Could not read chrome manifest 'file:///C:/Users/_______/AppData/Roaming/Mozilla/Firefox/Profiles/40xnlurj.Default%20Nightly%202025/chrome/utils/addonManifest/%7Bdc572301-7619-498c-a57d-39143191b318%7D.manifest'.
the file is created.
Edit:
look like adding timestamp to the file name solved this issue
I also moved the temp manifest to browser-extension-data directory in the profile
let tempDir = Services.dirsvc.get("ProfD", Ci.nsIFile)
tempDir.append("browser-extension-data");
tempDir.append(addon.id);
tempDir.append("temp.manifest." + Date.now());
can we use
Components.manager .QueryInterface(Ci.nsIComponentRegistrar) .autoUnRegister(tempDir);
on exit instead of checkForNewChrome ?
@117649
On My Windows 11 pc, when Firefox start cold, and {dc572301-7619-498c-a57d-39143191b318}.manifest does not exist i get this error:
Could not read chrome manifest 'file:///C:/Users/_______/AppData/Roaming/Mozilla/Firefox/Profiles/40xnlurj.Default%20Nightly%202025/chrome/utils/addonManifest/%7Bdc572301-7619-498c-a57d-39143191b318%7D.manifest'.the file is created.
Edit:
look like adding timestamp to the file name solved this issue I also moved the temp manifest to
browser-extension-datadirectory in the profilelet tempDir = Services.dirsvc.get("ProfD", Ci.nsIFile) tempDir.append("browser-extension-data"); tempDir.append(addon.id); tempDir.append("temp.manifest." + Date.now());can we use
Components.manager .QueryInterface(Ci.nsIComponentRegistrar) .autoUnRegister(tempDir);on exit instead ofcheckForNewChrome?
Didn't saw that method before need test. And I also not sure will autoregister check extension name or not if tested and success then it's fine. I'm also not understanding the need to have all the version of temp file by timestamp. If separating by sub path is works for you, you can just have a 'chrome.manifest' inside every and reuse it every time.
@117649
when i use
function createManifestTemporarily(manifestText) {
let tempDir = Services.dirsvc.get("ProfD", Ci.nsIFile)
tempDir.append("browser-extension-data");
tempDir.append(addon.id);
tempDir.append("temp.manifest");
let foStream = Cc[
"@mozilla.org/network/file-output-stream;1"
].createInstance(Ci.nsIFileOutputStream);
foStream.init(tempDir, 0x02 | 0x08 | 0x20, 0o664, 0); // write, create, truncate
foStream.write(manifestText, manifestText.length);
foStream.close();
Components.manager
.QueryInterface(Ci.nsIComponentRegistrar)
.autoRegister(tempDir);
Cc["@mozilla.org/uriloader/external-helper-app-service;1"]
.getService(Ci.nsPIExternalAppLauncher)
.deleteTemporaryFileOnExit(tempDir);
return function () {
tempDir.fileSize = 0; // truncate the manifest
Cc["@mozilla.org/chrome/chrome-registry;1"]
.getService(Ci.nsIXULChromeRegistry)
.checkForNewChrome();
};
}
I get this error when Firefox start
Could not read chrome manifest 'file:///C:/Users/___/AppData/Roaming/Mozilla/Firefox/Profiles/40xnlurj.Default%20Nightly%202025/browser-extension-data/%7Bdc572301-7619-498c-a57d-39143191b318%7D/temp.manifest'.
changing
- tempDir.append("temp.manifest");
+ tempDir.append("temp.manifest." + Date.now());
solve this problem, I guess it is cache issue
regarding autoUnregister read this
regarding autoUnregister read this
And no result on https://searchfox.org/mozilla-central/search?q=autoUnregister&path=&case=false®exp=false
This method seems to be long gone unlucky for us.
This is working fine to restore the two legacy addons installed but there is one bug: if you close the browser and re-open it the addons are no longer functional. The remedy is to delete the startupCache folder each time before re-opening.
This is working fine to restore the two legacy addons installed but there is one bug: if you close the browser and re-open it the addons are no longer functional. The remedy is to delete the startupCache folder each time before re-opening.
@onemen @marty60 See if that still happens if un-comment those 'nglayout.debug.disable_xul_cache' uses.
@onemen @marty60 See if that still happens if un-comment those 'nglayout.debug.disable_xul_cache' uses.
Is this the line you're referring to in bootstrapLoader:
const XUL_CACHE_PREF = "nglayout.debug.disable_xul_cache";
It was deleted but had no effect.
@onemen @marty60 Add a
Cc["@mozilla.org/chrome/chrome-registry;1"]
.getService(Ci.nsIXULChromeRegistry)
.checkForNewChrome();
somewhere before autoRegister() seems has effect.
Cc["@mozilla.org/chrome/chrome-registry;1"] .getService(Ci.nsIXULChromeRegistry) .checkForNewChrome();
somewhere before
autoRegister()seems has effect.
Does not work for me
@onemen @marty60 Add a Cc["@mozilla.org/chrome/chrome-registry;1"] .getService(Ci.nsIXULChromeRegistry) .checkForNewChrome(); somewhere before
autoRegister()seems has effect.Does not work for me
Didn't work for me either.
Don't dodeleteTemporaryFileOnExit(tempFile) for now?
let tempDir = Services.dirsvc.get("ProfD", Ci.nsIFile)
tempDir.append("browser-extension-data");
tempDir.append(addon.id);
function createManifestTemporarily(manifestText) {
let tempFile = tempDir.clone();
tempFile.append("chrome.manifest");
let foStream = Cc[
"@mozilla.org/network/file-output-stream;1"
].createInstance(Ci.nsIFileOutputStream);
foStream.init(tempFile, 0x02 | 0x08 | 0x20, 0o664, 0); // write, create, truncate
foStream.write(manifestText, manifestText.length);
foStream.close();
Components.manager
.QueryInterface(Ci.nsIComponentRegistrar)
.autoRegister(tempFile);
// Cc["@mozilla.org/uriloader/external-helper-app-service;1"]
// .getService(Ci.nsPIExternalAppLauncher)
// .deleteTemporaryFileOnExit(tempFile);
return function () {
tempFile.fileSize = 0; // truncate the manifest
Cc["@mozilla.org/chrome/chrome-registry;1"]
.getService(Ci.nsIXULChromeRegistry)
.checkForNewChrome();
};
}
If we are using "browser-extension-data" why bother to delete manifest every time.
Don't do
deleteTemporaryFileOnExit(tempFile)for now?
If we are using "browser-extension-data" why bother to delete manifest every time.
That resolved it on my end. The manifest files are extremely small so can't see a problem not deleting them but that's just me. Doubtful anyone would even notice as long as they can use their legacy addons.
@117649
why not simply create a unique filename with timestamp?
- tempFile.append("chrome.manifest");
+ tempFile.append("temp.manifest." + Date.now());
@117649 ,
Maybe we does not need to create temp manifest at all
this code work with Tab Mix Plus
Can you test it
BootstrapLoader.js
startup(...args) {
if (addon.type == 'extension') {
logger.debug(`Registering manifest for ${file.path}\n`);
let manifest = file.clone();
manifest.append("chrome.manifest");
Components.manager.QueryInterface(Ci.nsIComponentRegistrar)
.autoRegister(manifest);
}
return startup(...args);
},
shutdown(data, reason) {
try {
return shutdown(data, reason);
} catch (err) {
throw err;
} finally {
if (reason != BOOTSTRAP_REASONS.APP_SHUTDOWN) {
logger.debug(`Removing manifest for ${file.path}\n`);
Cc["@mozilla.org/chrome/chrome-registry;1"].getService(Ci.nsIXULChromeRegistry)
.checkForNewChrome();
}
}
},
why not simply create a unique filename with timestamp?
- tempFile.append("chrome.manifest");
- tempFile.append("temp.manifest." + Date.now());
I don't know, what happens if you start browser at yesterday then update the addon at the next day? What if browser crashed then reopened at next day?
@117649 ,
Maybe we does not need to create temp manifest at all this code work with
Tab Mix PlusCan you test it
BootstrapLoader.jsstartup(...args) { if (addon.type == 'extension') { logger.debug(`Registering manifest for ${file.path}\n`); let manifest = file.clone(); manifest.append("chrome.manifest"); Components.manager.QueryInterface(Ci.nsIComponentRegistrar) .autoRegister(manifest); } return startup(...args); }, shutdown(data, reason) { try { return shutdown(data, reason); } catch (err) { throw err; } finally { if (reason != BOOTSTRAP_REASONS.APP_SHUTDOWN) { logger.debug(`Removing manifest for ${file.path}\n`); Cc["@mozilla.org/chrome/chrome-registry;1"].getService(Ci.nsIXULChromeRegistry) .checkForNewChrome(); } } },
I'm stay on win10. Where you put your TMP's source? Are they in a '.xpi'?
Where you put your TMP's source? Are they in a '.xpi'?
You are right my code does not work for xpi.
@117649 why not simply create a unique filename with timestamp?
tempFile.append("chrome.manifest");
tempFile.append("temp.manifest." + Date.now());
I don't know, what happens if you start browser at yesterday then update the addon at the next day? What if browser crashed then reopened at next day?
we can make sure to remove all leftover "temp.manifest" before creating the new one. in this way we can bypass cache without changing user preferences.
function createManifestTemporarily(manifestText) {
let tempDir = Services.dirsvc.get("ProfD", Ci.nsIFile)
tempDir.append("browser-extension-data");
tempDir.append(addon.id);
tempDir.append("manifests");
if (tempDir.exists()) {
// Clean any leftover temp.manifest
tempDir.remove(true);
}
tempDir.append("temp.manifest." + Date.now());
let foStream = Cc[
"@mozilla.org/network/file-output-stream;1"
].createInstance(Ci.nsIFileOutputStream);
foStream.init(tempDir, 0x02 | 0x08 | 0x20, 0o664, 0); // write, create, truncate
foStream.write(manifestText, manifestText.length);
foStream.close();
Components.manager
.QueryInterface(Ci.nsIComponentRegistrar)
.autoRegister(tempDir);
Cc["@mozilla.org/uriloader/external-helper-app-service;1"]
.getService(Ci.nsPIExternalAppLauncher)
.deleteTemporaryFileOnExit(tempDir);
return function () {
tempDir.fileSize = 0; // truncate the manifest
Cc["@mozilla.org/chrome/chrome-registry;1"]
.getService(Ci.nsIXULChromeRegistry)
.checkForNewChrome();
};
}
we can make sure to remove all leftover "temp.manifest" before creating the new one. in this way we can bypass cache without changing user preferences.
Of course.
This is updated version of utils for Firefox 142+
This version is compatible with all Firefox version.
All users must update replace the utils files with the new version before Firefox 142 release