The ability of developers using the SDK to get chrome authority and access xpcom services is a key feature. The SDK was designed from the start with the assumption that some developers will always need access to the underlying Mozilla platform. While xpcom is the main way to access low level apis, a lot of functionality in Firefox is instead implemented as JavaScript Modules, and can be used in your code much more naturally than xpcom services because they are just JavaScript, and from a design perspective quite similar to CommonJS modules.
Here’s a code snippet that you can use to import a jsm into your code:
const { Cu } = require("chrome");
let AddonManager = Cu.import("resource://gre/modules/AddonManager.jsm").AddonManager;
AddonManager.getAddonsByTypes(["extension"], function(addons) {
var addonData = [];
for (let i in addons) {
let cur = addons[i];
addonData.push({
id: cur.id.toString(),
name: cur.name,
});
};
console.log(JSON.stringify(addonData, null, ' '));
});
The code requires chrome in order to get the Cu object ( Components.Utils ) and then imports the AddonManager module. Nice and easy! The only real problem with adding code like this to your add-on is that getting chrome authority to access Cu has review implications on AMO, and we in the Jetpack team want to do everything we can to get your add-ons reviewed as quickly as possible.
With that in mind, we have been considering including a utility function in the SDK that allows developers to import jsm modules without having to get chrome authority. Ben Buksch contributed this code snippet in a bug that neatly abstracts the small amount of chrome-level code into a single function:
const { Cu } = require("chrome");
/**
* Imports a JS Module using Components.utils.import()
* and returns the scope, similar to Jetpack require().
*
* @param targetScope {Object} (optional)
* If null, the scope will just be returned
* and *not* added to the global scope.
* If given, all functions/objects from the JSM will be
* imported directly in |targetScope|, so that you
* can do e.g.
* requireJSM("url", this)
* someFuncFromJSM();
* which will have the same effect as
* Components.utils.import("url");
* someFuncFromJSM();
* in normal Mozilla code, but the latter won't work in Jetpack code.
*/
function requireJSM(url, targetScope)
{
var scope = targetScope ? targetScope : {};
return Cu.import(url, scope);
return scope;
}
I’ve created a Jetpack module on Builder that you can use to load Javascript modules using Ben’s code:
https://builder.addons.mozilla.org/library/1040049/latest
I’ve also created this example addon that uses my module:
https://builder.addons.mozilla.org/addon/1040048/latest/
Here is the above code, re-factored to use my module:
let requireJSM = require("jsmutils/jsmutils").requireJSM;
let AddonManager = requireJSM("resource://gre/modules/AddonManager.jsm").AddonManager;
AddonManager.getAddonsByTypes(["extension"], function(addons) {
var addonData = [];
for (let i in addons) {
let cur = addons[i];
addonData.push({
id: cur.id.toString(),
name: cur.name,
});
};
console.log(JSON.stringify(addonData, null, ' '));
});
I know what you’re thinking – there isn’t really any less code involved using the abstracted module. I would argue that the advantage is instead that I have isolated the part of my code that needs chrome authority to a single, small file that is very easy to understand. This is better separation and greatly aids the ability of our add-on reviewers to quickly understand your code and any security implications it might have.
jonathan wrote on
Jeff Griffiths wrote on
Ben Bucksch wrote on
Plz update code & link wrote on
Jeff Griffiths wrote on
Ben Bucksch wrote on
Jeff Griffiths wrote on