// JavaScript to Java bridge via the Java Native Interface // Allows calling into Android SDK from JavaScript in Firefox Add-On. // Released into the public domain. // C. Scott Ananian (http://cscott.net) // NOTE: All changes to this file should first be pushed to the repo at: // https://github.com/cscott/skeleton-addon-fxandroid/tree/jni var EXPORTED_SYMBOLS = ["JNI","android_log"]; Components.utils.import("resource://gre/modules/ctypes.jsm") var liblog = ctypes.open('liblog.so'); var android_log = liblog.declare("__android_log_write", ctypes.default_abi, ctypes.int32_t, ctypes.int32_t, ctypes.char.ptr, ctypes.char.ptr); var libxul = ctypes.open('libxul.so'); var jenvptr = ctypes.voidptr_t; var jclass = ctypes.voidptr_t; var jobject = ctypes.voidptr_t; var jvalue = ctypes.voidptr_t; var jmethodid = ctypes.voidptr_t; var jfieldid = ctypes.voidptr_t; var jboolean = ctypes.uint8_t; var jbyte = ctypes.int8_t; var jchar = ctypes.uint16_t; var jshort = ctypes.int16_t; var jint = ctypes.int32_t; var jlong = ctypes.int64_t; var jfloat = ctypes.float32_t; var jdouble = ctypes.float64_t; var jsize = jint; var jstring = jobject; var jarray = jobject; var jthrowable = jobject; var JNINativeInterface = new ctypes.StructType( "JNINativeInterface", [{reserved0: ctypes.voidptr_t}, {reserved1: ctypes.voidptr_t}, {reserved2: ctypes.voidptr_t}, {reserved3: ctypes.voidptr_t}, {GetVersion: new ctypes.FunctionType(ctypes.default_abi, ctypes.int32_t, [ctypes.voidptr_t]).ptr}, {DefineClass: new ctypes.FunctionType(ctypes.default_abi, jclass, [jenvptr, ctypes.char.ptr, jobject, jbyte.array(), jsize]).ptr}, {FindClass: new ctypes.FunctionType(ctypes.default_abi, jclass, [jenvptr, ctypes.char.ptr]).ptr}, {FromReflectedMethod: new ctypes.FunctionType(ctypes.default_abi, jmethodid, [jenvptr, jobject]).ptr}, {FromReflectedField: new ctypes.FunctionType(ctypes.default_abi, jfieldid, [jenvptr, jobject]).ptr}, {ToReflectedMethod: new ctypes.FunctionType(ctypes.default_abi, jobject, [jenvptr, jclass, jmethodid]).ptr}, {GetSuperclass: new ctypes.FunctionType(ctypes.default_abi, jclass, [jenvptr, jclass]).ptr}, {IsAssignableFrom: new ctypes.FunctionType(ctypes.default_abi, jboolean, [jenvptr, jclass, jclass]).ptr}, {ToReflectedField: new ctypes.FunctionType(ctypes.default_abi, jobject, [jenvptr, jclass, jfieldid]).ptr}, {Throw: new ctypes.FunctionType(ctypes.default_abi, jint, [jenvptr, jthrowable]).ptr}, {ThrowNew: new ctypes.FunctionType(ctypes.default_abi, jint, [jenvptr, jclass, ctypes.char.ptr]).ptr}, {ExceptionOccurred: new ctypes.FunctionType(ctypes.default_abi, jthrowable, [jenvptr]).ptr}, {ExceptionDescribe: new ctypes.FunctionType(ctypes.default_abi, ctypes.void_t, [jenvptr]).ptr}, {ExceptionClear: new ctypes.FunctionType(ctypes.default_abi, ctypes.void_t, [jenvptr]).ptr}, {FatalError: new ctypes.FunctionType(ctypes.default_abi, ctypes.void_t, [jenvptr, ctypes.char.ptr]).ptr}, {PushLocalFrame: new ctypes.FunctionType(ctypes.default_abi, jint, [jenvptr, jint]).ptr}, {PopLocalFrame: new ctypes.FunctionType(ctypes.default_abi, jobject, [jenvptr, jobject]).ptr}, {NewGlobalRef: new ctypes.FunctionType(ctypes.default_abi, jobject, [jenvptr, jobject]).ptr}, {DeleteGlobalRef: new ctypes.FunctionType(ctypes.default_abi, ctypes.void_t, [jenvptr, jobject]).ptr}, {DeleteLocalRef: new ctypes.FunctionType(ctypes.default_abi, ctypes.void_t, [jenvptr, jobject]).ptr}, {IsSameObject: new ctypes.FunctionType(ctypes.default_abi, jboolean, [jenvptr, jobject, jobject]).ptr}, {NewLocalRef: new ctypes.FunctionType(ctypes.default_abi, jobject, [jenvptr, jobject]).ptr}, {EnsureLocalCapacity: new ctypes.FunctionType(ctypes.default_abi, jint, [jenvptr, jint]).ptr}, {AllocObject: new ctypes.FunctionType(ctypes.default_abi, jobject, [jenvptr, jclass]).ptr}, {NewObject: new ctypes.FunctionType(ctypes.default_abi, jobject, [jenvptr, jclass, jmethodid, "..."]).ptr}, {NewObjectV: ctypes.voidptr_t}, {NewObjectA: ctypes.voidptr_t}, {GetObjectClass: new ctypes.FunctionType(ctypes.default_abi, jclass, [jenvptr, jobject]).ptr}, {IsInstanceOf: new ctypes.FunctionType(ctypes.default_abi, jboolean, [jenvptr, jobject, jclass]).ptr}, {GetMethodID: new ctypes.FunctionType(ctypes.default_abi, jmethodid, [jenvptr, jclass, ctypes.char.ptr, ctypes.char.ptr]).ptr}, {CallObjectMethod: new ctypes.FunctionType(ctypes.default_abi, jobject, [jenvptr, jobject, jmethodid, "..."]).ptr}, {CallObjectMethodV: ctypes.voidptr_t}, {CallObjectMethodA: ctypes.voidptr_t}, {CallBooleanMethod: new ctypes.FunctionType(ctypes.default_abi, jboolean, [jenvptr, jobject, jmethodid, "..."]).ptr}, {CallBooleanMethodV: ctypes.voidptr_t}, {CallBooleanMethodA: ctypes.voidptr_t}, {CallByteMethod: new ctypes.FunctionType(ctypes.default_abi, jbyte, [jenvptr, jobject, jmethodid, "..."]).ptr}, {CallByteMethodV: ctypes.voidptr_t}, {CallByteMethodA: ctypes.voidptr_t}, {CallCharMethod: new ctypes.FunctionType(ctypes.default_abi, jchar, [jenvptr, jobject, jmethodid, "..."]).ptr}, {CallCharMethodV: ctypes.voidptr_t}, {CallCharMethodA: ctypes.voidptr_t}, {CallShortMethod: new ctypes.FunctionType(ctypes.default_abi, jshort, [jenvptr, jobject, jmethodid, "..."]).ptr}, {CallShortMethodV: ctypes.voidptr_t}, {CallShortMethodA: ctypes.voidptr_t}, {CallIntMethod: new ctypes.FunctionType(ctypes.default_abi, jint, [jenvptr, jobject, jmethodid, "..."]).ptr}, {CallIntMethodV: ctypes.voidptr_t}, {CallIntMethodA: ctypes.voidptr_t}, {CallLongMethod: new ctypes.FunctionType(ctypes.default_abi, jlong, [jenvptr, jobject, jmethodid, "..."]).ptr}, {CallLongMethodV: ctypes.voidptr_t}, {CallLongMethodA: ctypes.voidptr_t}, {CallFloatMethod: new ctypes.FunctionType(ctypes.default_abi, jfloat, [jenvptr, jobject, jmethodid, "..."]).ptr}, {CallFloatMethodV: ctypes.voidptr_t}, {CallFloatMethodA: ctypes.voidptr_t}, {CallDoubleMethod: new ctypes.FunctionType(ctypes.default_abi, jdouble, [jenvptr, jobject, jmethodid, "..."]).ptr}, {CallDoubleMethodV: ctypes.voidptr_t}, {CallDoubleMethodA: ctypes.voidptr_t}, {CallVoidMethod: new ctypes.FunctionType(ctypes.default_abi, ctypes.void_t, [jenvptr, jobject, jmethodid, "..."]).ptr}, {CallVoidMethodV: ctypes.voidptr_t}, {CallVoidMethodA: ctypes.voidptr_t}, {CallNonvirtualObjectMethod: new ctypes.FunctionType(ctypes.default_abi, jobject, [jenvptr, jobject, jclass, jmethodid, "..."]).ptr}, {CallNonvirtualObjectMethodV: ctypes.voidptr_t}, {CallNonvirtualObjectMethodA: ctypes.voidptr_t}, {CallNonvirtualBooleanMethod: new ctypes.FunctionType(ctypes.default_abi, jboolean, [jenvptr, jobject, jclass, jmethodid, "..."]).ptr}, {CallNonvirtualBooleanMethodV: ctypes.voidptr_t}, {CallNonvirtualBooleanMethodA: ctypes.voidptr_t}, {CallNonvirtualByteMethod: new ctypes.FunctionType(ctypes.default_abi, jbyte, [jenvptr, jobject, jclass, jmethodid, "..."]).ptr}, {CallNonvirtualByteMethodV: ctypes.voidptr_t}, {CallNonvirtualByteMethodA: ctypes.voidptr_t}, {CallNonvirtualCharMethod: new ctypes.FunctionType(ctypes.default_abi, jchar, [jenvptr, jobject, jclass, jmethodid, "..."]).ptr}, {CallNonvirtualCharMethodV: ctypes.voidptr_t}, {CallNonvirtualCharMethodA: ctypes.voidptr_t}, {CallNonvirtualShortMethod: new ctypes.FunctionType(ctypes.default_abi, jshort, [jenvptr, jobject, jclass, jmethodid, "..."]).ptr}, {CallNonvirtualShortMethodV: ctypes.voidptr_t}, {CallNonvirtualShortMethodA: ctypes.voidptr_t}, {CallNonvirtualIntMethod: new ctypes.FunctionType(ctypes.default_abi, jint, [jenvptr, jobject, jclass, jmethodid, "..."]).ptr}, {CallNonvirtualIntMethodV: ctypes.voidptr_t}, {CallNonvirtualIntMethodA: ctypes.voidptr_t}, {CallNonvirtualLongMethod: new ctypes.FunctionType(ctypes.default_abi, jlong, [jenvptr, jobject, jclass, jmethodid, "..."]).ptr}, {CallNonvirtualLongMethodV: ctypes.voidptr_t}, {CallNonvirtualLongMethodA: ctypes.voidptr_t}, {CallNonvirtualFloatMethod: new ctypes.FunctionType(ctypes.default_abi, jfloat, [jenvptr, jobject, jclass, jmethodid, "..."]).ptr}, {CallNonvirtualFloatMethodV: ctypes.voidptr_t}, {CallNonvirtualFloatMethodA: ctypes.voidptr_t}, {CallNonvirtualDoubleMethod: new ctypes.FunctionType(ctypes.default_abi, jdouble, [jenvptr, jobject, jclass, jmethodid, "..."]).ptr}, {CallNonvirtualDoubleMethodV: ctypes.voidptr_t}, {CallNonvirtualDoubleMethodA: ctypes.voidptr_t}, {CallNonvirtualVoidMethod: new ctypes.FunctionType(ctypes.default_abi, ctypes.void_t, [jenvptr, jobject, jclass, jmethodid, "..."]).ptr}, {CallNonvirtualVoidMethodV: ctypes.voidptr_t}, {CallNonvirtualVoidMethodA: ctypes.voidptr_t}, {GetFieldID: new ctypes.FunctionType(ctypes.default_abi, jfieldid, [jenvptr, jclass, ctypes.char.ptr, ctypes.char.ptr]).ptr}, {GetObjectField: new ctypes.FunctionType(ctypes.default_abi, jobject, [jenvptr, jobject, jfieldid]).ptr}, {GetBooleanField: new ctypes.FunctionType(ctypes.default_abi, jboolean, [jenvptr, jobject, jfieldid]).ptr}, {GetByteField: new ctypes.FunctionType(ctypes.default_abi, jbyte, [jenvptr, jobject, jfieldid]).ptr}, {GetCharField: new ctypes.FunctionType(ctypes.default_abi, jchar, [jenvptr, jobject, jfieldid]).ptr}, {GetShortField: new ctypes.FunctionType(ctypes.default_abi, jshort, [jenvptr, jobject, jfieldid]).ptr}, {GetIntField: new ctypes.FunctionType(ctypes.default_abi, jint, [jenvptr, jobject, jfieldid]).ptr}, {GetLongField: new ctypes.FunctionType(ctypes.default_abi, jlong, [jenvptr, jobject, jfieldid]).ptr}, {GetFloatField: new ctypes.FunctionType(ctypes.default_abi, jfloat, [jenvptr, jobject, jfieldid]).ptr}, {GetDoubleField: new ctypes.FunctionType(ctypes.default_abi, jdouble, [jenvptr, jobject, jfieldid]).ptr}, {SetObjectField: new ctypes.FunctionType(ctypes.default_abi, ctypes.void_t, [jenvptr, jobject, jfieldid, jobject]).ptr}, {SetBooleanField: new ctypes.FunctionType(ctypes.default_abi, ctypes.void_t, [jenvptr, jobject, jfieldid, jboolean]).ptr}, {SetByteField: new ctypes.FunctionType(ctypes.default_abi, ctypes.void_t, [jenvptr, jobject, jfieldid, jbyte]).ptr}, {SetCharField: new ctypes.FunctionType(ctypes.default_abi, ctypes.void_t, [jenvptr, jobject, jfieldid, jchar]).ptr}, {SetShortField: new ctypes.FunctionType(ctypes.default_abi, ctypes.void_t, [jenvptr, jobject, jfieldid, jshort]).ptr}, {SetIntField: new ctypes.FunctionType(ctypes.default_abi, ctypes.void_t, [jenvptr, jobject, jfieldid, jint]).ptr}, {SetLongField: new ctypes.FunctionType(ctypes.default_abi, ctypes.void_t, [jenvptr, jobject, jfieldid, jlong]).ptr}, {SetFloatField: new ctypes.FunctionType(ctypes.default_abi, ctypes.void_t, [jenvptr, jobject, jfieldid, jfloat]).ptr}, {SetDoubleField: new ctypes.FunctionType(ctypes.default_abi, ctypes.void_t, [jenvptr, jobject, jfieldid, jdouble]).ptr}, {GetStaticMethodID: new ctypes.FunctionType(ctypes.default_abi, jmethodid, [jenvptr, jclass, ctypes.char.ptr, ctypes.char.ptr]).ptr}, {CallStaticObjectMethod: new ctypes.FunctionType(ctypes.default_abi, jobject, [jenvptr, jclass, jmethodid, "..."]).ptr}, {CallStaticObjectMethodV: ctypes.voidptr_t}, {CallStaticObjectMethodA: ctypes.voidptr_t}, {CallStaticBooleanMethod: new ctypes.FunctionType(ctypes.default_abi, jboolean, [jenvptr, jclass, jmethodid, "..."]).ptr}, {CallStaticBooleanMethodV: ctypes.voidptr_t}, {CallStaticBooleanMethodA: ctypes.voidptr_t}, {CallStaticByteMethod: new ctypes.FunctionType(ctypes.default_abi, jbyte, [jenvptr, jclass, jmethodid, "..."]).ptr}, {CallStaticByteMethodV: ctypes.voidptr_t}, {CallStaticByteMethodA: ctypes.voidptr_t}, {CallStaticCharMethod: new ctypes.FunctionType(ctypes.default_abi, jchar, [jenvptr, jclass, jmethodid, "..."]).ptr}, {CallStaticCharMethodV: ctypes.voidptr_t}, {CallStaticCharMethodA: ctypes.voidptr_t}, {CallStaticShortMethod: new ctypes.FunctionType(ctypes.default_abi, jshort, [jenvptr, jclass, jmethodid, "..."]).ptr}, {CallStaticShortMethodV: ctypes.voidptr_t}, {CallStaticShortMethodA: ctypes.voidptr_t}, {CallStaticIntMethod: new ctypes.FunctionType(ctypes.default_abi, jint, [jenvptr, jclass, jmethodid, "..."]).ptr}, {CallStaticIntMethodV: ctypes.voidptr_t}, {CallStaticIntMethodA: ctypes.voidptr_t}, {CallStaticLongMethod: new ctypes.FunctionType(ctypes.default_abi, jlong, [jenvptr, jclass, jmethodid, "..."]).ptr}, {CallStaticLongMethodV: ctypes.voidptr_t}, {CallStaticLongMethodA: ctypes.voidptr_t}, {CallStaticFloatMethod: new ctypes.FunctionType(ctypes.default_abi, jfloat, [jenvptr, jclass, jmethodid, "..."]).ptr}, {CallStaticFloatMethodV: ctypes.voidptr_t}, {CallStaticFloatMethodA: ctypes.voidptr_t}, {CallStaticDoubleMethod: new ctypes.FunctionType(ctypes.default_abi, jdouble, [jenvptr, jclass, jmethodid, "..."]).ptr}, {CallStaticDoubleMethodV: ctypes.voidptr_t}, {CallStaticDoubleMethodA: ctypes.voidptr_t}, {CallStaticVoidMethod: new ctypes.FunctionType(ctypes.default_abi, ctypes.void_t, [jenvptr, jclass, jmethodid, "..."]).ptr}, {CallStaticVoidMethodV: ctypes.voidptr_t}, {CallStaticVoidMethodA: ctypes.voidptr_t}, {GetStaticFieldID: new ctypes.FunctionType(ctypes.default_abi, jfieldid, [jenvptr, jclass, ctypes.char.ptr, ctypes.char.ptr]).ptr}, {GetStaticObjectField: new ctypes.FunctionType(ctypes.default_abi, jobject, [jenvptr, jclass, jfieldid]).ptr}, {GetStaticBooleanField: new ctypes.FunctionType(ctypes.default_abi, jboolean, [jenvptr, jclass, jfieldid]).ptr}, {GetStaticByteField: new ctypes.FunctionType(ctypes.default_abi, jbyte, [jenvptr, jclass, jfieldid]).ptr}, {GetStaticCharField: new ctypes.FunctionType(ctypes.default_abi, jchar, [jenvptr, jclass, jfieldid]).ptr}, {GetStaticShortField: new ctypes.FunctionType(ctypes.default_abi, jshort, [jenvptr, jclass, jfieldid]).ptr}, {GetStaticIntField: new ctypes.FunctionType(ctypes.default_abi, jint, [jenvptr, jclass, jfieldid]).ptr}, {GetStaticLongField: new ctypes.FunctionType(ctypes.default_abi, jlong, [jenvptr, jclass, jfieldid]).ptr}, {GetStaticFloatField: new ctypes.FunctionType(ctypes.default_abi, jfloat, [jenvptr, jclass, jfieldid]).ptr}, {GetStaticDoubleField: new ctypes.FunctionType(ctypes.default_abi, jdouble, [jenvptr, jclass, jfieldid]).ptr}, {SetStaticObjectField: new ctypes.FunctionType(ctypes.default_abi, ctypes.void_t, [jenvptr, jclass, jfieldid, jobject]).ptr}, {SetStaticBooleanField: new ctypes.FunctionType(ctypes.default_abi, ctypes.void_t, [jenvptr, jclass, jfieldid, jboolean]).ptr}, {SetStaticByteField: new ctypes.FunctionType(ctypes.default_abi, ctypes.void_t, [jenvptr, jclass, jfieldid, jbyte]).ptr}, {SetStaticCharField: new ctypes.FunctionType(ctypes.default_abi, ctypes.void_t, [jenvptr, jclass, jfieldid, jchar]).ptr}, {SetStaticShortField: new ctypes.FunctionType(ctypes.default_abi, ctypes.void_t, [jenvptr, jclass, jfieldid, jshort]).ptr}, {SetStaticIntField: new ctypes.FunctionType(ctypes.default_abi, ctypes.void_t, [jenvptr, jclass, jfieldid, jint]).ptr}, {SetStaticLongField: new ctypes.FunctionType(ctypes.default_abi, ctypes.void_t, [jenvptr, jclass, jfieldid, jlong]).ptr}, {SetStaticFloatField: new ctypes.FunctionType(ctypes.default_abi, ctypes.void_t, [jenvptr, jclass, jfieldid, jfloat]).ptr}, {SetStaticDoubleField: new ctypes.FunctionType(ctypes.default_abi, ctypes.void_t, [jenvptr, jclass, jfieldid, jdouble]).ptr}, {NewString: new ctypes.FunctionType(ctypes.default_abi, jstring, [jenvptr, jchar.ptr, jsize]).ptr}, {GetStringLength: new ctypes.FunctionType(ctypes.default_abi, jsize, [jenvptr, jstring]).ptr}, {GetStringChars: new ctypes.FunctionType(ctypes.default_abi, jchar.ptr, [jenvptr, jstring, jboolean.ptr]).ptr}, {ReleaseStringChars: new ctypes.FunctionType(ctypes.default_abi, ctypes.void_t, [jenvptr, jstring, jchar.ptr]).ptr}, {NewStringUTF: new ctypes.FunctionType(ctypes.default_abi, jstring, [jenvptr, ctypes.char.ptr]).ptr}, {GetStringUTFLength: new ctypes.FunctionType(ctypes.default_abi, jsize, [jenvptr, jstring]).ptr}, {GetStringUTFChars: new ctypes.FunctionType(ctypes.default_abi, ctypes.char.ptr, [jenvptr, jstring, jboolean.ptr]).ptr}, {ReleaseStringUTFChars: new ctypes.FunctionType(ctypes.default_abi, ctypes.void_t, [jenvptr, jstring, ctypes.char.ptr]).ptr}, {GetArrayLength: new ctypes.FunctionType(ctypes.default_abi, jsize, [jenvptr, jarray]).ptr}, {NewObjectArray: new ctypes.FunctionType(ctypes.default_abi, jarray, [jenvptr, jsize, jclass, jobject]).ptr}, {GetObjectArrayElement: new ctypes.FunctionType(ctypes.default_abi, jobject, [jenvptr, jarray, jsize]).ptr}, {SetObjectArrayElement: new ctypes.FunctionType(ctypes.default_abi, ctypes.void_t, [jenvptr, jarray, jsize, jobject]).ptr}, {NewBooleanArray: new ctypes.FunctionType(ctypes.default_abi, jarray, [jenvptr, jsize]).ptr}, {NewByteArray: new ctypes.FunctionType(ctypes.default_abi, jarray, [jenvptr, jsize]).ptr}, {NewCharArray: new ctypes.FunctionType(ctypes.default_abi, jarray, [jenvptr, jsize]).ptr}, {NewShortArray: new ctypes.FunctionType(ctypes.default_abi, jarray, [jenvptr, jsize]).ptr}, {NewIntArray: new ctypes.FunctionType(ctypes.default_abi, jarray, [jenvptr, jsize]).ptr}, {NewLongArray: new ctypes.FunctionType(ctypes.default_abi, jarray, [jenvptr, jsize]).ptr}, {NewFloatArray: new ctypes.FunctionType(ctypes.default_abi, jarray, [jenvptr, jsize]).ptr}, {NewDoubleArray: new ctypes.FunctionType(ctypes.default_abi, jarray, [jenvptr, jsize]).ptr}, {GetBooleanArrayElements: new ctypes.FunctionType(ctypes.default_abi, jboolean.ptr, [jenvptr, jarray, jboolean.ptr]).ptr}, {GetByteArrayElements: new ctypes.FunctionType(ctypes.default_abi, jbyte.ptr, [jenvptr, jarray, jboolean.ptr]).ptr}, {GetCharArrayElements: new ctypes.FunctionType(ctypes.default_abi, jchar.ptr, [jenvptr, jarray, jboolean.ptr]).ptr}, {GetShortArrayElements: new ctypes.FunctionType(ctypes.default_abi, jshort.ptr, [jenvptr, jarray, jboolean.ptr]).ptr}, {GetIntArrayElements: new ctypes.FunctionType(ctypes.default_abi, jint.ptr, [jenvptr, jarray, jboolean.ptr]).ptr}, {GetLongArrayElements: new ctypes.FunctionType(ctypes.default_abi, jlong.ptr, [jenvptr, jarray, jboolean.ptr]).ptr}, {GetFloatArrayElements: new ctypes.FunctionType(ctypes.default_abi, jfloat.ptr, [jenvptr, jarray, jboolean.ptr]).ptr}, {GetDoubleArrayElements: new ctypes.FunctionType(ctypes.default_abi, jdouble.ptr, [jenvptr, jarray, jboolean.ptr]).ptr}, {ReleaseBooleanArrayElements: new ctypes.FunctionType(ctypes.default_abi, ctypes.void_t, [jenvptr, jarray, jboolean.ptr, jint]).ptr}, {ReleaseByteArrayElements: new ctypes.FunctionType(ctypes.default_abi, ctypes.void_t, [jenvptr, jarray, jbyte.ptr, jint]).ptr}, {ReleaseCharArrayElements: new ctypes.FunctionType(ctypes.default_abi, ctypes.void_t, [jenvptr, jarray, jchar.ptr, jint]).ptr}, {ReleaseShortArrayElements: new ctypes.FunctionType(ctypes.default_abi, ctypes.void_t, [jenvptr, jarray, jshort.ptr, jint]).ptr}, {ReleaseIntArrayElements: new ctypes.FunctionType(ctypes.default_abi, ctypes.void_t, [jenvptr, jarray, jint.ptr, jint]).ptr}, {ReleaseLongArrayElements: new ctypes.FunctionType(ctypes.default_abi, ctypes.void_t, [jenvptr, jarray, jlong.ptr, jint]).ptr}, {ReleaseFloatArrayElements: new ctypes.FunctionType(ctypes.default_abi, ctypes.void_t, [jenvptr, jarray, jfloat.ptr, jint]).ptr}, {ReleaseDoubleArrayElements: new ctypes.FunctionType(ctypes.default_abi, ctypes.void_t, [jenvptr, jarray, jdouble.ptr, jint]).ptr}, {GetBooleanArrayRegion: new ctypes.FunctionType(ctypes.default_abi, ctypes.void_t, [jenvptr, jarray, jsize, jsize, jboolean.array()]).ptr}, {GetByteArrayRegion: new ctypes.FunctionType(ctypes.default_abi, ctypes.void_t, [jenvptr, jarray, jsize, jsize, jbyte.array()]).ptr}, {GetCharArrayRegion: new ctypes.FunctionType(ctypes.default_abi, ctypes.void_t, [jenvptr, jarray, jsize, jsize, jchar.array()]).ptr}, {GetShortArrayRegion: new ctypes.FunctionType(ctypes.default_abi, ctypes.void_t, [jenvptr, jarray, jsize, jsize, jshort.array()]).ptr}, {GetIntArrayRegion: new ctypes.FunctionType(ctypes.default_abi, ctypes.void_t, [jenvptr, jarray, jsize, jsize, jint.array()]).ptr}, {GetLongArrayRegion: new ctypes.FunctionType(ctypes.default_abi, ctypes.void_t, [jenvptr, jarray, jsize, jsize, jlong.array()]).ptr}, {GetFloatArrayRegion: new ctypes.FunctionType(ctypes.default_abi, ctypes.void_t, [jenvptr, jarray, jsize, jsize, jfloat.array()]).ptr}, {GetDoubleArrayRegion: new ctypes.FunctionType(ctypes.default_abi, ctypes.void_t, [jenvptr, jarray, jsize, jsize, jdouble.array()]).ptr}, {SetBooleanArrayRegion: new ctypes.FunctionType(ctypes.default_abi, ctypes.void_t, [jenvptr, jarray, jsize, jsize, jboolean.array()]).ptr}, {SetByteArrayRegion: new ctypes.FunctionType(ctypes.default_abi, ctypes.void_t, [jenvptr, jarray, jsize, jsize, jbyte.array()]).ptr}, {SetCharArrayRegion: new ctypes.FunctionType(ctypes.default_abi, ctypes.void_t, [jenvptr, jarray, jsize, jsize, jchar.array()]).ptr}, {SetShortArrayRegion: new ctypes.FunctionType(ctypes.default_abi, ctypes.void_t, [jenvptr, jarray, jsize, jsize, jshort.array()]).ptr}, {SetIntArrayRegion: new ctypes.FunctionType(ctypes.default_abi, ctypes.void_t, [jenvptr, jarray, jsize, jsize, jint.array()]).ptr}, {SetLongArrayRegion: new ctypes.FunctionType(ctypes.default_abi, ctypes.void_t, [jenvptr, jarray, jsize, jsize, jlong.array()]).ptr}, {SetFloatArrayRegion: new ctypes.FunctionType(ctypes.default_abi, ctypes.void_t, [jenvptr, jarray, jsize, jsize, jfloat.array()]).ptr}, {SetDoubleArrayRegion: new ctypes.FunctionType(ctypes.default_abi, ctypes.void_t, [jenvptr, jarray, jsize, jsize, jdouble.array()]).ptr}, {RegisterNatives: ctypes.voidptr_t}, {UnregisterNatives: ctypes.voidptr_t}, {MonitorEnter: new ctypes.FunctionType(ctypes.default_abi, jint, [jenvptr, jobject]).ptr}, {MonitorExit: new ctypes.FunctionType(ctypes.default_abi, jint, [jenvptr, jobject]).ptr}, {GetJavaVM: ctypes.voidptr_t}, {GetStringRegion: new ctypes.FunctionType(ctypes.default_abi, ctypes.void_t, [jenvptr, jstring, jsize, jsize, jchar.array()]).ptr}, {GetStringUTFRegion: new ctypes.FunctionType(ctypes.default_abi, ctypes.void_t, [jenvptr, jstring, jsize, jsize, ctypes.char.array()]).ptr}, {GetPrimitiveArrayCritical: ctypes.voidptr_t}, {ReleasePrimitiveArrayCritical: ctypes.voidptr_t}, {GetStringCritical: ctypes.voidptr_t}, {ReleaseStringCritical: ctypes.voidptr_t}, {NewWeakGlobalRef: ctypes.voidptr_t}, {DeleteWeakGlobalRef: ctypes.voidptr_t}, {ExceptionCheck: new ctypes.FunctionType(ctypes.default_abi, jboolean, [jenvptr]).ptr}, {NewDirectByteBuffer: ctypes.voidptr_t}, {GetDirectBufferAddress: ctypes.voidptr_t}, {GetDirectBufferCapacity: ctypes.voidptr_t}, {GetObjectRefType: ctypes.voidptr_t}] ); var GetJNIForThread = libxul.declare("GetJNIForThread", ctypes.default_abi, JNINativeInterface.ptr.ptr); var registry = Object.create(null); var classes = Object.create(null); function JNIUnloadClasses(jenv) { Object.getOwnPropertyNames(registry).forEach(function(classname) { var jcls = unwrap(registry[classname]); jenv.contents.contents.DeleteGlobalRef(jenv, jcls); // Purge the registry, so we don't try to reuse stale global references // in JNI calls and we garbage-collect the JS global reference objects. delete registry[classname]; }); // The refs also get added to the 'classes' object, so we should purge it too. // That object is a hierarchical data structure organized by class path parts, // but deleting its own properties should be sufficient to break its refs. Object.getOwnPropertyNames(classes).forEach(function(topLevelPart) { delete classes[topLevelPart]; }); } var PREFIX = 'js#'; // this regex matches one component of a type signature: // any number of array modifiers, followed by either a // primitive type character or L; var sigRegex = () => /\[*([VZBCSIJFD]|L([^.\/;]+(\/[^.\/;]+)*);)/g; var ensureSig = function(classname_or_signature) { // convert a classname into a signature, // leaving unchanged signatures. We assume that // anything not a valid signature is a classname. var m = sigRegex().exec(classname_or_signature); return (m && m[0] === classname_or_signature) ? classname_or_signature : 'L' + classname_or_signature.replace(/\./g, '/') + ';'; }; var wrap = function(obj, classSig) { if (!classSig) { return obj; } // don't wrap primitive types. if (classSig.charAt(0)!=='L' && classSig.charAt(0)!=='[') { return obj; } var proto = registry[classSig][PREFIX+'proto']; return new proto(obj); }; var unwrap = function(obj, opt_jenv, opt_ctype) { if (obj && typeof(obj)==='object' && (PREFIX+'obj') in obj) { return obj[PREFIX+'obj']; } else if (opt_jenv && opt_ctype) { if (opt_ctype !== jobject) return opt_ctype(obj); // cast to given primitive ctype if (typeof(obj)==='string') return unwrap(JNINewString(opt_jenv, obj)); // create Java String } return obj; }; var ensureLoaded = function(jenv, classSig) { if (!Object.hasOwnProperty.call(registry, classSig)) { JNILoadClass(jenv, classSig); } return registry[classSig]; }; function JNINewString(jenv, value) { var s = jenv.contents.contents.NewStringUTF(jenv, ctypes.char.array()(value)); ensureLoaded(jenv, "Ljava/lang/String;"); return wrap(s, "Ljava/lang/String;"); } function JNIReadString(jenv, jstring_value) { var val = unwrap(jstring_value); if ((!val) || val.isNull()) { return null; } var chars = jenv.contents.contents.GetStringUTFChars(jenv, val, null); var result = chars.readString(); jenv.contents.contents.ReleaseStringUTFChars(jenv, val, chars); return result; } var sigInfo = { 'V': { name: 'Void', longName: 'Void', ctype: ctypes.void_t }, 'Z': { name: 'Boolean', longName: 'Boolean', ctype: jboolean }, 'B': { name: 'Byte', longName: 'Byte', ctype: jbyte }, 'C': { name: 'Char', longName: 'Char', ctype: jchar }, 'S': { name: 'Short', longName: 'Short', ctype: jshort }, 'I': { name: 'Int', longName: 'Integer', ctype: jint }, 'J': { name: 'Long', longName: 'Long', ctype: jlong }, 'F': { name: 'Float', longName: 'Float', ctype: jfloat }, 'D': { name: 'Double', longName: 'Double', ctype: jdouble }, 'L': { name: 'Object', longName: 'Object', ctype: jobject }, '[': { name: 'Object', longName: 'Object', ctype: jarray } }; var sig2type = function(sig) { return sigInfo[sig.charAt(0)].name; }; var sig2ctype = function(sig) { return sigInfo[sig.charAt(0)].ctype; }; var sig2prim = function(sig) { return sigInfo[sig.charAt(0)].longName; }; // return the class object for a signature string. // allocates 1 or 2 local refs function JNIClassObj(jenv, classSig) { var jenvpp = function() { return jenv.contents.contents; }; // Deal with funny calling convention of JNI FindClass method. // Classes get the leading & trailing chars stripped; primitives // have to be looked up via their wrapper type. var prim = function(ty) { var jcls = jenvpp().FindClass(jenv, "java/lang/"+ty); var jfld = jenvpp().GetStaticFieldID(jenv, jcls, "TYPE", "Ljava/lang/Class;"); return jenvpp().GetStaticObjectField(jenv, jcls, jfld); }; switch (classSig.charAt(0)) { case '[': return jenvpp().FindClass(jenv, classSig); case 'L': classSig = classSig.substring(1, classSig.indexOf(';')); return jenvpp().FindClass(jenv, classSig); default: return prim(sig2prim(classSig)); } } // return the signature string for a Class object. // allocates 2 local refs function JNIClassSig(jenv, jcls) { var jenvpp = function() { return jenv.contents.contents; }; var jclscls = jenvpp().FindClass(jenv, "java/lang/Class"); var jmtd = jenvpp().GetMethodID(jenv, jclscls, "getName", "()Ljava/lang/String;"); var name = jenvpp().CallObjectMethod(jenv, jcls, jmtd); name = JNIReadString(jenv, name); // API is weird. Make sure we're using slashes not dots name = name.replace(/\./g, '/'); // special case primitives, arrays if (name.charAt(0)==='[') return name; switch(name) { case 'void': return 'V'; case 'boolean': return 'Z'; case 'byte': return 'B'; case 'char': return 'C'; case 'short': return 'S'; case 'int': return 'I'; case 'long': return 'J'; case 'float': return 'F'; case 'double': return 'D'; default: return 'L' + name + ';'; } } // create dispatch method // we resolve overloaded methods only by # of arguments. If you need // further resolution, use the 'long form' of the method name, ie: // obj['toString()Ljava/lang/String'].call(obj); var overloadFunc = function(basename) { return function() { return this[basename+'('+arguments.length+')'].apply(this, arguments); }; }; // Create appropriate wrapper fields/methods for a Java class. function JNILoadClass(jenv, classSig, opt_props) { var jenvpp = function() { return jenv.contents.contents; }; var props = opt_props || {}; // allocate a local reference frame with enough space // this class (1 or 2 local refs) plus superclass (3 refs) // plus array element class (1 or 2 local refs) var numLocals = 7; jenvpp().PushLocalFrame(jenv, numLocals); var jcls; if (Object.hasOwnProperty.call(registry, classSig)) { jcls = unwrap(registry[classSig]); } else { jcls = jenvpp().NewGlobalRef(jenv, JNIClassObj(jenv, classSig)); // get name of superclass var jsuper = jenvpp().GetSuperclass(jenv, jcls); if (jsuper.isNull()) { jsuper = null; } else { jsuper = JNIClassSig(jenv, jsuper); } registry[classSig] = Object.create(jsuper?ensureLoaded(jenv, jsuper):null); registry[classSig][PREFIX+'obj'] = jcls; // global ref, persistent. registry[classSig][PREFIX+'proto'] = function(o) { this[PREFIX+'obj'] = o; }; registry[classSig][PREFIX+'proto'].prototype = Object.create(jsuper ? ensureLoaded(jenv, jsuper)[PREFIX+'proto'].prototype : null); // Add a __cast__ method to the wrapper corresponding to the class registry[classSig].__cast__ = function(obj) { return wrap(unwrap(obj), classSig); }; // make wrapper accessible via the classes object. var path = sig2type(classSig).toLowerCase(); if (classSig.charAt(0)==='L') { path = classSig.substring(1, classSig.length-1); } if (classSig.charAt(0)!=='[') { var root = classes, i; var parts = path.split('/'); for (i = 0; i < parts.length-1; i++) { if (!Object.hasOwnProperty.call(root, parts[i])) { root[parts[i]] = Object.create(null); } root = root[parts[i]]; } root[parts[parts.length-1]] = registry[classSig]; } } var r = registry[classSig]; var rpp = r[PREFIX+'proto'].prototype; if (classSig.charAt(0)==='[') { // add 'length' field for arrays Object.defineProperty(rpp, 'length', { get: function() { return jenvpp().GetArrayLength(jenv, unwrap(this)); } }); // add 'get' and 'set' methods, 'new' constructor var elemSig = classSig.substring(1); ensureLoaded(jenv, elemSig); registry[elemSig].__array__ = r; if (!Object.hasOwnProperty.call(registry[elemSig], 'array')) registry[elemSig].array = r; if (elemSig.charAt(0)==='L' || elemSig.charAt(0)==='[') { var elemClass = unwrap(registry[elemSig]); rpp.get = function(idx) { return wrap(jenvpp().GetObjectArrayElement(jenv, unwrap(this), idx), elemSig); }; rpp.set = function(idx, value) { jenvpp().SetObjectArrayElement(jenv, unwrap(this), idx, unwrap(value, jenv, jobject)); }; rpp.getElements = function(start, len) { var i, r=[]; for (i=0; i sig2ctype(s)); var returnSig = mtd.sig.substring(mtd.sig.indexOf(')')+1); var ty = sig2type(returnSig), nm = returnSig; var call = "CallStatic"+ty+"Method"; ensureLoaded(jenv, nm); r[mtd.name] = rpp[mtd.name] = overloadFunc(mtd.name); r[mtd.name + mtd.sig] = r[mtd.name+'('+(argctypes.length-1)+')'] = // add static methods to object instances, too. rpp[mtd.name + mtd.sig] = rpp[mtd.name+'('+(argctypes.length-1)+')'] = function() { var i, j = jenvpp(); var args = [jenv, jcls, jmtd]; for (i=0; i sig2ctype(s)); var returnSig = mtd.sig.substring(mtd.sig.indexOf(')')+1); r['new'] = overloadFunc('new'); r['new'+mtd.sig] = r['new('+(argctypes.length-1)+')'] = function() { var i, j = jenvpp(); var args = [jenv, jcls, jmtd]; for (i=0; i sig2ctype(s)); var returnSig = mtd.sig.substring(mtd.sig.indexOf(')')+1); var ty = sig2type(returnSig), nm = returnSig; var call = "Call"+ty+"Method"; ensureLoaded(jenv, nm); rpp[mtd.name] = overloadFunc(mtd.name); rpp[mtd.name + mtd.sig] = rpp[mtd.name+'('+(argctypes.length-1)+')'] = function() { var i, j = jenvpp(); var args = [jenv, unwrap(this), jmtd]; for (i=0; i