Convert wrapped WebExtensions to modern WebExtensions
After legacy WebExtensions had been deprecated in Thunderbird 78, the Thunderbird team provided two so-called wrapper Experiments (the WindowListener
Experiment and the BootstrapLoader
Experiment), which re-implemented the loading framework of legacy extensions and required only little changes for add-ons to be usable in Thunderbird 78. This mechanism was intended as an intermediate solution.
This document describes how to remove the wrapper Experiment and how to properly convert a legacy extension to a modern WebExtension.
If you need any help, get in touch with the add-on developer community:
Developer CommunityConverting a wrapped WebExtension into a modern WebExtension will be a complex task: almost all interactions with Thunderbird will need to be re-written to use the new APIs. If these APIs are not yet sufficient for your add-on, you may even need to implement additional Experiment APIs yourself. Don't worry though: you can find information on all aspects of the migration process below, including links to many advanced topics.
Before working on an update, it is advised to read some information about the WebExtension technology first. Our Extension guide and our "Hello World" Extension Tutorial are good starting points.
The guide assumes that the background script is loaded as a module.
Wrapped WebExtensions have a background script similar to the following:
Step 1: Replace registerDefaultPrefs()
registerDefaultPrefs()
Most legacy extensions stored their preferences in an nsIPrefBranch
, and the registerDefaultPrefs()
function loaded a JavaScript file with default preference values. An example default preference file could look like this:
This file and the associated call to registerDefaultPrefs()
can be removed, and the default values must be set in the background script through the LegacyPrefs Experiment:
We can now use the LegacyPrefs Experiment to access existing preferences, for example the preference entry at extensions.myaddon.enableDebug
can be read from any WebExtension script via:
Modern WebExtension should eventually use browser.storage.local.* for their preferences, but to simplify the conversion process, we will keep using the nsIPrefBranch
for now. The very last conversion step will migrate the preferences.
Step 2: Replace registerChromeUrl()
registerChromeUrl()
We will keep registering global legacy chrome://
or resource://
URLs, but we will use the LegacyHelper Experiment. Use the registerGlobalUrls()
function of the LegacyHelper Experiment instead of the registerChromeUrl()
function of the wrapper Experiment. For example:
Step 3: Replace registerOptionsPage()
registerOptionsPage()
Modern WebExtensions show their options in an HTML page in a tab or in a frame inside the Add-on Manger. The wrapper APIs instead allowed to register a legacy XUL dialog to be opened when the wrench icon in the add-on card of the Add-on Manger was clicked. This has to be removed to allow that wrench icon to show the standard WebExtension HTML options page.
In this step, we will create a menu entry on the tools
menu to open the XUL options dialog via the LegacyHelper Experiment:
This will be removed after the XUL options dialog has been converted to a standard WebExtension HTML options page.
Step 4: Remove the wrapper API
This step will interrupt the main functionality of your add-on. Remove the registration for the wrapper Experiment from manifest.json
, remove its implementation and schema files and any usage from your background script. The only remaining working part of your add-on should now be your XUL options dialog.
Please continue at step 5 of the conversion from legacy WebExtensions to modern WebExtensions.
Last updated