gecko-dev/mobile/android/modules/JavaAddonManager.jsm

116 lines
3.4 KiB
JavaScript

// -*- 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);
}
});