mobile/android/modules/JNI.jsm

Wed, 31 Dec 2014 07:22:50 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 07:22:50 +0100
branch
TOR_BUG_3246
changeset 4
fc2d59ddac77
permissions
-rw-r--r--

Correct previous dual key logic pending first delivery installment.

michael@0 1 /* Very basic JNI support for JS
michael@0 2 *
michael@0 3 * Example Usage:
michael@0 4 * let jni = new JNI();
michael@0 5 * cls = jni.findClass("org/mozilla/gecko/GeckoAppShell");
michael@0 6 * method = jni.getStaticMethodID(cls, "getPreferredIconSize", "(I)I");
michael@0 7 *
michael@0 8 * let val = jni.callStaticIntMethod(cls, method, 3);
michael@0 9 * // close the jni library when you are done
michael@0 10 * jni.close();
michael@0 11 *
michael@0 12 * Note: the getters in this file are deleted and replaced with static
michael@0 13 * values once computed, as in, for example
michael@0 14 * http://code.activestate.com/recipes/577310-using-a-getter-for-a-one-time-calculation-of-a-jav/
michael@0 15 */
michael@0 16 this.EXPORTED_SYMBOLS = ["JNI"];
michael@0 17
michael@0 18 Components.utils.import("resource://gre/modules/ctypes.jsm")
michael@0 19 Components.utils.import("resource://gre/modules/Services.jsm")
michael@0 20
michael@0 21 this.JNI = function JNI() { }
michael@0 22
michael@0 23 JNI.prototype = {
michael@0 24 get lib() {
michael@0 25 delete this.lib;
michael@0 26 return this.lib = ctypes.open("libxul.so");
michael@0 27 },
michael@0 28
michael@0 29 getType: function(aType) {
michael@0 30 switch(aType) {
michael@0 31 case "B": return ctypes.char;
michael@0 32 case "C": return ctypes.char;
michael@0 33 case "D": return ctypes.double;
michael@0 34 case "F": return ctypes.float;
michael@0 35 case "I": return ctypes.int32_t;
michael@0 36 case "J": return ctypes.int64_t;
michael@0 37 case "S": return ctypes.int16_t;
michael@0 38 case "V": return ctypes.void_t;
michael@0 39 case "Z": return ctypes.bool;
michael@0 40 default: return this.types.jobject
michael@0 41 }
michael@0 42 },
michael@0 43
michael@0 44 getArgs: function(aMethod, aArgs) {
michael@0 45 if (aArgs.length != aMethod.parameters.length)
michael@0 46 throw ("Incorrect number of arguments passed to " + aMethod.name);
michael@0 47
michael@0 48 // Convert arguments to an array of jvalue objects
michael@0 49 let modifiedArgs = new ctypes.ArrayType(this.types.jvalue, aMethod.parameters.length)();
michael@0 50 for (let i = 0; i < aMethod.parameters.length; i++) {
michael@0 51 let parameter = aMethod.parameters[i];
michael@0 52 let arg = new this.types.jvalue();
michael@0 53
michael@0 54 if (aArgs[i] instanceof Array || parameter[0] == "[")
michael@0 55 throw "No support for array arguments yet";
michael@0 56 else
michael@0 57 ctypes.cast(arg, this.getType(parameter)).value = aArgs[i];
michael@0 58
michael@0 59 modifiedArgs[i] = arg;
michael@0 60 }
michael@0 61
michael@0 62 return modifiedArgs;
michael@0 63 },
michael@0 64
michael@0 65 types: {
michael@0 66 jobject: ctypes.StructType("_jobject").ptr,
michael@0 67 jclass: ctypes.StructType("_jobject").ptr,
michael@0 68 jmethodID: ctypes.StructType("jmethodID").ptr,
michael@0 69 jvalue: ctypes.double
michael@0 70 },
michael@0 71
michael@0 72 get _findClass() {
michael@0 73 delete this._findClass;
michael@0 74 return this._findClass = this.lib.declare("jsjni_FindClass",
michael@0 75 ctypes.default_abi,
michael@0 76 this.types.jclass,
michael@0 77 ctypes.char.ptr);
michael@0 78 },
michael@0 79
michael@0 80 findClass: function(name) {
michael@0 81 let ret = this._findClass(name);
michael@0 82 if (this.exceptionCheck())
michael@0 83 throw("Can't find class " + name);
michael@0 84 return ret;
michael@0 85 },
michael@0 86
michael@0 87 get _getStaticMethodID() {
michael@0 88 delete this._getStaticMethodID;
michael@0 89 return this._getStaticMethodID = this.lib.declare("jsjni_GetStaticMethodID",
michael@0 90 ctypes.default_abi,
michael@0 91 this.types.jmethodID,
michael@0 92 this.types.jclass, // class
michael@0 93 ctypes.char.ptr, // method name
michael@0 94 ctypes.char.ptr); // signature
michael@0 95 },
michael@0 96
michael@0 97 getStaticMethodID: function(aClass, aName, aSignature) {
michael@0 98 let ret = this._getStaticMethodID(aClass, aName, aSignature);
michael@0 99 if (this.exceptionCheck())
michael@0 100 throw("Can't find method " + aName);
michael@0 101 return new jMethod(aName, ret, aSignature);
michael@0 102 },
michael@0 103
michael@0 104 get _exceptionCheck() {
michael@0 105 delete this._exceptionCheck;
michael@0 106 return this._exceptionCheck = this.lib.declare("jsjni_ExceptionCheck",
michael@0 107 ctypes.default_abi,
michael@0 108 ctypes.bool);
michael@0 109 },
michael@0 110
michael@0 111 exceptionCheck: function() {
michael@0 112 return this._exceptionCheck();
michael@0 113 },
michael@0 114
michael@0 115 get _callStaticVoidMethod() {
michael@0 116 delete this._callStaticVoidMethod;
michael@0 117 return this._callStaticVoidMethod = this.lib.declare("jsjni_CallStaticVoidMethodA",
michael@0 118 ctypes.default_abi,
michael@0 119 ctypes.void_t,
michael@0 120 this.types.jclass,
michael@0 121 this.types.jmethodID,
michael@0 122 this.types.jvalue.ptr);
michael@0 123 },
michael@0 124
michael@0 125 callStaticVoidMethod: function(aClass, aMethod) {
michael@0 126 let args = Array.prototype.slice.apply(arguments, [2]);
michael@0 127 this._callStaticVoidMethod(aClass, aMethod.methodId, this.getArgs(aMethod, args));
michael@0 128 if (this.exceptionCheck())
michael@0 129 throw("Error calling static void method");
michael@0 130 },
michael@0 131
michael@0 132 get _callStaticIntMethod() {
michael@0 133 delete this._callStaticIntMethod;
michael@0 134 return this._callStaticIntMethod = this.lib.declare("jsjni_CallStaticIntMethodA",
michael@0 135 ctypes.default_abi,
michael@0 136 ctypes.int,
michael@0 137 this.types.jclass,
michael@0 138 this.types.jmethodID,
michael@0 139 this.types.jvalue.ptr);
michael@0 140 },
michael@0 141
michael@0 142 callStaticIntMethod: function(aClass, aMethod) {
michael@0 143 let args = Array.prototype.slice.apply(arguments, [2]);
michael@0 144 let ret = this._callStaticIntMethod(aClass, aMethod.methodId, this.getArgs(aMethod, args));
michael@0 145 if (this.exceptionCheck())
michael@0 146 throw("Error calling static int method");
michael@0 147 return ret;
michael@0 148 },
michael@0 149
michael@0 150 close: function() {
michael@0 151 this.lib.close();
michael@0 152 },
michael@0 153 }
michael@0 154
michael@0 155 function jMethod(name, jMethodId, signature) {
michael@0 156 this.name = name;
michael@0 157 this.methodId = jMethodId;
michael@0 158 this.signature = signature;
michael@0 159 }
michael@0 160
michael@0 161 jMethod.prototype = {
michael@0 162 parameters: [],
michael@0 163 returnType: null,
michael@0 164 _signature: "",
michael@0 165
michael@0 166 // this just splits up the return value from the parameters
michael@0 167 signatureRegExp: /^\(([^\)]*)\)(.*)$/,
michael@0 168
michael@0 169 // This splits up the actual parameters
michael@0 170 parameterRegExp: /(\[*)(B|C|D|F|I|J|S|V|Z|L[^;]*;)/y,
michael@0 171
michael@0 172 parseSignature: function(aSignature) {
michael@0 173 let [, parameters, returnType] = this.signatureRegExp.exec(aSignature);
michael@0 174
michael@0 175 // parse the parameters that should be passed to this method
michael@0 176 if (parameters) {
michael@0 177 let parameter = this.parameterRegExp.exec(parameters);
michael@0 178 while (parameter) {
michael@0 179 this.parameters.push(parameter[0]);
michael@0 180 parameter = this.parameterRegExp.exec(parameters);
michael@0 181 }
michael@0 182 } else {
michael@0 183 this.parameters = [];
michael@0 184 }
michael@0 185
michael@0 186 // parse the return type
michael@0 187 this.returnType = returnType;
michael@0 188 },
michael@0 189
michael@0 190 _signature: "",
michael@0 191 get signature() { return this._signature; },
michael@0 192 set signature(val) {
michael@0 193 this.parameters = [];
michael@0 194 this.returnType = null;
michael@0 195 this.parseSignature(val);
michael@0 196 }
michael@0 197 }

mercurial