From 86264a3b23aff4e93bb8e821c7c744c21f499998 Mon Sep 17 00:00:00 2001 From: "beard%netscape.com" Date: Sat, 20 Feb 1999 02:27:18 +0000 Subject: [PATCH] First Checked In. --- plugin/oji/MRJ/plugin/Source/CSecureEnv.cpp | 1972 +++++++++++++++++ plugin/oji/MRJ/plugin/Source/CSecureEnv.h | 405 ++++ .../oji/MRJ/plugin/Source/MRJPlugin_config.h | 28 + 3 files changed, 2405 insertions(+) create mode 100644 plugin/oji/MRJ/plugin/Source/CSecureEnv.cpp create mode 100644 plugin/oji/MRJ/plugin/Source/CSecureEnv.h create mode 100644 plugin/oji/MRJ/plugin/Source/MRJPlugin_config.h diff --git a/plugin/oji/MRJ/plugin/Source/CSecureEnv.cpp b/plugin/oji/MRJ/plugin/Source/CSecureEnv.cpp new file mode 100644 index 00000000000..9d1cf463302 --- /dev/null +++ b/plugin/oji/MRJ/plugin/Source/CSecureEnv.cpp @@ -0,0 +1,1972 @@ +/* + * The contents of this file are subject to the Netscape Public License + * Version 1.0 (the "NPL"); you may not use this file except in + * compliance with the NPL. You may obtain a copy of the NPL at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the NPL is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL + * for the specific language governing rights and limitations under the + * NPL. + * + * The Initial Developer of this code under the NPL is + * Sun Microsystems, Inc. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All Rights + * Reserved. + */ + +/* + CSecureEnv.cpp + + Rewritten for use with MRJ plugin by Patrick C. Beard. Just forwards all + calls through the underlying JNIEnv that this wraps. Eventually, it will + communicate with the underlying threads using a message queue. + */ + +#include "CSecureEnv.h" +#include "nsISecurityContext.h" + +#include "MRJPlugin.h" +#include "MRJSession.h" +#include "nsIThreadManager.h" +#include "nsIJVMManager.h" + +#include "MRJMonitor.h" +#include "NativeMonitor.h" +#include "JavaMessageQueue.h" + +#if 0 +static NS_DEFINE_IID(kISecureEnvIID, NS_ISECUREENV_IID); +static NS_DEFINE_IID(kIRunnableIID, NS_IRUNNABLE_IID); +static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID); +#endif + +JavaMessageQueue::JavaMessageQueue(Monitor* monitor) + : mFirst(NULL), mLast(NULL), mMonitor(monitor) +{ +} + +void JavaMessageQueue::putMessage(JavaMessage* msg) +{ + if (mFirst == NULL) { + mFirst = mLast = msg; + } else { + mLast->setNext(msg); + mLast = msg; + } + msg->setNext(NULL); +} + +JavaMessage* JavaMessageQueue::getMessage() +{ + JavaMessage* msg = mFirst; + if (msg != NULL) { + mFirst = mFirst->getNext(); + if (mFirst == NULL) mLast = NULL; + } + return msg; +} + +void JavaMessageQueue::enter() +{ + mMonitor->enter(); +} + +void JavaMessageQueue::exit() +{ + mMonitor->exit(); +} + +void JavaMessageQueue::wait() +{ + mMonitor->wait(); +} + +void JavaMessageQueue::wait(long long millis) +{ + mMonitor->wait(millis); +} + +void JavaMessageQueue::notify() +{ + mMonitor->notify(); +} + +/** + * Native run method that communicates with LiveConnect from a Java thread. + */ +static void netscape_oji_JNIThread_run(JNIEnv* env, jobject self) +{ + CSecureEnv* secureEnv = NULL; + jmethodID yieldMethod = NULL; + jmethodID sleepMethod = NULL; + + jclass clazz = env->GetObjectClass(self); + if (clazz != NULL) { + // the field fSecureEnv contains a pointer to a CSecureEnv. + jfieldID fSecureEnvField = env->GetFieldID(clazz, "fSecureEnv", "I"); + if (fSecureEnvField != NULL) { + secureEnv = (CSecureEnv*) env->GetIntField(self, fSecureEnvField); + } + yieldMethod = env->GetStaticMethodID(clazz, "yield", "()V"); + sleepMethod = env->GetStaticMethodID(clazz, "sleep", "(J)V"); + } + + // notify the secure JNI that we are here, and wait for messages to arrive. + if (secureEnv != NULL) { + jboolean isRunning = true; + MRJSession* session = secureEnv->getSession(); + MRJMonitor requestMonitor(session, self); + MRJMonitor replyMonitor(session); + // NativeMonitor replyMonitor(secureEnv->getThreadManager()); + JavaMessageQueue requests(&requestMonitor), replies(&replyMonitor); + secureEnv->initialize(env, &isRunning, &requests, &replies); + + // when this thread is running, no other thread can enter the request queue monitor. + requests.enter(); + + while (isRunning) { + // the protocol for now is dead simple: get a message from the + // requests message queue, process it, and then put it back in + // the replies queue. This will get more elaborate to handle + // upcall requests. + JavaMessage* msg = requests.getMessage(); + if (msg != NULL) { + msg->execute(env); + replies.putMessage(msg); + replies.notify(); + } else { + // should we do sleep, timed wait, or what? + // env->CallStaticVoidMethod(clazz, yieldMethod); + // env->CallStaticVoidMethod(clazz, sleepMethod, jlong(kDefaultJMTime)); + requests.wait(); + } + } + + requests.exit(); + } +} + +/** + * Called from browser side, starts the Java thread that calls from LiveConnect to Java + * are processed in. + */ +static void CreateJNIThread(CSecureEnv* secureEnv) +{ + nsIThreadManager* manager = secureEnv->getThreadManager(); + MRJSession* session = secureEnv->getSession(); + JNIEnv* env = session->getCurrentEnv(); + jclass JNIThreadClass = env->FindClass("netscape/oji/JNIThread"); + if (JNIThreadClass != NULL) { + JNINativeMethod method = { "run", "()V", &netscape_oji_JNIThread_run }; + env->RegisterNatives(JNIThreadClass, &method, 1); + jmethodID constructorID = env->GetMethodID(JNIThreadClass, "", "(I)V"); + if (constructorID != NULL) { + jobject javaThread = env->NewObject(JNIThreadClass, constructorID, secureEnv); + for (;;) { + // give time to Java, to allow the thread to come up. + session->idle(kDefaultJMTime); + // has the thread made contact? + if (secureEnv->isInitialized()) + break; + // give time to NSPR, to avoid hanging too long. + manager->Sleep(); + } + } + } +} + +/** + * Creates a new native thread in MRJ's main thread, to avoid deadlock problems. + */ +class CreateNativeThreadMessage : public NativeMessage { + nsresult* mResult; + PRUint32* mThreadID; + CSecureEnv* mSecureEnv; +public: + CreateNativeThreadMessage(nsresult* outResult, PRUint32* outThreadID, CSecureEnv* secureEnv) + : mResult(outResult), mThreadID(outThreadID), mSecureEnv(secureEnv) + { + } + + virtual void execute() + { + nsIThreadManager* manager = mSecureEnv->getThreadManager(); + *mResult = manager->CreateThread(mThreadID, mSecureEnv); + } +}; + +/** + * Called from a Java thread that wants to communicate with the browser. + */ +static void CreateNativeThread(CSecureEnv* secureEnv) +{ + nsresult result; + PRUint32 threadID; + MRJSession* session = secureEnv->getSession(); + + // cause a native thread to be created on our behalf. Perhaps this should be a message we send to the + // session itself. otherwise we could have reentrancy problems. + CreateNativeThreadMessage message(&result, &threadID, secureEnv); + session->sendMessage(&message); + + if (session->onMainThread()) { + // give time to other native threads, so the new thread can come up. + nsIThreadManager* manager = secureEnv->getThreadManager(); + while (!secureEnv->isInitialized()) { + manager->Sleep(); + } + } else { + // sleep the current Java thread until we rendezvous with the Native thread. + JNIEnv* env = session->getCurrentEnv(); + jclass threadClass = env->FindClass("java/lang/Thread"); + if (threadClass != NULL) { + jmethodID sleepMethod = env->GetStaticMethodID(threadClass, "sleep", "(J)V"); + if (sleepMethod != NULL) { + while (!secureEnv->isInitialized()) + env->CallStaticVoidMethod(threadClass, sleepMethod, jlong(kDefaultJMTime)); + } + env->DeleteLocalRef(threadClass); + } + } +} + +/** + * Runs the server thread for LiveConnect upcalls from spontaneous Java threads. + */ +NS_IMETHODIMP CSecureEnv::Run() +{ + jboolean isRunning = true; + NativeMonitor requestMonitor(mSession, mThreadManager); + MRJMonitor replyMonitor(mSession); + JavaMessageQueue requests(&requestMonitor), replies(&replyMonitor); + // initialize(env, self, &isRunning, &requests, &replies); + + // we have to create the Proxy JNI here, so it associated with this thread. + nsIJVMManager* manager = mPlugin->getManager(); + manager->CreateProxyJNI(this, &mProxyEnv); + + mIsRunning = &isRunning; + mNativeQueue = &requests; + mJavaQueue = &replies; + + // when this thread is running, no other thread can enter the request queue monitor. + requests.enter(); + + while (isRunning) { + // the protocol for now is dead simple: get a message from the + // requests message queue, process it, and then put it back in + // the replies queue. This will get more elaborate to handle + // upcall requests. + JavaMessage* msg = requests.getMessage(); + if (msg != NULL) { + msg->execute(mProxyEnv); + replies.putMessage(msg); + replies.notify(); + } else { + // should we do sleep, timed wait, or what? + // env->CallStaticVoidMethod(clazz, yieldMethod); + // env->CallStaticVoidMethod(clazz, sleepMethod, jlong(kDefaultJMTime)); + requests.wait(); + } + } + + requests.exit(); + + return NS_OK; +} + +/** + * Used to send a message from Native to Java threads. + */ +void CSecureEnv::sendMessageToJava(JavaMessage* msg) +{ + messageLoop(mProxyEnv, msg, mJavaQueue, mNativeQueue, true); +} + +/** + * Used to send a message from Java to Native threads. + */ +void CSecureEnv::sendMessageFromJava(JNIEnv* javaEnv, JavaMessage* msg, Boolean busyWaiting) +{ + messageLoop(javaEnv, msg, mNativeQueue, mJavaQueue, busyWaiting); +} + +//////////////////////////////////////////////////////////////////////////// +// from nsISupports and AggregatedQueryInterface: + +// Thes macro expands to the aggregated query interface scheme. + +#if 0 +NS_IMPL_AGGREGATED(CSecureEnv); + +NS_METHOD +CSecureEnv::AggregatedQueryInterface(const nsIID& aIID, void** aInstancePtr) +{ + if (aIID.Equals(kISupportsIID)) { + *aInstancePtr = GetInner(); + AddRef(); + return NS_OK; + } + if (aIID.Equals(kISecureEnvIID)) { + *aInstancePtr = (nsISecureEnv*) this; + AddRef(); + return NS_OK; + } + if (aIID.Equals(kIRunnableIID)) { + *aInstancePtr = (nsIRunnable*) this; + AddRef(); + return NS_OK; + } + return NS_NOINTERFACE; +} +#endif + +const InterfaceInfo CSecureEnv::sInterfaces[] = { + { NS_ISECUREENV_IID, INTERFACE_OFFSET(CSecureEnv, nsISecureEnv) }, + { NS_IRUNNABLE_IID, INTERFACE_OFFSET(CSecureEnv, nsIRunnable) }, +}; +const UInt32 CSecureEnv::kInterfaceCount = sizeof(sInterfaces) / sizeof(InterfaceInfo); + +///=--------------------------------------------------------------------------= +// CSecureEnv::CSecureEnv +///=--------------------------------------------------------------------------= +// Implements the CSecureJNI object for creating object, invoking method, +// getting/setting field in JNI with security context. +// +// parameters : +// +// return : +// +// notes : +// +CSecureEnv::CSecureEnv(MRJPlugin* plugin, JNIEnv* proxyEnv, JNIEnv* javaEnv) + : SupportsMixin(this, sInterfaces, kInterfaceCount), + mPlugin(plugin), mProxyEnv(proxyEnv), mJavaEnv(javaEnv), + mSession(plugin->getSession()), mThreadManager(plugin->getThreadManager()), + mIsRunning(NULL), mJavaQueue(NULL), mNativeQueue(NULL) +{ + // need to create the JNIThread for communicating with Java. + if (mJavaEnv != NULL) + CreateNativeThread(this); + else + CreateJNIThread(this); +} + + +///=--------------------------------------------------------------------------= +// CSecureEnv::~CSecureEnv +///=--------------------------------------------------------------------------= +// Implements the CSecureEnv object for creating object, invoking method, +// getting/setting field in JNI with security context. +// +// parameters : +// +// return : +// +// notes : +// +CSecureEnv::~CSecureEnv() +{ + // Tell the Java thread to die. + if (mIsRunning != NULL) { + *mIsRunning = false; + mJavaQueue->notify(); + } +} + +void CSecureEnv::initialize(JNIEnv* javaEnv, jboolean* isRunning, JavaMessageQueue* javaQueue, JavaMessageQueue* nativeQueue) +{ + mJavaEnv = javaEnv; + mIsRunning = isRunning; + mJavaQueue = javaQueue; + mNativeQueue = nativeQueue; +} + +///=--------------------------------------------------------------------------= +// CSecureEnv::Create +///=--------------------------------------------------------------------------= +// Create the CSecureEnv object for creating object, invoking method, +// getting/setting field in JNI with security context. +// +// parameters : +// +// return : +// +// notes : +// +NS_METHOD +CSecureEnv::Create(MRJPlugin* plugin, JNIEnv* proxyEnv, const nsIID& aIID, void* *aInstancePtr) +{ + CSecureEnv* secureEnv = new CSecureEnv(plugin, proxyEnv); + if (secureEnv == NULL) + return NS_ERROR_OUT_OF_MEMORY; + nsresult result = secureEnv->QueryInterface(aIID, aInstancePtr); + if (result != NS_OK) { + delete secureEnv; + return result; + } + return NS_OK; +} + +//////////////////////////////////////////////////////////////////////////// +// from nsISecureJNI: +// + + +///=--------------------------------------------------------------------------= +// CSecureEnv::NewObject +///=--------------------------------------------------------------------------= +// Create new Java object in LiveConnect. +// +// @param env -- JNIEnv pointer. +// @param clazz -- Java Class object. +// @param methodID -- Method id +// @param args -- arguments for invoking the constructor. +// @param result -- return new Java object. +// @param ctx -- security context +// + +class NewObjectMessage : public JavaMessage { + jclass clazz; + jmethodID methodID; + jvalue* args; + jobject* result; + +public: + NewObjectMessage(jclass clazz, jmethodID methodID, jvalue *args, jobject* result) + { + this->clazz = clazz; + this->methodID = methodID; + this->args = args; + this->result = result; + } + + virtual void execute(JNIEnv* env) + { + *result = env->NewObjectA(clazz, methodID, args); + } +}; + +NS_IMETHODIMP CSecureEnv::NewObject(/*[in]*/ jclass clazz, + /*[in]*/ jmethodID methodID, + /*[in]*/ jvalue *args, + /*[out]*/ jobject* result, + /*[in]*/ nsISecurityContext* ctx) +{ + if (clazz == NULL || methodID == NULL) + return NS_ERROR_NULL_POINTER; + + // Call method on Java side + NewObjectMessage msg(clazz, methodID, args, result); + sendMessageToJava(&msg); + // *result = m_env->NewObjectA(clazz, methodID, args); + + return NS_OK; +} + + +///=--------------------------------------------------------------------------= +// CSecureEnv::CallMethod +///=--------------------------------------------------------------------------= +// Invoke method on Java object in LiveConnect. +// +// @param type -- Return type +// @param obj -- Java object. +// @param methodID -- Method id +// @param result -- return result of invocation. +// @param ctx -- security context +// + +class CallMethodMessage : public JavaMessage { + jni_type type; + jobject obj; + jmethodID methodID; + jvalue* args; + jvalue* result; + +public: + CallMethodMessage(jni_type type, jobject obj, jmethodID methodID, jvalue *args, jvalue* result) + { + this->type = type; + this->obj = obj; + this->methodID = methodID; + this->args = args; + this->result = result; + } + + virtual void execute(JNIEnv* env) + { + switch (type) { + case jobject_type: + result->l = env->CallObjectMethodA(obj, methodID, args); + break; + case jboolean_type: + result->z = env->CallBooleanMethodA(obj, methodID, args); + break; + case jbyte_type: + result->b = env->CallByteMethodA(obj, methodID, args); + break; + case jchar_type: + result->c = env->CallCharMethodA(obj, methodID, args); + break; + case jshort_type: + result->s = env->CallShortMethodA(obj, methodID, args); + break; + case jint_type: + result->i = env->CallIntMethodA(obj, methodID, args); + break; + case jlong_type: + result->j = env->CallLongMethodA(obj, methodID, args); + break; + case jfloat_type: + result->f = env->CallFloatMethodA(obj, methodID, args); + break; + case jdouble_type: + result->d = env->CallDoubleMethodA(obj, methodID, args); + break; + case jvoid_type: + env->CallVoidMethodA(obj, methodID, args); + break; + } + } +}; + +NS_IMETHODIMP CSecureEnv::CallMethod(/*[in]*/ jni_type type, + /*[in]*/ jobject obj, + /*[in]*/ jmethodID methodID, + /*[in]*/ jvalue *args, + /*[out]*/ jvalue* result, + /*[in]*/ nsISecurityContext* ctx) +{ + if (obj == NULL || methodID == NULL) + return NS_ERROR_NULL_POINTER; + + // Call method on Java side + // return CallJavaMethod(obj, method, args, ctx, result); + CallMethodMessage msg(type, obj, methodID, args, result); + sendMessageToJava(&msg); + + return NS_OK; +} + + +///=--------------------------------------------------------------------------= +// CSecureEnv::CallNonvirtualMethod +///=--------------------------------------------------------------------------= +// Invoke non-virtual method on Java object in LiveConnect. +// +// @param obj -- Java object. +// @param methodID -- Method id +// @param args -- arguments for invoking the constructor. +// @param result -- return result of invocation. +// @param ctx -- security context +// + +class CallNonvirtualMethodMessage : public JavaMessage { + jni_type type; + jobject obj; + jclass clazz; + jmethodID methodID; + jvalue* args; + jvalue* result; + +public: + CallNonvirtualMethodMessage(jni_type type, jobject obj, jclass clazz, jmethodID methodID, jvalue *args, jvalue* result) + { + this->type = type; + this->obj = obj; + this->clazz = clazz; + this->methodID = methodID; + this->args = args; + this->result = result; + } + + virtual void execute(JNIEnv* env) + { + switch (type) { + case jobject_type: + result->l = env->CallNonvirtualObjectMethodA(obj, clazz, methodID, args); + break; + case jboolean_type: + result->z = env->CallNonvirtualBooleanMethodA(obj, clazz, methodID, args); + break; + case jbyte_type: + result->b = env->CallNonvirtualByteMethodA(obj, clazz, methodID, args); + break; + case jchar_type: + result->c = env->CallNonvirtualCharMethodA(obj, clazz, methodID, args); + break; + case jshort_type: + result->s = env->CallNonvirtualShortMethodA(obj, clazz, methodID, args); + break; + case jint_type: + result->i = env->CallNonvirtualIntMethodA(obj, clazz, methodID, args); + break; + case jlong_type: + result->j = env->CallNonvirtualLongMethodA(obj, clazz, methodID, args); + break; + case jfloat_type: + result->f = env->CallNonvirtualFloatMethodA(obj, clazz, methodID, args); + break; + case jdouble_type: + result->d = env->CallNonvirtualDoubleMethodA(obj, clazz, methodID, args); + break; + case jvoid_type: + env->CallNonvirtualVoidMethodA(obj, clazz, methodID, args); + break; + } + } +}; + +NS_IMETHODIMP CSecureEnv::CallNonvirtualMethod(/*[in]*/ jni_type type, + /*[in]*/ jobject obj, + /*[in]*/ jclass clazz, + /*[in]*/ jmethodID methodID, + /*[in]*/ jvalue *args, + /*[out]*/ jvalue* result, + /*[in]*/ nsISecurityContext* ctx) +{ + if (obj == NULL || clazz == NULL || methodID == NULL) + return NS_ERROR_NULL_POINTER; + + // Call non-virtual method on Java side + // return CallJavaMethod(obj, method, args, ctx, result); + CallNonvirtualMethodMessage msg(type, obj, clazz, methodID, args, result); + sendMessageToJava(&msg); + + return NS_OK; +} + + +///=--------------------------------------------------------------------------= +// CSecureEnv::GetField +///=--------------------------------------------------------------------------= +// Get a field on Java object in LiveConnect. +// +// @param obj -- Java object. +// @param fieldID -- field id +// @param result -- return field value +// @param ctx -- security context +// + +class GetFieldMessage : public JavaMessage { + jni_type type; + jobject obj; + jfieldID fieldID; + jvalue* args; + jvalue* result; + +public: + GetFieldMessage(jni_type type, jobject obj, jfieldID fieldID, jvalue *args, jvalue* result) + { + this->type = type; + this->obj = obj; + this->fieldID = fieldID; + this->args = args; + this->result = result; + } + + virtual void execute(JNIEnv* env) + { + switch (type) { + case jobject_type: + result->l = env->GetObjectField(obj, fieldID); + break; + case jboolean_type: + result->z = env->GetBooleanField(obj, fieldID); + break; + case jbyte_type: + result->b = env->GetByteField(obj, fieldID); + break; + case jchar_type: + result->c = env->GetCharField(obj, fieldID); + break; + case jshort_type: + result->s = env->GetShortField(obj, fieldID); + break; + case jint_type: + result->i = env->GetIntField(obj, fieldID); + break; + case jlong_type: + result->j = env->GetLongField(obj, fieldID); + break; + case jfloat_type: + result->f = env->GetFloatField(obj, fieldID); + break; + case jdouble_type: + result->d = env->GetDoubleField(obj, fieldID); + break; + } + } +}; + +NS_IMETHODIMP CSecureEnv::GetField(/*[in]*/ jni_type type, + /*[in]*/ jobject obj, + /*[in]*/ jfieldID fieldID, + /*[out]*/ jvalue* result, + /*[in]*/ nsISecurityContext* ctx) +{ + if (mJavaEnv == NULL || obj == NULL || fieldID == NULL) + return NS_ERROR_NULL_POINTER; + + // Get field on Java side + // return GetJavaField(obj, field, ctx, result); + + JNIEnv* env = mJavaEnv; + switch (type) { + case jobject_type: + result->l = env->GetObjectField(obj, fieldID); + break; + case jboolean_type: + result->z = env->GetBooleanField(obj, fieldID); + break; + case jbyte_type: + result->b = env->GetByteField(obj, fieldID); + break; + case jchar_type: + result->c = env->GetCharField(obj, fieldID); + break; + case jshort_type: + result->s = env->GetShortField(obj, fieldID); + break; + case jint_type: + result->i = env->GetIntField(obj, fieldID); + break; + case jlong_type: + result->j = env->GetLongField(obj, fieldID); + break; + case jfloat_type: + result->f = env->GetFloatField(obj, fieldID); + break; + case jdouble_type: + result->d = env->GetDoubleField(obj, fieldID); + break; + } + + return NS_OK; +} + + +///=--------------------------------------------------------------------------= +// CSecureEnv::SetField +///=--------------------------------------------------------------------------= +// +// Set a field on Java object in LiveConnect. +// +// @param obj -- Java object. +// @param fieldID -- field id +// @param result -- field value to set +// @param ctx -- security context +// +NS_IMETHODIMP CSecureEnv::SetField(/*[in]*/ jni_type type, + /*[in]*/ jobject obj, + /*[in]*/ jfieldID fieldID, + /*[in]*/ jvalue val, + /*[in]*/ nsISecurityContext* ctx) +{ + if (mJavaEnv == NULL || obj == NULL || fieldID == NULL) + return NS_ERROR_NULL_POINTER; + + // Set field on Java side + // return SetJavaField(obj, field, val, ctx); + + JNIEnv* env = mJavaEnv; + switch (type) { + case jobject_type: + env->SetObjectField(obj, fieldID, val.l); + break; + case jboolean_type: + env->SetBooleanField(obj, fieldID, val.z); + break; + case jbyte_type: + env->SetByteField(obj, fieldID, val.b); + break; + case jchar_type: + env->SetCharField(obj, fieldID, val.c); + break; + case jshort_type: + env->SetShortField(obj, fieldID, val.s); + break; + case jint_type: + env->SetIntField(obj, fieldID, val.i); + break; + case jlong_type: + env->SetLongField(obj, fieldID, val.j); + break; + case jfloat_type: + env->SetFloatField(obj, fieldID, val.f); + break; + case jdouble_type: + env->SetDoubleField(obj, fieldID, val.d); + break; + } + + return NS_OK; +} + + +///=--------------------------------------------------------------------------= +// CSecureEnv::CallStaticMethod +///=--------------------------------------------------------------------------= +// +// Invoke static method on Java object in LiveConnect. +// +// @param obj -- Java object. +// @param methodID -- method id +// @param args -- arguments for invoking the constructor. +// @param result -- return result of invocation. +// @param ctx -- security context +// + +class CallStaticMethodMessage : public JavaMessage { + jni_type type; + jclass clazz; + jmethodID methodID; + jvalue* args; + jvalue* result; + +public: + CallStaticMethodMessage(jni_type type, jclass clazz, jmethodID methodID, jvalue *args, jvalue* result) + { + this->type = type; + this->clazz = clazz; + this->methodID = methodID; + this->args = args; + this->result = result; + } + + virtual void execute(JNIEnv* env) + { + switch (type) { + case jobject_type: + result->l = env->CallStaticObjectMethodA(clazz, methodID, args); + break; + case jboolean_type: + result->z = env->CallStaticBooleanMethodA(clazz, methodID, args); + break; + case jbyte_type: + result->b = env->CallStaticByteMethodA(clazz, methodID, args); + break; + case jchar_type: + result->c = env->CallStaticCharMethodA(clazz, methodID, args); + break; + case jshort_type: + result->s = env->CallStaticShortMethodA(clazz, methodID, args); + break; + case jint_type: + result->i = env->CallStaticIntMethodA(clazz, methodID, args); + break; + case jlong_type: + result->j = env->CallStaticLongMethodA(clazz, methodID, args); + break; + case jfloat_type: + result->f = env->CallStaticFloatMethodA(clazz, methodID, args); + break; + case jdouble_type: + result->d = env->CallStaticDoubleMethodA(clazz, methodID, args); + break; + case jvoid_type: + env->CallStaticVoidMethodA(clazz, methodID, args); + break; + } + } +}; + +NS_IMETHODIMP CSecureEnv::CallStaticMethod(/*[in]*/ jni_type type, + /*[in]*/ jclass clazz, + /*[in]*/ jmethodID methodID, + /*[in]*/ jvalue *args, + /*[out]*/ jvalue* result, + /*[in]*/ nsISecurityContext* ctx) +{ + if (clazz == NULL || methodID == NULL) + return NS_ERROR_NULL_POINTER; + + // Call method on Java side + // return CallJavaMethod(NULL, method, args, ctx, result); + CallStaticMethodMessage msg(type, clazz, methodID, args, result); + sendMessageToJava(&msg); + + return NS_OK; +} + + +///=--------------------------------------------------------------------------= +// CSecureEnv::GetStaticField +///=--------------------------------------------------------------------------= +// Get a static field on Java object in LiveConnect. +// +// @param obj -- Java object. +// @param fieldID -- field id +// @param result -- return field value +// @param ctx -- security context +// + + +class GetStaticFieldMessage : public JavaMessage { + jni_type type; + jclass clazz; + jfieldID fieldID; + jvalue* args; + jvalue* result; + +public: + GetStaticFieldMessage(jni_type type, jclass clazz, jfieldID fieldID, jvalue* result) + { + this->type = type; + this->clazz = clazz; + this->fieldID = fieldID; + this->args = args; + this->result = result; + } + + virtual void execute(JNIEnv* env) + { + switch (type) { + case jobject_type: + result->l = env->GetStaticObjectField(clazz, fieldID); + break; + case jboolean_type: + result->z = env->GetStaticBooleanField(clazz, fieldID); + break; + case jbyte_type: + result->b = env->GetStaticByteField(clazz, fieldID); + break; + case jchar_type: + result->c = env->GetStaticCharField(clazz, fieldID); + break; + case jshort_type: + result->s = env->GetStaticShortField(clazz, fieldID); + break; + case jint_type: + result->i = env->GetStaticIntField(clazz, fieldID); + break; + case jlong_type: + result->j = env->GetStaticLongField(clazz, fieldID); + break; + case jfloat_type: + result->f = env->GetStaticFloatField(clazz, fieldID); + break; + case jdouble_type: + result->d = env->GetStaticDoubleField(clazz, fieldID); + break; + } + } +}; + +NS_IMETHODIMP CSecureEnv::GetStaticField(/*[in]*/ jni_type type, + /*[in]*/ jclass clazz, + /*[in]*/ jfieldID fieldID, + /*[out]*/ jvalue* result, + /*[in]*/ nsISecurityContext* ctx) +{ + if (mJavaEnv == NULL || clazz == NULL || fieldID == NULL) + return NS_ERROR_NULL_POINTER; + + // Get static field on Java side + // return GetJavaField(NULL, field, ctx, result); + // GetStaticFieldMessage msg(type, clazz, fieldID, result); + // sendMessageToJava(&msg); + + // should be able to perform in Java env. + JNIEnv* env = mJavaEnv; + switch (type) { + case jobject_type: + result->l = env->GetStaticObjectField(clazz, fieldID); + break; + case jboolean_type: + result->z = env->GetStaticBooleanField(clazz, fieldID); + break; + case jbyte_type: + result->b = env->GetStaticByteField(clazz, fieldID); + break; + case jchar_type: + result->c = env->GetStaticCharField(clazz, fieldID); + break; + case jshort_type: + result->s = env->GetStaticShortField(clazz, fieldID); + break; + case jint_type: + result->i = env->GetStaticIntField(clazz, fieldID); + break; + case jlong_type: + result->j = env->GetStaticLongField(clazz, fieldID); + break; + case jfloat_type: + result->f = env->GetStaticFloatField(clazz, fieldID); + break; + case jdouble_type: + result->d = env->GetStaticDoubleField(clazz, fieldID); + break; + } + + return NS_OK; +} + + +///=--------------------------------------------------------------------------= +// CSecureEnv::SetStaticField +///=--------------------------------------------------------------------------= +// Set a static field on Java object in LiveConnect. +// +// @param obj -- Java object. +// @param fieldID -- field id +// @param result -- field value to set +// @param ctx -- security context +// +NS_IMETHODIMP CSecureEnv::SetStaticField(/*[in]*/ jni_type type, + /*[in]*/ jclass clazz, + /*[in]*/ jfieldID fieldID, + /*[in]*/ jvalue val, + /*[in]*/ nsISecurityContext* ctx) +{ + if (mJavaEnv == NULL || clazz == NULL || fieldID == NULL) + return NS_ERROR_NULL_POINTER; + + // Set static field on Java side + // return SetJavaField(NULL, field, val, ctx); + + JNIEnv* env = mJavaEnv; + switch (type) { + case jobject_type: + env->SetStaticObjectField(clazz, fieldID, val.l); + break; + case jboolean_type: + env->SetStaticBooleanField(clazz, fieldID, val.z); + break; + case jbyte_type: + env->SetStaticByteField(clazz, fieldID, val.b); + break; + case jchar_type: + env->SetStaticCharField(clazz, fieldID, val.c); + break; + case jshort_type: + env->SetStaticShortField(clazz, fieldID, val.s); + break; + case jint_type: + env->SetStaticIntField(clazz, fieldID, val.i); + break; + case jlong_type: + env->SetStaticLongField(clazz, fieldID, val.j); + break; + case jfloat_type: + env->SetStaticFloatField(clazz, fieldID, val.f); + break; + case jdouble_type: + env->SetStaticDoubleField(clazz, fieldID, val.d); + break; + } + + return NS_OK; +} + + +NS_IMETHODIMP CSecureEnv::GetVersion(/*[out]*/ jint* version) +{ + if (version == NULL) + return NS_ERROR_NULL_POINTER; + + JNIEnv* env = mSession->getCurrentEnv(); + *version = env->GetVersion(); + + return NS_OK; +} + +/** + * To give proper "local" refs, need to run this in the Java thread. + */ +class DefineClassMessage : public JavaMessage { + const char* name; + jobject loader; + const jbyte *buf; + jsize len; + jclass* clazz; +public: + DefineClassMessage(const char* name, jobject loader, const jbyte *buf, jsize len, jclass* clazz) + { + this->name = name; + this->loader = loader; + this->buf = buf; + this->len = len; + this->clazz = clazz; + } + + virtual void execute(JNIEnv* env) + { + *clazz = env->DefineClass(name, loader, buf, len); + } +}; + +NS_IMETHODIMP CSecureEnv::DefineClass(/*[in]*/ const char* name, + /*[in]*/ jobject loader, + /*[in]*/ const jbyte *buf, + /*[in]*/ jsize len, + /*[out]*/ jclass* clazz) +{ + if (clazz == NULL) + return NS_ERROR_NULL_POINTER; + + DefineClassMessage msg(name, loader, buf, len, clazz); + sendMessageToJava(&msg); + + return NS_OK; +} + +/** + * To give proper "local" refs, need to run this in the Java thread. + */ +class FindClassMessage : public JavaMessage { + const char* name; + jclass* result; +public: + FindClassMessage(const char* name, jclass* result) + { + this->name = name; + this->result = result; + } + + virtual void execute(JNIEnv* env) + { + *result = env->FindClass(name); + } +}; + +NS_IMETHODIMP CSecureEnv::FindClass(/*[in]*/ const char* name, + /*[out]*/ jclass* clazz) +{ + if (clazz == NULL) + return NS_ERROR_NULL_POINTER; + + // JNIEnv* env = mSession->getCurrentEnv(); + // *clazz = env->FindClass(name); + FindClassMessage msg(name, clazz); + sendMessageToJava(&msg); + + return NS_OK; +} + +/** + * To give proper "local" refs, need to run this in the Java thread. + */ +class GetSuperclassMessage : public JavaMessage { + jclass sub; + jclass* super; +public: + GetSuperclassMessage(jclass sub, jclass* super) + { + this->sub = sub; + this->super = super; + } + + virtual void execute(JNIEnv* env) + { + *super = env->GetSuperclass(sub); + } +}; + +NS_IMETHODIMP CSecureEnv::GetSuperclass(/*[in]*/ jclass sub, + /*[out]*/ jclass* super) +{ + if (mJavaEnv == NULL || super == NULL) + return NS_ERROR_NULL_POINTER; + + // GetSuperclassMessage msg(sub, super); + // sendMessageToJava(&msg); + *super = mJavaEnv->GetSuperclass(sub); + + return NS_OK; +} + + +NS_IMETHODIMP CSecureEnv::IsAssignableFrom(/*[in]*/ jclass sub, + /*[in]*/ jclass super, + /*[out]*/ jboolean* result) +{ + if (mJavaEnv == NULL || result == NULL) + return NS_ERROR_NULL_POINTER; + + // JNIEnv* env = mSession->getCurrentEnv(); + // *result = env->IsAssignableFrom(sub, super); + *result = mJavaEnv->IsAssignableFrom(sub, super); + + return NS_OK; +} + + +NS_IMETHODIMP CSecureEnv::Throw(/*[in]*/ jthrowable obj, + /*[out]*/ jint* result) +{ + if (mJavaEnv == NULL || result == NULL) + return NS_ERROR_NULL_POINTER; + + // Huh? This doesn't really make sense. + + *result = mJavaEnv->Throw(obj); + + return NS_OK; +} + +NS_IMETHODIMP CSecureEnv::ThrowNew(/*[in]*/ jclass clazz, + /*[in]*/ const char *msg, + /*[out]*/ jint* result) +{ + if (mJavaEnv == NULL || result == NULL) + return NS_ERROR_NULL_POINTER; + + *result = mJavaEnv->ThrowNew(clazz, msg); + + return NS_OK; +} + + +NS_IMETHODIMP CSecureEnv::ExceptionOccurred(/*[out]*/ jthrowable* result) +{ + if (mJavaEnv == NULL || result == NULL) + return NS_ERROR_NULL_POINTER; + + *result = mJavaEnv->ExceptionOccurred(); + + return NS_OK; +} + +NS_IMETHODIMP CSecureEnv::ExceptionDescribe(void) +{ + if (mJavaEnv == NULL) + return NS_ERROR_NULL_POINTER; + + mJavaEnv->ExceptionDescribe(); + + return NS_OK; +} + + +NS_IMETHODIMP CSecureEnv::ExceptionClear(void) +{ + mJavaEnv->ExceptionClear(); + + return NS_OK; +} + + +NS_IMETHODIMP CSecureEnv::FatalError(/*[in]*/ const char* msg) +{ + mJavaEnv->FatalError(msg); + + return NS_OK; +} + + +/** + * To give proper "local" refs, need to run this in the true thread. + */ +NS_IMETHODIMP CSecureEnv::NewGlobalRef(/*[in]*/ jobject localRef, + /*[out]*/ jobject* result) +{ + if (result == NULL) + return NS_ERROR_NULL_POINTER; + + // *result = mJavaEnv->NewGlobalRef(localRef); + class NewGlobalRefMessage : public JavaMessage { + jobject localRef; + jobject* result; + public: + NewGlobalRefMessage(jobject localRef, jobject* result) + { + this->localRef = localRef; + this->result = result; + } + + virtual void execute(JNIEnv* env) + { + *result = env->NewGlobalRef(localRef); + } + } msg(localRef, result); + sendMessageToJava(&msg); + + return NS_OK; +} + + +NS_IMETHODIMP CSecureEnv::DeleteGlobalRef(/*[in]*/ jobject globalRef) +{ + JNIEnv* env = mSession->getCurrentEnv(); + env->DeleteGlobalRef(globalRef); + return NS_OK; +} + +/** + * To give proper "local" refs, need to run this in the true thread. + */ +class DeleteLocalRefMessage : public JavaMessage { + jobject localRef; +public: + DeleteLocalRefMessage(jobject localRef) + { + this->localRef = localRef; + } + + virtual void execute(JNIEnv* env) + { + env->DeleteLocalRef(localRef); + } +}; + +NS_IMETHODIMP CSecureEnv::DeleteLocalRef(/*[in]*/ jobject obj) +{ + mJavaEnv->DeleteLocalRef(obj); + return NS_OK; +} + +NS_IMETHODIMP CSecureEnv::IsSameObject(/*[in]*/ jobject obj1, + /*[in]*/ jobject obj2, + /*[out]*/ jboolean* result) +{ + if (mJavaEnv == NULL || result == NULL) + return NS_ERROR_NULL_POINTER; + + *result = mJavaEnv->IsSameObject(obj1, obj2); + + return NS_OK; +} + + +NS_IMETHODIMP CSecureEnv::AllocObject(/*[in]*/ jclass clazz, + /*[out]*/ jobject* result) +{ + if (mJavaEnv == NULL || result == NULL) + return NS_ERROR_NULL_POINTER; + + *result = mJavaEnv->AllocObject(clazz); + + return NS_OK; +} + + +NS_IMETHODIMP CSecureEnv::GetObjectClass(/*[in]*/ jobject obj, + /*[out]*/ jclass* result) +{ + if (mJavaEnv == NULL || result == NULL) + return NS_ERROR_NULL_POINTER; + + *result = mJavaEnv->GetObjectClass(obj); + + return NS_OK; +} + + +NS_IMETHODIMP CSecureEnv::IsInstanceOf(/*[in]*/ jobject obj, + /*[in]*/ jclass clazz, + /*[out]*/ jboolean* result) +{ + if (mJavaEnv == NULL || result == NULL) + return NS_ERROR_NULL_POINTER; + + *result = mJavaEnv->IsInstanceOf(obj, clazz); + + return NS_OK; +} + + +NS_IMETHODIMP CSecureEnv::GetMethodID(/*[in]*/ jclass clazz, + /*[in]*/ const char* name, + /*[in]*/ const char* sig, + /*[out]*/ jmethodID* result) +{ + if (result == NULL) + return NS_ERROR_NULL_POINTER; + + // run this on the *CURRENT* thread. + JNIEnv* env = mSession->getCurrentEnv(); + *result = env->GetMethodID(clazz, name, sig); + + return NS_OK; +} + + +NS_IMETHODIMP CSecureEnv::GetFieldID(/*[in]*/ jclass clazz, + /*[in]*/ const char* name, + /*[in]*/ const char* sig, + /*[out]*/ jfieldID* result) +{ + if (result == NULL) + return NS_ERROR_NULL_POINTER; + + // run this on the *CURRENT* thread. + JNIEnv* env = mSession->getCurrentEnv(); + *result = env->GetFieldID(clazz, name, sig); + + return NS_OK; +} + + +NS_IMETHODIMP CSecureEnv::GetStaticMethodID(/*[in]*/ jclass clazz, + /*[in]*/ const char* name, + /*[in]*/ const char* sig, + /*[out]*/ jmethodID* result) +{ + if (result == NULL) + return NS_ERROR_NULL_POINTER; + + // run this on the *CURRENT* thread. + JNIEnv* env = mSession->getCurrentEnv(); + *result = env->GetStaticMethodID(clazz, name, sig); + + return NS_OK; +} + + +NS_IMETHODIMP CSecureEnv::GetStaticFieldID(/*[in]*/ jclass clazz, + /*[in]*/ const char* name, + /*[in]*/ const char* sig, + /*[out]*/ jfieldID* result) +{ + if (result == NULL) + return NS_ERROR_NULL_POINTER; + + // run this on the *CURRENT* thread. + JNIEnv* env = mSession->getCurrentEnv(); + *result = env->GetStaticFieldID(clazz, name, sig); + + return NS_OK; +} + +/** + * To give proper "local" refs, need to run this in the true thread. + */ +NS_IMETHODIMP CSecureEnv::NewString(/*[in]*/ const jchar* unicode, + /*[in]*/ jsize len, + /*[out]*/ jstring* result) +{ + if (result == NULL) + return NS_ERROR_NULL_POINTER; + + // *result = mJavaEnv->NewString(unicode, len); + class NewStringMessage : public JavaMessage { + const jchar* unicode; + jsize len; + jstring* result; + public: + NewStringMessage(const jchar* unicode, jsize len, jstring* result) + { + this->unicode = unicode; + this->len = len; + this->result = result; + } + + virtual void execute(JNIEnv* env) + { + *result = env->NewString(unicode, len); + } + } msg(unicode, len, result); + sendMessageToJava(&msg); + + return NS_OK; +} + +NS_IMETHODIMP CSecureEnv::GetStringLength(/*[in]*/ jstring str, + /*[out]*/ jsize* result) +{ + if (mJavaEnv == NULL || result == NULL) + return NS_ERROR_NULL_POINTER; + + *result = mJavaEnv->GetStringLength(str); + + return NS_OK; +} + +NS_IMETHODIMP CSecureEnv::GetStringChars(/*[in]*/ jstring str, + /*[in]*/ jboolean *isCopy, + /*[out]*/ const jchar** result) +{ + if (mJavaEnv == NULL || result == NULL) + return NS_ERROR_NULL_POINTER; + + *result = mJavaEnv->GetStringChars(str, isCopy); + + return NS_OK; +} + + +NS_IMETHODIMP CSecureEnv::ReleaseStringChars(/*[in]*/ jstring str, + /*[in]*/ const jchar *chars) +{ + if (mJavaEnv == NULL) + return NS_ERROR_NULL_POINTER; + + mJavaEnv->ReleaseStringChars(str, chars); + + return NS_OK; +} + + +NS_IMETHODIMP CSecureEnv::NewStringUTF(/*[in]*/ const char *utf, + /*[out]*/ jstring* result) +{ + if (mJavaEnv == NULL || result == NULL) + return NS_ERROR_NULL_POINTER; + + // *result = mJavaEnv->NewStringUTF(utf); + class NewStringUTFMessage : public JavaMessage { + const char *utf; + jstring* result; + public: + NewStringUTFMessage(const char *utf, jstring* result) + { + this->utf = utf; + this->result = result; + } + + virtual void execute(JNIEnv* env) + { + *result = env->NewStringUTF(utf); + } + } msg(utf, result); + sendMessageToJava(&msg); + + return NS_OK; +} + + +NS_IMETHODIMP CSecureEnv::GetStringUTFLength(/*[in]*/ jstring str, + /*[out]*/ jsize* result) +{ + if (mJavaEnv == NULL || result == NULL) + return NS_ERROR_NULL_POINTER; + + *result = mJavaEnv->GetStringUTFLength(str); + + return NS_OK; +} + + +NS_IMETHODIMP CSecureEnv::GetStringUTFChars(/*[in]*/ jstring str, + /*[in]*/ jboolean *isCopy, + /*[out]*/ const char** result) +{ + if (mJavaEnv == NULL || result == NULL) + return NS_ERROR_NULL_POINTER; + + *result = mJavaEnv->GetStringUTFChars(str, isCopy); + + return NS_OK; +} + + +NS_IMETHODIMP CSecureEnv::ReleaseStringUTFChars(/*[in]*/ jstring str, + /*[in]*/ const char *chars) +{ + if (mJavaEnv == NULL) + return NS_ERROR_NULL_POINTER; + + mJavaEnv->ReleaseStringUTFChars(str, chars); + + return NS_OK; +} + + +NS_IMETHODIMP CSecureEnv::GetArrayLength(/*[in]*/ jarray array, + /*[out]*/ jsize* result) +{ + if (mJavaEnv == NULL || result == NULL) + return NS_ERROR_NULL_POINTER; + + *result = mJavaEnv->GetArrayLength(array); + + return NS_OK; +} + +NS_IMETHODIMP CSecureEnv::NewObjectArray(/*[in]*/ jsize len, + /*[in]*/ jclass clazz, + /*[in]*/ jobject init, + /*[out]*/ jobjectArray* result) +{ + if (mJavaEnv == NULL || result == NULL) + return NS_ERROR_NULL_POINTER; + + *result = mJavaEnv->NewObjectArray(len, clazz, init); + + return NS_OK; +} + +NS_IMETHODIMP CSecureEnv::GetObjectArrayElement(/*[in]*/ jobjectArray array, + /*[in]*/ jsize index, + /*[out]*/ jobject* result) +{ + if (mJavaEnv == NULL || result == NULL) + return NS_ERROR_NULL_POINTER; + + *result = mJavaEnv->GetObjectArrayElement(array, index); + + return NS_OK; +} + + +NS_IMETHODIMP CSecureEnv::SetObjectArrayElement(/*[in]*/ jobjectArray array, + /*[in]*/ jsize index, + /*[in]*/ jobject val) +{ + if (mJavaEnv == NULL) + return NS_ERROR_NULL_POINTER; + + mJavaEnv->SetObjectArrayElement(array, index, val); + + return NS_OK; +} + +NS_IMETHODIMP CSecureEnv::NewArray(/*[in]*/ jni_type element_type, + /*[in]*/ jsize len, + /*[out]*/ jarray* result) +{ + if (mJavaEnv == NULL || result == NULL) + return NS_ERROR_NULL_POINTER; + + switch (element_type) { + case jboolean_type: + result = (jarray*) mJavaEnv->NewBooleanArray(len); + break; + case jbyte_type: + result = (jarray*) mJavaEnv->NewByteArray(len); + break; + case jchar_type: + result = (jarray*) mJavaEnv->NewCharArray(len); + break; + case jshort_type: + result = (jarray*) mJavaEnv->NewShortArray(len); + break; + case jint_type: + result = (jarray*) mJavaEnv->NewIntArray(len); + break; + case jlong_type: + result = (jarray*) mJavaEnv->NewLongArray(len); + break; + case jfloat_type: + result = (jarray*) mJavaEnv->NewFloatArray(len); + break; + case jdouble_type: + result = (jarray*) mJavaEnv->NewDoubleArray(len); + break; + default: + return NS_ERROR_FAILURE; + } + + return NS_OK; +} + + +NS_IMETHODIMP CSecureEnv::GetArrayElements(/*[in]*/ jni_type type, + /*[in]*/ jarray array, + /*[in]*/ jboolean *isCopy, + /*[out]*/ void* result) +{ + if (mJavaEnv == NULL || result == NULL) + return NS_ERROR_NULL_POINTER; + + switch (type) { + case jboolean_type: + result = (void*) mJavaEnv->GetBooleanArrayElements((jbooleanArray)array, isCopy); + break; + case jbyte_type: + result = (void*) mJavaEnv->GetByteArrayElements((jbyteArray)array, isCopy); + break; + case jchar_type: + result = (void*) mJavaEnv->GetCharArrayElements((jcharArray)array, isCopy); + break; + case jshort_type: + result = (void*) mJavaEnv->GetShortArrayElements((jshortArray)array, isCopy); + break; + case jint_type: + result = (void*) mJavaEnv->GetIntArrayElements((jintArray)array, isCopy); + break; + case jlong_type: + result = (void*) mJavaEnv->GetLongArrayElements((jlongArray)array, isCopy); + break; + case jfloat_type: + result = (void*) mJavaEnv->GetFloatArrayElements((jfloatArray)array, isCopy); + break; + case jdouble_type: + result = (void*) mJavaEnv->GetDoubleArrayElements((jdoubleArray)array, isCopy); + break; + default: + return NS_ERROR_FAILURE; + } + + return NS_OK; +} + + +NS_IMETHODIMP CSecureEnv::ReleaseArrayElements(/*[in]*/ jni_type type, + /*[in]*/ jarray array, + /*[in]*/ void *elems, + /*[in]*/ jint mode) +{ + if (mJavaEnv == NULL) + return NS_ERROR_NULL_POINTER; + + switch (type) + { + case jboolean_type: + mJavaEnv->ReleaseBooleanArrayElements((jbooleanArray)array, (jboolean*)elems, mode); + break; + case jbyte_type: + mJavaEnv->ReleaseByteArrayElements((jbyteArray)array, (jbyte*)elems, mode); + break; + case jchar_type: + mJavaEnv->ReleaseCharArrayElements((jcharArray)array, (jchar*)elems, mode); + break; + case jshort_type: + mJavaEnv->ReleaseShortArrayElements((jshortArray)array, (jshort*)elems, mode); + break; + case jint_type: + mJavaEnv->ReleaseIntArrayElements((jintArray)array, (jint*)elems, mode); + break; + case jlong_type: + mJavaEnv->ReleaseLongArrayElements((jlongArray)array, (jlong*)elems, mode); + break; + case jfloat_type: + mJavaEnv->ReleaseFloatArrayElements((jfloatArray)array, (jfloat*)elems, mode); + break; + case jdouble_type: + mJavaEnv->ReleaseDoubleArrayElements((jdoubleArray)array, (jdouble*)elems, mode); + break; + default: + return NS_ERROR_FAILURE; + } + + return NS_OK; +} + +NS_IMETHODIMP CSecureEnv::GetArrayRegion(/*[in]*/ jni_type type, + /*[in]*/ jarray array, + /*[in]*/ jsize start, + /*[in]*/ jsize len, + /*[out]*/ void* buf) +{ + if (mJavaEnv == NULL || buf == NULL) + return NS_ERROR_NULL_POINTER; + + switch (type) { + case jboolean_type: + mJavaEnv->GetBooleanArrayRegion((jbooleanArray)array, start, len, (jboolean*)buf); + break; + case jbyte_type: + mJavaEnv->GetByteArrayRegion((jbyteArray)array, start, len, (jbyte*)buf); + break; + case jchar_type: + mJavaEnv->GetCharArrayRegion((jcharArray)array, start, len, (jchar*)buf); + break; + case jshort_type: + mJavaEnv->GetShortArrayRegion((jshortArray)array, start, len, (jshort*)buf); + break; + case jint_type: + mJavaEnv->GetIntArrayRegion((jintArray)array, start, len, (jint*)buf); + break; + case jlong_type: + mJavaEnv->GetLongArrayRegion((jlongArray)array, start, len, (jlong*)buf); + break; + case jfloat_type: + mJavaEnv->GetFloatArrayRegion((jfloatArray)array, start, len, (jfloat*)buf); + break; + case jdouble_type: + mJavaEnv->GetDoubleArrayRegion((jdoubleArray)array, start, len, (jdouble*)buf); + break; + default: + return NS_ERROR_FAILURE; + } + + return NS_OK; +} + + +NS_IMETHODIMP CSecureEnv::SetArrayRegion(/*[in]*/ jni_type type, + /*[in]*/ jarray array, + /*[in]*/ jsize start, + /*[in]*/ jsize len, + /*[in]*/ void* buf) +{ + if (mJavaEnv == NULL || buf == NULL) + return NS_ERROR_NULL_POINTER; + + switch (type) { + case jboolean_type: + mJavaEnv->SetBooleanArrayRegion((jbooleanArray)array, start, len, (jboolean*)buf); + break; + case jbyte_type: + mJavaEnv->SetByteArrayRegion((jbyteArray)array, start, len, (jbyte*)buf); + break; + case jchar_type: + mJavaEnv->SetCharArrayRegion((jcharArray)array, start, len, (jchar*)buf); + break; + case jshort_type: + mJavaEnv->SetShortArrayRegion((jshortArray)array, start, len, (jshort*)buf); + break; + case jint_type: + mJavaEnv->SetIntArrayRegion((jintArray)array, start, len, (jint*)buf); + break; + case jlong_type: + mJavaEnv->SetLongArrayRegion((jlongArray)array, start, len, (jlong*)buf); + break; + case jfloat_type: + mJavaEnv->SetFloatArrayRegion((jfloatArray)array, start, len, (jfloat*)buf); + break; + case jdouble_type: + mJavaEnv->SetDoubleArrayRegion((jdoubleArray)array, start, len, (jdouble*)buf); + break; + default: + return NS_ERROR_FAILURE; + } + + return NS_OK; +} + + +NS_IMETHODIMP CSecureEnv::RegisterNatives(/*[in]*/ jclass clazz, + /*[in]*/ const JNINativeMethod *methods, + /*[in]*/ jint nMethods, + /*[out]*/ jint* result) +{ + if (mJavaEnv == NULL || result == NULL) + return NS_ERROR_NULL_POINTER; + + *result = mJavaEnv->RegisterNatives(clazz, methods, nMethods); + + return NS_OK; +} + + +NS_IMETHODIMP CSecureEnv::UnregisterNatives(/*[in]*/ jclass clazz, + /*[out]*/ jint* result) +{ + if (mJavaEnv == NULL || result == NULL) + return NS_ERROR_NULL_POINTER; + + *result = mJavaEnv->UnregisterNatives(clazz); + + return NS_OK; +} + + +NS_IMETHODIMP CSecureEnv::MonitorEnter(/*[in]*/ jobject obj, + /*[out]*/ jint* result) +{ + if (mJavaEnv == NULL || result == NULL) + return NS_ERROR_NULL_POINTER; + + // *result = mJavaEnv->MonitorEnter(obj); + class MonitorEnterMessage : public JavaMessage { + jobject obj; + jint* result; + public: + MonitorEnterMessage(jobject obj, jint* result) + { + this->obj = obj; + this->result = result; + } + + virtual void execute(JNIEnv* env) + { + *result = env->MonitorEnter(obj); + } + } msg(obj, result); + sendMessageToJava(&msg); + + return NS_OK; +} + + +NS_IMETHODIMP CSecureEnv::MonitorExit(/*[in]*/ jobject obj, + /*[out]*/ jint* result) +{ + if (mJavaEnv == NULL || result == NULL) + return NS_ERROR_NULL_POINTER; + + // *result = mJavaEnv->MonitorExit(obj); + class MonitorExitMessage : public JavaMessage { + jobject obj; + jint* result; + public: + MonitorExitMessage(jobject obj, jint* result) + { + this->obj = obj; + this->result = result; + } + + virtual void execute(JNIEnv* env) + { + *result = env->MonitorExit(obj); + } + } msg(obj, result); + sendMessageToJava(&msg); + + return NS_OK; +} + +NS_IMETHODIMP CSecureEnv::GetJavaVM(/*[in]*/ JavaVM **vm, + /*[out]*/ jint* result) +{ + if (mJavaEnv == NULL || result == NULL) + return NS_ERROR_NULL_POINTER; + + *result = mJavaEnv->GetJavaVM(vm); + + return NS_OK; +} + +/** + * Runs a message loop. Puts the message in the sendQueue, then waits on the receiveQueue for the reply. + */ + +void CSecureEnv::messageLoop(JNIEnv* env, JavaMessage* msg, JavaMessageQueue* sendQueue, JavaMessageQueue* receiveQueue, Boolean busyWaiting) +{ + // put the message in the send queue, and wait for a reply. + sendQueue->putMessage(msg); + sendQueue->notify(); + JavaMessage* replyMsg = receiveQueue->getMessage(); + for (;;) { + // Fully synchronized approach. + if (replyMsg != NULL) { + if (replyMsg == msg) + break; + // must be a message that needs executing. + replyMsg->execute(env); + sendQueue->putMessage(replyMsg); + sendQueue->notify(); + // notify can cause a yield, so look again. + replyMsg = receiveQueue->getMessage(); + if (replyMsg != NULL) + continue; + } + // when busy waiting, must give time to browser between timed waits. + if (busyWaiting) { + receiveQueue->wait(kDefaultJMTime); + replyMsg = receiveQueue->getMessage(); + if (replyMsg != NULL) + continue; + // mSession->lock(); + mThreadManager->Sleep(); + // mSession->unlock(); + } else { + // wait for a message to arrive. + receiveQueue->wait(); + } + replyMsg = receiveQueue->getMessage(); + } +} + +CSecureEnv* GetSecureJNI(JNIEnv* env, jobject thread) +{ + CSecureEnv* secureJNI = NULL; + + jclass threadClass = env->GetObjectClass(thread); + if (threadClass != NULL) { + jfieldID fSecureEnvField = env->GetFieldID(threadClass, "fSecureEnv", "I"); + if (fSecureEnvField != NULL) { + secureJNI = (CSecureEnv*) env->GetIntField(thread, fSecureEnvField); + } else { + env->ExceptionClear(); + } + env->DeleteLocalRef(threadClass); + } + + return secureJNI; +} diff --git a/plugin/oji/MRJ/plugin/Source/CSecureEnv.h b/plugin/oji/MRJ/plugin/Source/CSecureEnv.h new file mode 100644 index 00000000000..9fde46bcad8 --- /dev/null +++ b/plugin/oji/MRJ/plugin/Source/CSecureEnv.h @@ -0,0 +1,405 @@ +/* + * The contents of this file are subject to the Netscape Public License + * Version 1.0 (the "NPL"); you may not use this file except in + * compliance with the NPL. You may obtain a copy of the NPL at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the NPL is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL + * for the specific language governing rights and limitations under the + * NPL. + * + * The Initial Developer of this code under the NPL is + * Sun Microsystems, Inc. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All Rights + * Reserved. + */ + +/* + CSecureEnv.h + + Rewritten for use with MRJ plugin by Patrick C. Beard. + */ + +#ifndef CSecureJNI2_h___ +#define CSecureJNI_h___ + +#include "nsISecureEnv.h" +#include "nsIThreadManager.h" +#include "SupportsMixin.h" +#include "nsAgg.h" + +class MRJPlugin; +class MRJSession; + +class Monitor; +class nsIThreadManager; +class nsIJVMManager; + +class JavaMessage; +class JavaMessageQueue; + +class CSecureEnv : public nsISecureEnv, public nsIRunnable, private SupportsMixin { +public: + + //////////////////////////////////////////////////////////////////////////// + // from nsISupports and AggregatedQueryInterface: + + // NS_DECL_AGGREGATED + DECL_SUPPORTS_MIXIN + + static NS_METHOD Create(MRJPlugin* plugin, JNIEnv* proxyEnv, const nsIID& aIID, void* *aInstancePtr); + + //////////////////////////////////////////////////////////////////////////// + // from nsISecureJNI2: + + + /** + * Create new Java object in LiveConnect. + * + * @param clazz -- Java Class object. + * @param methodID -- Method id + * @param args -- arguments for invoking the constructor. + * @param result -- return new Java object. + * @param ctx -- security context + */ + NS_IMETHOD NewObject(/*[in]*/ jclass clazz, + /*[in]*/ jmethodID methodID, + /*[in]*/ jvalue *args, + /*[out]*/ jobject* result, + /*[in]*/ nsISecurityContext* ctx = NULL); + + /** + * Invoke method on Java object in LiveConnect. + * + * @param type -- Return type + * @param obj -- Java object. + * @param methodID -- method id + * @param args -- arguments for invoking the constructor. + * @param result -- return result of invocation. + * @param ctx -- security context + */ + NS_IMETHOD CallMethod(/*[in]*/ jni_type type, + /*[in]*/ jobject obj, + /*[in]*/ jmethodID methodID, + /*[in]*/ jvalue *args, + /*[out]*/ jvalue* result, + /*[in]*/ nsISecurityContext* ctx = NULL); + + /** + * Invoke non-virtual method on Java object in LiveConnect. + * + * @param type -- Return type + * @param obj -- Java object. + * @param clazz -- Class object + * @param methodID -- method id + * @param args -- arguments for invoking the constructor. + * @param ctx -- security context + * @param result -- return result of invocation. + */ + NS_IMETHOD CallNonvirtualMethod(/*[in]*/ jni_type type, + /*[in]*/ jobject obj, + /*[in]*/ jclass clazz, + /*[in]*/ jmethodID methodID, + /*[in]*/ jvalue *args, + /*[out]*/ jvalue* result, + /*[in]*/ nsISecurityContext* ctx = NULL); + + /** + * Get a field on Java object in LiveConnect. + * + * @param type -- Return type + * @param obj -- Java object. + * @param fieldID -- field id + * @param result -- return field value + * @param ctx -- security context + */ + NS_IMETHOD GetField(/*[in]*/ jni_type type, + /*[in]*/ jobject obj, + /*[in]*/ jfieldID fieldID, + /*[out]*/ jvalue* result, + /*[in]*/ nsISecurityContext* ctx = NULL); + + /** + * Set a field on Java object in LiveConnect. + * + * @param type -- Return type + * @param obj -- Java object. + * @param fieldID -- field id + * @param val -- field value to set + * @param ctx -- security context + */ + NS_IMETHOD SetField(/*[in]*/ jni_type type, + /*[in]*/ jobject obj, + /*[in]*/ jfieldID fieldID, + /*[in]*/ jvalue val, + /*[in]*/ nsISecurityContext* ctx = NULL); + + /** + * Invoke static method on Java object in LiveConnect. + * + * @param type -- Return type + * @param clazz -- Class object. + * @param methodID -- method id + * @param args -- arguments for invoking the constructor. + * @param result -- return result of invocation. + * @param ctx -- security context + */ + NS_IMETHOD CallStaticMethod(/*[in]*/ jni_type type, + /*[in]*/ jclass clazz, + /*[in]*/ jmethodID methodID, + /*[in]*/ jvalue *args, + /*[out]*/ jvalue* result, + /*[in]*/ nsISecurityContext* ctx = NULL); + + /** + * Get a static field on Java object in LiveConnect. + * + * @param type -- Return type + * @param clazz -- Class object. + * @param fieldID -- field id + * @param result -- return field value + * @param ctx -- security context + */ + NS_IMETHOD GetStaticField(/*[in]*/ jni_type type, + /*[in]*/ jclass clazz, + /*[in]*/ jfieldID fieldID, + /*[out]*/ jvalue* result, + /*[in]*/ nsISecurityContext* ctx = NULL); + + + /** + * Set a static field on Java object in LiveConnect. + * + * @param type -- Return type + * @param clazz -- Class object. + * @param fieldID -- field id + * @param val -- field value to set + * @param ctx -- security context + */ + NS_IMETHOD SetStaticField(/*[in]*/ jni_type type, + /*[in]*/ jclass clazz, + /*[in]*/ jfieldID fieldID, + /*[in]*/ jvalue val, + /*[in]*/ nsISecurityContext* ctx = NULL); + + + NS_IMETHOD GetVersion(/*[out]*/ jint* version); + + NS_IMETHOD DefineClass(/*[in]*/ const char* name, + /*[in]*/ jobject loader, + /*[in]*/ const jbyte *buf, + /*[in]*/ jsize len, + /*[out]*/ jclass* clazz); + + NS_IMETHOD FindClass(/*[in]*/ const char* name, + /*[out]*/ jclass* clazz); + + NS_IMETHOD GetSuperclass(/*[in]*/ jclass sub, + /*[out]*/ jclass* super); + + NS_IMETHOD IsAssignableFrom(/*[in]*/ jclass sub, + /*[in]*/ jclass super, + /*[out]*/ jboolean* result); + + NS_IMETHOD Throw(/*[in]*/ jthrowable obj, + /*[out]*/ jint* result); + + NS_IMETHOD ThrowNew(/*[in]*/ jclass clazz, + /*[in]*/ const char *msg, + /*[out]*/ jint* result); + + NS_IMETHOD ExceptionOccurred(/*[out]*/ jthrowable* result); + + NS_IMETHOD ExceptionDescribe(void); + + NS_IMETHOD ExceptionClear(void); + + NS_IMETHOD FatalError(/*[in]*/ const char* msg); + + NS_IMETHOD NewGlobalRef(/*[in]*/ jobject lobj, + /*[out]*/ jobject* result); + + NS_IMETHOD DeleteGlobalRef(/*[in]*/ jobject gref); + + NS_IMETHOD DeleteLocalRef(/*[in]*/ jobject obj); + + NS_IMETHOD IsSameObject(/*[in]*/ jobject obj1, + /*[in]*/ jobject obj2, + /*[out]*/ jboolean* result); + + NS_IMETHOD AllocObject(/*[in]*/ jclass clazz, + /*[out]*/ jobject* result); + + NS_IMETHOD GetObjectClass(/*[in]*/ jobject obj, + /*[out]*/ jclass* result); + + NS_IMETHOD IsInstanceOf(/*[in]*/ jobject obj, + /*[in]*/ jclass clazz, + /*[out]*/ jboolean* result); + + NS_IMETHOD GetMethodID(/*[in]*/ jclass clazz, + /*[in]*/ const char* name, + /*[in]*/ const char* sig, + /*[out]*/ jmethodID* id); + + NS_IMETHOD GetFieldID(/*[in]*/ jclass clazz, + /*[in]*/ const char* name, + /*[in]*/ const char* sig, + /*[out]*/ jfieldID* id); + + NS_IMETHOD GetStaticMethodID(/*[in]*/ jclass clazz, + /*[in]*/ const char* name, + /*[in]*/ const char* sig, + /*[out]*/ jmethodID* id); + + NS_IMETHOD GetStaticFieldID(/*[in]*/ jclass clazz, + /*[in]*/ const char* name, + /*[in]*/ const char* sig, + /*[out]*/ jfieldID* id); + + NS_IMETHOD NewString(/*[in]*/ const jchar* unicode, + /*[in]*/ jsize len, + /*[out]*/ jstring* result); + + NS_IMETHOD GetStringLength(/*[in]*/ jstring str, + /*[out]*/ jsize* result); + + NS_IMETHOD GetStringChars(/*[in]*/ jstring str, + /*[in]*/ jboolean *isCopy, + /*[out]*/ const jchar** result); + + NS_IMETHOD ReleaseStringChars(/*[in]*/ jstring str, + /*[in]*/ const jchar *chars); + + NS_IMETHOD NewStringUTF(/*[in]*/ const char *utf, + /*[out]*/ jstring* result); + + NS_IMETHOD GetStringUTFLength(/*[in]*/ jstring str, + /*[out]*/ jsize* result); + + NS_IMETHOD GetStringUTFChars(/*[in]*/ jstring str, + /*[in]*/ jboolean *isCopy, + /*[out]*/ const char** result); + + NS_IMETHOD ReleaseStringUTFChars(/*[in]*/ jstring str, + /*[in]*/ const char *chars); + + NS_IMETHOD GetArrayLength(/*[in]*/ jarray array, + /*[out]*/ jsize* result); + + NS_IMETHOD NewObjectArray(/*[in]*/ jsize len, + /*[in]*/ jclass clazz, + /*[in]*/ jobject init, + /*[out]*/ jobjectArray* result); + + NS_IMETHOD GetObjectArrayElement(/*[in]*/ jobjectArray array, + /*[in]*/ jsize index, + /*[out]*/ jobject* result); + + NS_IMETHOD SetObjectArrayElement(/*[in]*/ jobjectArray array, + /*[in]*/ jsize index, + /*[in]*/ jobject val); + + NS_IMETHOD NewArray(/*[in]*/ jni_type element_type, + /*[in]*/ jsize len, + /*[out]*/ jarray* result); + + NS_IMETHOD GetArrayElements(/*[in]*/ jni_type type, + /*[in]*/ jarray array, + /*[in]*/ jboolean *isCopy, + /*[out]*/ void* result); + + NS_IMETHOD ReleaseArrayElements(/*[in]*/ jni_type type, + /*[in]*/ jarray array, + /*[in]*/ void *elems, + /*[in]*/ jint mode); + + NS_IMETHOD GetArrayRegion(/*[in]*/ jni_type type, + /*[in]*/ jarray array, + /*[in]*/ jsize start, + /*[in]*/ jsize len, + /*[out]*/ void* buf); + + NS_IMETHOD SetArrayRegion(/*[in]*/ jni_type type, + /*[in]*/ jarray array, + /*[in]*/ jsize start, + /*[in]*/ jsize len, + /*[in]*/ void* buf); + + NS_IMETHOD RegisterNatives(/*[in]*/ jclass clazz, + /*[in]*/ const JNINativeMethod *methods, + /*[in]*/ jint nMethods, + /*[out]*/ jint* result); + + NS_IMETHOD UnregisterNatives(/*[in]*/ jclass clazz, + /*[out]*/ jint* result); + + NS_IMETHOD MonitorEnter(/*[in]*/ jobject obj, + /*[out]*/ jint* result); + + NS_IMETHOD MonitorExit(/*[in]*/ jobject obj, + /*[out]*/ jint* result); + + NS_IMETHOD GetJavaVM(/*[in]*/ JavaVM **vm, + /*[out]*/ jint* result); + + //////////////////////////////////////////////////////////////////////////// + // from nsIRunnable: + + NS_IMETHOD Run(); + + CSecureEnv(MRJPlugin* plugin, JNIEnv* proxyEnv, JNIEnv* javaEnv = NULL); + virtual ~CSecureEnv(void); + + /** + * Called by the native run method, to connect the + * thread and the secure env. + */ + void initialize(JNIEnv* javaEnv, jboolean* isRunning, JavaMessageQueue* javaQueue, JavaMessageQueue* nativeQueue); + + jboolean isInitialized() { return mJavaQueue != NULL; } + + void setProxyEnv(JNIEnv* proxyEnv) { mProxyEnv = proxyEnv; } + JNIEnv* getProxyEnv() { return mProxyEnv; } + + void setJavaEnv(JNIEnv* javaEnv) { mJavaEnv = javaEnv; } + JNIEnv* getJavaEnv() { return mJavaEnv; } + + MRJSession* getSession() { return mSession; } + nsIThreadManager* getThreadManager() { return mThreadManager; } + + void getMessageQueues(JavaMessageQueue*& javaQueue, JavaMessageQueue*& nativeQueue) + { + javaQueue = mJavaQueue; + nativeQueue = mNativeQueue; + } + + void sendMessageToJava(JavaMessage* msg); + void sendMessageFromJava(JNIEnv* javaEnv, JavaMessage* msg, Boolean busyWaiting = false); + void messageLoop(JNIEnv* env, JavaMessage* msgToSend, JavaMessageQueue* sendQueue, JavaMessageQueue* receiveQueue, Boolean busyWaiting = false); + +protected: + + MRJPlugin* mPlugin; + JNIEnv* mProxyEnv; + MRJSession* mSession; + nsIThreadManager* mThreadManager; + + JNIEnv* mJavaEnv; + jboolean* mIsRunning; + JavaMessageQueue* mJavaQueue; + JavaMessageQueue* mNativeQueue; + +private: + // support for SupportsMixin. + static const InterfaceInfo sInterfaces[]; + static const UInt32 kInterfaceCount; +}; + +/** + * Returns the secure JNI associated with the current thread (if any). + */ +CSecureEnv* GetSecureJNI(JNIEnv* env, jobject thread); + +#endif // CSecureJNI2_h___ diff --git a/plugin/oji/MRJ/plugin/Source/MRJPlugin_config.h b/plugin/oji/MRJ/plugin/Source/MRJPlugin_config.h new file mode 100644 index 00000000000..7757503a345 --- /dev/null +++ b/plugin/oji/MRJ/plugin/Source/MRJPlugin_config.h @@ -0,0 +1,28 @@ +/* + * The contents of this file are subject to the Netscape Public License + * Version 1.0 (the "NPL"); you may not use this file except in + * compliance with the NPL. You may obtain a copy of the NPL at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the NPL is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL + * for the specific language governing rights and limitations under the + * NPL. + * + * The Initial Developer of this code under the NPL is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All Rights + * Reserved. + */ + +/* + MRJPlugin_config.h + + Global configuration defines used by the MRJ plugin. + + by Patrick C. Beard. + */ + +#include "MacHeaders.h" + +#define NEW_PLUGIN_STREAM_API