This article is a technical comparison between the WebExtensions technology and "classic" extensions developed using direct XUL manipulation and direct access to XPCOM. It's intended to help orient people who maintain an add-on like this, and who are planning to port it to use WebExtension APIs.
At a very basic level, XUL/XPCOM extensions are similar to extensions developed with WebExtensions. They both include:
- manifest files defining metadata for the extension and some aspects of its behavior.
- the ability to add specific UI elements, such as buttons, to the browser.
Beyond that, though, the systems are very different. In particular:
- WebExtensions can only access web content by injecting separate scripts into web pages and communicating with them using a messaging API (note, though, that this is also true of XUL/XPCOM extensions that expect to work with multiprocess Firefox).
XUL/XPCOM extensions have two manifest files:
- the install.rdf contains metadata about the extension such as its name, icons, and so on
- the chrome.manifest, that tells Firefox where it can find the components of the extension, including XUL overlays for the extension's interface, scripts for its behavior, and files containing localized strings.
WebExtensions have a single manifest file called manifest.json, that has a similar purpose. You use it to specify the extension's name, description, icons, and so on, as well as to specify any buttons it adds to Firefox and to list scripts it needs to run. To get an overview of the components of an extension developed using WebExtension APIs, and how they are specified in manifest.json, see "Anatomy of an extension".
|Browser action||Button in the browser toolbar, with an optional popup panel.||
|Page action||Button in the URL bar, with an optional popup panel.||
|Context menu||Adds items and submenus to the browser's context menu.||
Both XUL/XPCOM extensions and extensions built with WebExtension APIs can contain scripts that stay loaded for as long as the extension itself is enabled, and that have access to a set of privileged APIs. However, XUL/XPCOM extensions get access to a much wider range of APIs.
Components object. They also get direct access to the browser's internals through globals like
window global, with all the DOM objects that are available in a normal web page.
There are vastly more APIs available to XUL/XPCOM extensions than are available to WebExtensions, and for many XUL/XPCOM APIs, there isn't a WebExtensions substitute. The table below lists every API in the popular Services.jsm module, describe what the equivalent WebExtensions API would be, if there is one.
You'll see that many APIs have no WebExtensions equivalent yet. However we are intending to extend the WebExtension APIs to support the needs of add-on developers, so if you have ideas, we'd love to hear them. You can reach us on the dev-addons mailing list or #webextensions on IRC.
Interacting with web content
Historically, XUL/XPCOM extensions have been able to get direct access to web content. For example, they can directly access and modify the page DOM using
gBrowser.contentWindow.document.querySelector("h1").innerHTML = "yadda yadda";
However, this is only possible in single-process Firefox. In multiprocess Firefox, web content and extension code run in different processes, so this direct access is no longer possible, and extensions which rely on it will break. Multiprocess Firefox is coming soon, and multiprocess compatibility will be a necessity.
XUL/XPCOM extensions can still interact with web content in multiprocess Firefox by refactoring the code that accesses web content into separate scripts called frame scripts, and using the message manager to communicate with these scripts. But this is complex and can involve deep changes to the extension's code.
WebExtensions are multiprocess-compatible by default: code that interacts with web content is factored into separate scripts called content scripts, that can communicate with the rest of the extension using a messaging API.
In a XUL/XPCOM extension you handle localization by supplying DTD or properties for each supported language, and referring to them using locale statements inside the chrome.manifest. You can then include localized strings in UI elements or in code.
The general approach with WebExtensions is similar, but the details are all different. With WebExtensions you supply localized strings as a collection of JSON files, one for each locale.
To retrieve localized strings in extension code, use the
With WebExtensions you write an HTML file that presents the settings UI, which can include a script for persisting the settings for your extension. The script gets access to all the WebExtensions APIs, and it's generally expected that you should use the
storage API to persist settings.
You then assign the HTML file's URL to the
options_ui key in manifest.json. Your settings page then appears in the extension's entry in the Add-ons Manager. The options page can also be programmatically opened with an API call to
Note that WebExtensions does not give you access to the Preferences API, so you can't directly get or set the browser's own preferences.