Chrome Authority
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 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 "cfx xpi
" or "cfx 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.