1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
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);
}
});
|