A Firefox WebExtension Experiment addon to provide unrestricted legacy addon functionality to WebExtension addons.
By policy and design, WebExtensions are more restricted than the legacy addons they are intended to replace. This means that some of the functionality that legacy addons could provide is no longer possible to do as a WebExtension.
This addon should be regarded as similar to jailbreaking or rooting your phone. It is expressely bypassing the restrictions and permissions for WebExtensions for addons that use it. Needless to say, if an addon requires you to install this helper, only do so if you trust that addon completely!
This addon can only be installed in Firefox Developer Edition or Nightly. First, set the extensions.legacy.enabled
and xpinstall.signatures.required
preferences in about:config
to true
(Mozilla will not sign experiments). Then install LegacyHelper.xpi from Latest Release.
Other addons may depend on this addon for their functionality. It does nothing on its own, and only needs to be installed if another addon has requested it.
To use the Legacy Helper from your own addon, include in the manifest.json
permissions array the permission: experiments.legacyHelper
. For example:
"permissions": [
"experiments.legacyHelper"
]
All legacy code must be in its own, separate, script files. These can be loaded either as framescripts (content) or as bootstrap (background) scripts.
Legacy framescripts (for the content process) are loaded using the loadFrameScript(uri, allowDelayedLoad, [optional] runInGlobalScope)
function. If the allowDelayedLoad
parameter is set true, then removeDelayedFrameScript
will automatically be called when the addon is unloaded.
browser.legacy.loadFrameScript(browser.runtime.getURL("content.js"), true);
If the runInGlobalScope
is true then the frame script scope will be shared with other frame scripts that have this flag set true.
Messages may be broadcast to all legacy framescripts using the broadcastAsyncMessage
function.
Legacy bootstrap scripts (for the chrome process) are loaded using the loadBootstrapScript(uri)
function. There is no requirement for it to be named bootstrap.js. Once loaded, the startup(data, reason, messageSender)
function will be called. When the addon is unloaded, shutdown(data, reason)
will be called.
If this function is called again for the same script uri, it won't be re-loaded, but startup()
will be called again.
The reason
parameters is passed as a string rather than a constant. The possible strings are:
"APP_STARTUP"
"APP_SHUTDOWN"
"ADDON_ENABLE"
"ADDON_DISABLE"
"ADDON_INSTALL"
"ADDON_UNINSTALL"
"ADDON_UPGRADE"
"ADDON_DOWNGRADE"
The messageSender
parameter passed to startup
can be used to send a message back to the WebExtension by calling messageSender.sendMessage(message)
. This will be raised by the onBootstrapScriptMessage
event, so the WebExtension may listen for it using browser.legacy.onBootstrapScriptMessage.addListener(listener)
. A response to the message may be returned as a Promise
.
Legacy style sheets are loaded using the loadStyleSheet(uri, type)
function. The type
paramter should be one of browser.legacy.AGENT_SHEET
, browser.legacy.USER_SHEET
or browser.legacy.AUTHOR_SHEET
. Style sheets will be automatically unloaded when the addon is unloaded.
Additional helper functions: isStyleSheetLoaded(uri, type)
and unloadStyleSheet(uri, type)
are also provided.
Addons used to be able to place files within a chrome folder. This functionality can be reproduced by calling registerChromeOverride(path, [optional] reloadSession)
and passing the path to the chrome folder, relative to the addon root.
browser.legacy.registerChromeOverride("chrome", true);
If the addon is packed in an .xpi file, it will be automatically extracted into the system temp folder so that the chrome files can be accessed by Firefox. The temporary folder will be automatically deleted when the addon is unloaded, or Firefox is closed.
Unfortunately, at the current time, the main window is loaded before addons have a chance to execute, so overrides will not apply to the first open window. To work around this, the open windows can be reloaded (using the session manager) by passing true for the reloadSession
parameter.
Delayed framescripts are automatically removed, but it is not possible to unload a framescript that has already been loaded into a tab. Accepted practice is to broadcast a message which notifies the framescripts to disable themselves. To assist with this, an addUnloadMessage(messageName, data)
function is provided. When the addon is unloaded, this message will be broadcast to all framescripts.
For bootstrap scripts, the shutdown
function will be called.
Style sheets will be automatcially unloaded.
Chrome overrides will be automatically removed.
//background.js
browser.legacy.loadBootstrapScript(browser.runtime.getURL("bootstrap.js"));
browser.legacy.loadFrameScript(browser.runtime.getURL("content.js"), true);
browser.legacy.addUnloadMessage("myAddonDisableMessage");
//content.js:
addMessageListener("myAddonDisableMessage", function () {
// clean up framescript
});
//bootstrap.js
shutdown() {
// clean up bootstrap script
}