Add-ons using the techniques described in this document are considered a legacy technology in Firefox. Don't use these techniques to develop new add-ons. Use WebExtensions instead. If you maintain an add-on which uses the techniques described here, consider migrating it to use WebExtensions.
From Firefox 53 onwards, no new legacy add-ons will be accepted on addons.mozilla.org (AMO).
From Firefox 57 onwards, WebExtensions will be the only supported extension type, and Firefox will not load other types.
Even before Firefox 57, changes coming up in the Firefox platform will break many legacy extensions. These changes include multiprocess Firefox (e10s), sandboxing, and multiple content processes. Legacy extensions that are affected by these changes should migrate to WebExtensions if they can. See the "Compatibility Milestones" document for more.
A wiki page containing resources, migration paths, office hours, and more, is available to help developers transition to the new technologies.
The API used to gain Chrome access is currently an experimental feature of the SDK, and may change in future releases.
Using Chrome Authority
The most powerful low-level modules are run with "chrome privileges", which gives them access to the infamous Components
object, which grants unfettered access to the host system. From this, the module can do pretty much anything the browser is capable of. To obtain these privileges, the module must declare its intent with a statement like the following:
var {Cc, Ci} = require("chrome");
The "chrome" built-in pseudo module is provided by the "toolkit/loader" module.
The object returned by require("chrome")
, when unpacked with the destructuring assignment feature available in the Mozilla JS environment, will provide the usual Components.*
aliases:
Cc
An alias for Components.classes
.
Ci
An alias for Components.interfaces
.
Cu
An alias for Components.utils
.
Cr
An alias for Components.results
.
Cm
An alias for Components.manager
.
components
An alias for Components
itself (note the lower-case). From this you can access less-frequently-used properties like Components.stack
and Components.isSuccessCode
.
Note: the require("chrome")
statement is the only way to access chrome functionality and the Components
API. The Components
object should not be accessed from modules. The SDK tools will emit a warning if it sees module code which references Components
directly.
Your modules should refrain from using chrome privileges unless they are absolutely necessary. Chrome-authority-using modules must receive extra security review, and most bugs in these modules are security-critical.
Manifest Generation
The manifest is a list, included in the generated XPI, which specifies which modules have requested require()
access to which other modules. It also records which modules have requested chrome access. This list is generated by scanning all included modules for require(XYZ)
statements and recording the particular "XYZ" strings that they reference.
When the manifest implementation is complete the runtime loader will actually prevent modules from require()
ing modules that are not listed in the manifest. Likewise, it will prevent modules from getting chrome authority unless the manifest indicates that they have asked for it. This will ensure that reviewers see the same authority restrictions that are enforced upon the running code, increasing the effectiveness of the time spent reviewing the add-on. (until this work is complete, modules may be able to sneak around these restrictions).
The manifest is built with a simple regexp-based scanner, not a full Javascript parser. Developers should stick to simple require
statements, with a single static string, one per line of code. If the scanner fails to see a require
entry, the manifest will not include that entry, and (once the implementation is complete) the runtime code will get an exception.
For example, none of the following code will be matched by the manifest scanner, leading to exceptions at runtime, when the require()
call is prohibited from importing the named modules:
// all of these will fail! var xhr = require("x"+"hr"); var modname = "xpcom"; var xpcom = require(modname); var one = require("one"); var two = require("two");
The intention is that developers use require()
statements for two purposes: to declare (to security reviewers) what sorts of powers the module wants to use, and to control how those powers are mapped into the module's local namespace. Their statements must therefore be clear and easy to parse. A future manifest format may move the declaration portion out to a separate file, to allow for more fine-grained expression of authority.
Commands that build a manifest, like "jpm xpi
" or "jpm run
", will scan all included modules for use of Cc
/Ci
aliases (or the expanded Components.classes
forms). It will emit a warning if it sees the expanded forms, or if it sees a use of e.g. "Cc
" without a corresponding entry in the require("chrome")
statement. These warnings will serve to guide developers to use the correct pattern. All module developers should heed the warnings and correct their code until the warnings go away.