summaryrefslogtreecommitdiffstats
path: root/toolkit/jetpack/sdk/addon/runner.js
diff options
context:
space:
mode:
Diffstat (limited to 'toolkit/jetpack/sdk/addon/runner.js')
-rw-r--r--toolkit/jetpack/sdk/addon/runner.js180
1 files changed, 180 insertions, 0 deletions
diff --git a/toolkit/jetpack/sdk/addon/runner.js b/toolkit/jetpack/sdk/addon/runner.js
new file mode 100644
index 000000000..3977a04e4
--- /dev/null
+++ b/toolkit/jetpack/sdk/addon/runner.js
@@ -0,0 +1,180 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+module.metadata = {
+ "stability": "experimental"
+};
+
+const { Cc, Ci, Cu } = require('chrome');
+const { rootURI, metadata, isNative } = require('@loader/options');
+const { id, loadReason } = require('../self');
+const { descriptor, Sandbox, evaluate, main, resolveURI } = require('toolkit/loader');
+const { once } = require('../system/events');
+const { exit, env, staticArgs } = require('../system');
+const { when: unload } = require('../system/unload');
+const globals = require('../system/globals');
+const xulApp = require('../system/xul-app');
+const { get } = require('../preferences/service');
+const appShellService = Cc['@mozilla.org/appshell/appShellService;1'].
+ getService(Ci.nsIAppShellService);
+const { preferences } = metadata;
+
+const Startup = Cu.import("resource://gre/modules/sdk/system/Startup.js", {}).exports;
+
+Cu.import("resource://gre/modules/XPCOMUtils.jsm");
+XPCOMUtils.defineLazyGetter(this, "BrowserToolboxProcess", function () {
+ return Cu.import("resource://devtools/client/framework/ToolboxProcess.jsm", {}).
+ BrowserToolboxProcess;
+});
+
+// Initializes default preferences
+function setDefaultPrefs(prefsURI) {
+ const prefs = Cc['@mozilla.org/preferences-service;1'].
+ getService(Ci.nsIPrefService).
+ QueryInterface(Ci.nsIPrefBranch2);
+ const branch = prefs.getDefaultBranch('');
+ const sandbox = Sandbox({
+ name: prefsURI,
+ prototype: {
+ pref: function(key, val) {
+ switch (typeof val) {
+ case 'boolean':
+ branch.setBoolPref(key, val);
+ break;
+ case 'number':
+ if (val % 1 == 0) // number must be a integer, otherwise ignore it
+ branch.setIntPref(key, val);
+ break;
+ case 'string':
+ branch.setCharPref(key, val);
+ break;
+ }
+ }
+ }
+ });
+ // load preferences.
+ evaluate(sandbox, prefsURI);
+}
+
+function definePseudo(loader, id, exports) {
+ let uri = resolveURI(id, loader.mapping);
+ loader.modules[uri] = { exports: exports };
+}
+
+function startup(reason, options) {
+ return Startup.onceInitialized.then(() => {
+ // Inject globals ASAP in order to have console API working ASAP
+ Object.defineProperties(options.loader.globals, descriptor(globals));
+
+ // NOTE: Module is intentionally required only now because it relies
+ // on existence of hidden window, which does not exists until startup.
+ let { ready } = require('../addon/window');
+ // Load localization manifest and .properties files.
+ // Run the addon even in case of error (best effort approach)
+ require('../l10n/loader').
+ load(rootURI).
+ then(null, function failure(error) {
+ if (!isNative)
+ console.info("Error while loading localization: " + error.message);
+ }).
+ then(function onLocalizationReady(data) {
+ // Exports data to a pseudo module so that api-utils/l10n/core
+ // can get access to it
+ definePseudo(options.loader, '@l10n/data', data ? data : null);
+ return ready;
+ }).then(function() {
+ run(options);
+ }).then(null, console.exception);
+ return void 0; // otherwise we raise a warning, see bug 910304
+ });
+}
+
+function run(options) {
+ try {
+ // Try initializing HTML localization before running main module. Just print
+ // an exception in case of error, instead of preventing addon to be run.
+ try {
+ // Do not enable HTML localization while running test as it is hard to
+ // disable. Because unit tests are evaluated in a another Loader who
+ // doesn't have access to this current loader.
+ if (options.main !== 'sdk/test/runner') {
+ require('../l10n/html').enable();
+ }
+ }
+ catch(error) {
+ console.exception(error);
+ }
+
+ // native-options does stuff directly with preferences key from package.json
+ if (preferences && preferences.length > 0) {
+ try {
+ require('../preferences/native-options').
+ enable({ preferences: preferences, id: id }).
+ catch(console.exception);
+ }
+ catch (error) {
+ console.exception(error);
+ }
+ }
+ else {
+ // keeping support for addons packaged with older SDK versions,
+ // when cfx didn't include the 'preferences' key in @loader/options
+
+ // Initialize inline options localization, without preventing addon to be
+ // run in case of error
+ try {
+ require('../l10n/prefs').enable();
+ }
+ catch(error) {
+ console.exception(error);
+ }
+
+ // TODO: When bug 564675 is implemented this will no longer be needed
+ // Always set the default prefs, because they disappear on restart
+ if (options.prefsURI) {
+ // Only set if `prefsURI` specified
+ try {
+ setDefaultPrefs(options.prefsURI);
+ }
+ catch (err) {
+ // cfx bootstrap always passes prefsURI, even in addons without prefs
+ }
+ }
+ }
+
+ // this is where the addon's main.js finally run.
+ let program = main(options.loader, options.main);
+
+ if (typeof(program.onUnload) === 'function')
+ unload(program.onUnload);
+
+ if (typeof(program.main) === 'function') {
+ program.main({
+ loadReason: loadReason,
+ staticArgs: staticArgs
+ }, {
+ print: function print(_) { dump(_ + '\n') },
+ quit: exit
+ });
+ }
+
+ if (get("extensions." + id + ".sdk.debug.show", false)) {
+ BrowserToolboxProcess.init({ addonID: id });
+ }
+ } catch (error) {
+ console.exception(error);
+ throw error;
+ }
+}
+exports.startup = startup;
+
+// If add-on is lunched via `cfx run` we need to use `system.exit` to let
+// cfx know we're done (`cfx test` will take care of exit so we don't do
+// anything here).
+if (env.CFX_COMMAND === 'run') {
+ unload(function(reason) {
+ if (reason === 'shutdown')
+ exit(0);
+ });
+}