diff options
Diffstat (limited to 'mobile/android/modules/JavaAddonManager.jsm')
-rw-r--r-- | mobile/android/modules/JavaAddonManager.jsm | 115 |
1 files changed, 115 insertions, 0 deletions
diff --git a/mobile/android/modules/JavaAddonManager.jsm b/mobile/android/modules/JavaAddonManager.jsm new file mode 100644 index 000000000..a24535ede --- /dev/null +++ b/mobile/android/modules/JavaAddonManager.jsm @@ -0,0 +1,115 @@ +// -*- Mode: js2; tab-width: 2; indent-tabs-mode: nil; js2-basic-offset: 2; js2-skip-preprocessor-directives: t; -*- +/* 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/. */ + +"use strict"; + +this.EXPORTED_SYMBOLS = ["JavaAddonManager"]; + +const { classes: Cc, interfaces: Ci, utils: Cu } = Components; /*global Components */ + +Cu.import("resource://gre/modules/Messaging.jsm"); /*global Messaging */ +Cu.import("resource://gre/modules/Services.jsm"); /*global Services */ + +function resolveGeckoURI(uri) { + if (!uri) { + throw new Error("Can't resolve an empty uri"); + } + if (uri.startsWith("chrome://")) { + let registry = Cc['@mozilla.org/chrome/chrome-registry;1'].getService(Ci["nsIChromeRegistry"]); + return registry.convertChromeURL(Services.io.newURI(uri, null, null)).spec; + } else if (uri.startsWith("resource://")) { + let handler = Services.io.getProtocolHandler("resource").QueryInterface(Ci.nsIResProtocolHandler); + return handler.resolveURI(Services.io.newURI(uri, null, null)); + } + return uri; +} + +/** + * A promise-based API + */ +var JavaAddonManager = Object.freeze({ + classInstanceFromFile: function(classname, filename) { + if (!classname) { + throw new Error("classname cannot be null"); + } + if (!filename) { + throw new Error("filename cannot be null"); + } + return Messaging.sendRequestForResult({ + type: "JavaAddonManagerV1:Load", + classname: classname, + filename: resolveGeckoURI(filename) + }) + .then((guid) => { + if (!guid) { + throw new Error("Internal error: guid should not be null"); + } + return new JavaAddonV1({classname: classname, guid: guid}); + }); + } +}); + +function JavaAddonV1(options = {}) { + if (!(this instanceof JavaAddonV1)) { + return new JavaAddonV1(options); + } + if (!options.classname) { + throw new Error("options.classname cannot be null"); + } + if (!options.guid) { + throw new Error("options.guid cannot be null"); + } + this._classname = options.classname; + this._guid = options.guid; + this._loaded = true; + this._listeners = {}; +} + +JavaAddonV1.prototype = Object.freeze({ + unload: function() { + if (!this._loaded) { + return; + } + + Messaging.sendRequestForResult({ + type: "JavaAddonManagerV1:Unload", + guid: this._guid + }) + .then(() => { + this._loaded = false; + for (let listener of this._listeners) { + // If we use this.removeListener, we prefix twice. + Messaging.removeListener(listener); + } + this._listeners = {}; + }); + }, + + _prefix: function(message) { + let newMessage = Cu.cloneInto(message, {}, { cloneFunctions: false }); + newMessage.type = this._guid + ":" + message.type; + return newMessage; + }, + + sendRequest: function(message) { + return Messaging.sendRequest(this._prefix(message)); + }, + + sendRequestForResult: function(message) { + return Messaging.sendRequestForResult(this._prefix(message)); + }, + + addListener: function(listener, message) { + let prefixedMessage = this._guid + ":" + message; + this._listeners[prefixedMessage] = listener; + return Messaging.addListener(listener, prefixedMessage); + }, + + removeListener: function(message) { + let prefixedMessage = this._guid + ":" + message; + delete this._listeners[prefixedMessage]; + return Messaging.removeListener(prefixedMessage); + } +}); |