mobile/android/modules/JNI.jsm

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

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

mercurial