Srdjan Petrovic | 6f6b2c0 | 2014-07-11 12:36:23 -0700 | [diff] [blame] | 1 | // +build android |
| 2 | |
| 3 | package jni |
| 4 | |
| 5 | import ( |
| 6 | "fmt" |
| 7 | "runtime" |
| 8 | |
| 9 | "veyron/runtimes/google/jni/util" |
| 10 | "veyron2/security" |
| 11 | ) |
| 12 | |
| 13 | // #cgo LDFLAGS: -ljniwrapper |
| 14 | // #include "jni_wrapper.h" |
| 15 | // |
| 16 | // // CGO doesn't support variadic functions so we have to hard-code these |
| 17 | // // functions to match the invoking code. Ugh! |
| 18 | // static jobject CallCaveatNewContextObject(JNIEnv* env, jclass class, jmethodID id, jlong goContextPtr) { |
| 19 | // return (*env)->NewObject(env, class, id, goContextPtr); |
| 20 | // } |
| 21 | // static void CallCaveatValidateMethod(JNIEnv* env, jobject obj, jmethodID id, jobject context) { |
| 22 | // return (*env)->CallVoidMethod(env, obj, id, context); |
| 23 | // } |
| 24 | import "C" |
| 25 | |
| 26 | func newCaveat(env *C.JNIEnv, jCaveat C.jobject) *caveat { |
| 27 | // We cannot cache Java environments as they are only valid in the current |
| 28 | // thread. We can, however, cache the Java VM and obtain an environment |
| 29 | // from it in whatever thread happens to be running at the time. |
| 30 | var jVM *C.JavaVM |
| 31 | if status := C.GetJavaVM(env, &jVM); status != 0 { |
| 32 | panic("couldn't get Java VM from the (Java) environment") |
| 33 | } |
| 34 | // Reference Java service caveat; it will be de-referenced when the go |
| 35 | // service caveat created below is garbage-collected (through the finalizer |
| 36 | // callback we setup just below). |
| 37 | jCaveat = C.NewGlobalRef(env, jCaveat) |
| 38 | c := &caveat{ |
| 39 | jVM: jVM, |
| 40 | jCaveat: jCaveat, |
| 41 | } |
| 42 | runtime.SetFinalizer(c, func(c *caveat) { |
| 43 | var env *C.JNIEnv |
| 44 | C.AttachCurrentThread(c.jVM, &env, nil) |
| 45 | defer C.DetachCurrentThread(c.jVM) |
| 46 | C.DeleteGlobalRef(env, c.jCaveat) |
| 47 | }) |
| 48 | return c |
| 49 | } |
| 50 | |
| 51 | type caveat struct { |
| 52 | jVM *C.JavaVM |
| 53 | jCaveat C.jobject |
| 54 | } |
| 55 | |
| 56 | func (c *caveat) Validate(context security.Context) error { |
| 57 | var env *C.JNIEnv |
| 58 | C.AttachCurrentThread(c.jVM, &env, nil) |
| 59 | defer C.DetachCurrentThread(c.jVM) |
| 60 | util.GoRef(&context) // un-refed when the Java Context object is finalized. |
Benjamin Prosnitz | b06a93b | 2014-07-15 15:43:18 -0700 | [diff] [blame] | 61 | cid := C.jmethodID(util.JMethodIDPtrOrDie(env, jContextImplClass, "<init>", fmt.Sprintf("(%s)%s", util.LongSign, util.VoidSign))) |
Srdjan Petrovic | ec6f511 | 2014-07-22 14:41:54 -0700 | [diff] [blame^] | 62 | jContext := C.CallCaveatNewContextObject(env, jContextImplClass, cid, C.jlong(util.PtrValue(&context))) |
Srdjan Petrovic | 6f6b2c0 | 2014-07-11 12:36:23 -0700 | [diff] [blame] | 63 | contextSign := "Lcom/veyron2/security/Context;" |
Benjamin Prosnitz | b06a93b | 2014-07-15 15:43:18 -0700 | [diff] [blame] | 64 | mid := C.jmethodID(util.JMethodIDPtrOrDie(env, C.GetObjectClass(env, c.jCaveat), "validate", fmt.Sprintf("(%s)%s", contextSign, util.VoidSign))) |
Srdjan Petrovic | 6f6b2c0 | 2014-07-11 12:36:23 -0700 | [diff] [blame] | 65 | C.CallCaveatValidateMethod(env, c.jCaveat, mid, jContext) |
| 66 | return util.JExceptionMsg(env) |
| 67 | } |