From b392af07771bf7077cb0dc8ac7aaeb1052ee88a5 Mon Sep 17 00:00:00 2001 From: "warren%netscape.com" Date: Wed, 30 Sep 1998 20:55:12 +0000 Subject: [PATCH] Broke out LiveConnect callbacks into separate file. git-svn-id: svn://10.0.0.236/trunk@11592 18797224-902f-48f8-a5cc-f745e15eee43 --- mozilla/modules/oji/src/lcglue.cpp | 468 +++++++++++++++++++++++++++++ 1 file changed, 468 insertions(+) create mode 100644 mozilla/modules/oji/src/lcglue.cpp diff --git a/mozilla/modules/oji/src/lcglue.cpp b/mozilla/modules/oji/src/lcglue.cpp new file mode 100644 index 00000000000..a395e4313e2 --- /dev/null +++ b/mozilla/modules/oji/src/lcglue.cpp @@ -0,0 +1,468 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * + * 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. + */ + +#include "prthread.h" +#include "pprthred.h" +#include "jsjava.h" +#ifdef MOCHA +#include "libmocha.h" +#include "libevent.h" +#endif +#include "jvmmgr.h" +#include "npglue.h" + +static NS_DEFINE_IID(kIJVMPluginInstanceIID, NS_IJVMPLUGININSTANCE_IID); +static NS_DEFINE_IID(kIJVMPluginTagInfoIID, NS_IJVMPLUGINTAGINFO_IID); + +static PRUintn tlsIndex_g = 0; + +//////////////////////////////////////////////////////////////////////////////// +// LiveConnect callbacks +//////////////////////////////////////////////////////////////////////////////// + +template +class ThreadLocalStorage { +public: + ThreadLocalStorage(PRThreadPrivateDTOR dtor) : mIndex(0), mValid(PR_FALSE) + { + mValid = (PR_NewThreadPrivateIndex(&mIndex, dtor) == PR_SUCCESS); + } + + void set(T value) + { + if (mValid) PR_SetThreadPrivate(mIndex, value); + } + + T get() + { + return (T) (mValid ? PR_GetThreadPrivate(mIndex) : 0); + } + +private: + PRUintn mIndex; + PRBool mValid; +}; + +PR_BEGIN_EXTERN_C + +#include "jscntxt.h" + +#ifdef MOCHA + +static JSContext* PR_CALLBACK +map_jsj_thread_to_js_context_impl(JSJavaThreadState *jsj_env, JNIEnv *env, char **errp) +{ + JSContext *cx = LM_GetCrippledContext(); + PRBool jvmMochaPrefsEnabled = PR_FALSE; + + *errp = NULL; +#if 0 + nsJVMMgr* pJVMMgr = JVM_GetJVMMgr(); + if (pJVMMgr != NULL) { + nsIJVMPlugin* pJVMPI = pJVMMgr->GetJVMPlugin(); + jvmMochaPrefsEnabled = LM_GetMochaEnabled(); + if (pJVMPI != NULL) { + nsIPluginInstance* pPIT; + nsresult err = pJVMPI->GetPluginInstance(env, &pPIT); + if ( (err == NS_OK) && (pPIT != NULL) ) { + nsIJVMPluginInstance* pJVMPIT; + if (pPIT->QueryInterface(kIJVMPluginInstanceIID, + (void**)&pJVMPIT) == NS_OK) { + nsPluginInstancePeer* pPITP; + err = pJVMPIT->GetPeer((nsIPluginInstancePeer**)&pPITP); + if ( (err == NS_OK) &&(pPITP != NULL) ) { + cx = pPITP->GetJSContext(); + pPITP->Release(); + } + pJVMPIT->Release(); + } + pPIT->Release(); + } + // pJVMPI->Release(); // GetJVMPlugin no longer calls AddRef + } + pJVMMgr->Release(); + } + if (jvmMochaPrefsEnabled == PR_FALSE) + { + *errp = strdup("Java preference is disabled"); + return NULL; + } + + if ( cx == NULL ) + { + *errp = strdup("Java thread could not be associated with a JSContext"); + return NULL; + } +#endif + return cx; +} + +static void PR_CALLBACK detach_jsjava_thread_state(void* env) +{ + JSJavaThreadState *jsj_env = (JSJavaThreadState*)env; + JSJ_DetachCurrentThreadFromJava(jsj_env); +} + +/* +** This callback is called to map a JSContext to a JSJavaThreadState which +** is a wrapper around JNIEnv. Hence this callback essentially maps a JSContext +** to a java thread. JSJ_AttachCurrentThreadToJava just calls AttachCurrentThread +** on the java vm. +*/ +static JSJavaThreadState* PR_CALLBACK +map_js_context_to_jsj_thread_impl(JSContext *cx, char **errp) +{ + *errp = NULL; + + static ThreadLocalStorage localThreadState(&detach_jsjava_thread_state); + JSJavaThreadState* jsj_env = localThreadState.get(); + if (jsj_env != NULL) + return jsj_env; + + if (ET_InitMoja(0) != LM_MOJA_OK) { + *errp = strdup("LiveConnect initialization failed."); + return NULL; + } + + JSJavaVM* js_jvm = NULL; + nsJVMMgr* pJVMMgr = JVM_GetJVMMgr(); + if (pJVMMgr != NULL) { + js_jvm = pJVMMgr->GetJSJavaVM(); + pJVMMgr->Release(); + if (js_jvm == NULL) { + *errp = strdup("Failed to attach to a Java VM."); + return NULL; + } + } + + jsj_env = JSJ_AttachCurrentThreadToJava(js_jvm, NULL, NULL); + localThreadState.set(jsj_env); + + return jsj_env; +} + +/* +** This callback is called to map a applet,bean to its corresponding JSObject +** created on javascript side and then map that to a java wrapper JSObject class. +** This callback is called in JSObject.getWindow implementation to get +** a java wrapper JSObject class for a applet only once. +** Note that once a mapping between applet -> javascript JSObject -> Java wrapper JSObject +** is made, all subsequent method calls via JSObject use the internal field +** to get to the javascript JSObject. +*/ +static JSObject* PR_CALLBACK +map_java_object_to_js_object_impl(JNIEnv *env, void *pNSIPluginInstanceIn, char **errp) +{ + MWContext *cx; + JSObject *window; + MochaDecoder *decoder; + PRBool mayscript = PR_FALSE; + PRBool jvmMochaPrefsEnabled = PR_FALSE; + nsresult err = NS_OK; + + *errp = NULL; + /* XXX assert JS is locked */ + + if (!pNSIPluginInstanceIn) { + env->ThrowNew(env->FindClass("java/lang/NullPointerException"),0); + return 0; + } + + nsJVMMgr* pJVMMgr = JVM_GetJVMMgr(); + if (pJVMMgr != NULL) { + nsIJVMPlugin* pJVMPI = pJVMMgr->GetJVMPlugin(); + jvmMochaPrefsEnabled = LM_GetMochaEnabled(); + if (pJVMPI != NULL) { + //jobject javaObject = applet; + nsIPluginInstance* pPIT; + //nsresult err = pJVMPI->GetPluginInstance(javaObject, &pPIT); + pPIT = (nsIPluginInstance*)pNSIPluginInstanceIn; + if ( (err == NS_OK) && (pPIT != NULL) ) { + nsIJVMPluginInstance* pJVMPIT; + if (pPIT->QueryInterface(kIJVMPluginInstanceIID, + (void**)&pJVMPIT) == NS_OK) { + nsPluginInstancePeer* pPITP; + err = pJVMPIT->GetPeer((nsIPluginInstancePeer**)&pPITP); + if ( (err == NS_OK) &&(pPITP != NULL) ) { + nsIJVMPluginTagInfo* pJVMTagInfo; + if (pPITP->QueryInterface(kIJVMPluginTagInfoIID, + (void**)&pJVMTagInfo) == NS_OK) { + err = pJVMTagInfo->GetMayScript(&mayscript); + PR_ASSERT(err != NS_OK ? mayscript == PR_FALSE : PR_TRUE); + pJVMTagInfo->Release(); + } + cx = pPITP->GetMWContext(); + pPITP->Release(); + } + pJVMPIT->Release(); + } + pPIT->Release(); + } + // pJVMPI->Release(); // GetJVMPlugin no longer calls AddRef + } + pJVMMgr->Release(); + } + + if ( (mayscript == PR_FALSE) + ||(jvmMochaPrefsEnabled == PR_FALSE) + ) + { + *errp = strdup("JSObject.getWindow() requires mayscript attribute on this Applet or java preference is disabled"); + goto except; + } + + + if (!cx || (cx->type != MWContextBrowser && cx->type != MWContextPane)) + { + *errp = strdup("JSObject.getWindow() can only be called in MWContextBrowser or MWContextPane"); + return 0; + } + + decoder = LM_GetMochaDecoder(cx); + + /* if there is a decoder now, reflect the window */ + if (decoder && (jvmMochaPrefsEnabled == PR_TRUE)) { + window = decoder->window_object; + } + + LM_PutMochaDecoder(decoder); + + return window; + except: + return 0; +} + +#if 0 +static JavaVM* PR_CALLBACK +get_java_vm_impl(char **errp) +{ + *errp = NULL; + JavaVM *pJavaVM = NULL; + + nsJVMMgr* pJVMMgr = JVM_GetJVMMgr(); + if (pJVMMgr != NULL) { + nsIJVMPlugin* pJVMPI = pJVMMgr->GetJVMPlugin(); + if (pJVMPI != NULL) { + nsresult err = pJVMPI->GetJavaVM(&pJavaVM); + PR_ASSERT(err != NS_OK ? pJavaVM == NULL : PR_TRUE); + // pJVMPI->Release(); // GetJVMPlugin no longer calls AddRef + } + pJVMMgr->Release(); + } + if ( pJavaVM == NULL ) + { + *errp = strdup("Could not find a JavaVM to attach to."); + } + return pJavaVM; +} +#endif + +static JSPrincipals* PR_CALLBACK +get_JSPrincipals_from_java_caller_impl(JNIEnv *pJNIEnv, JSContext *pJSContext) +{ + nsIPrincipal **ppNSIPrincipalArray = NULL; + PRInt32 length = 0; + nsresult err = NS_OK; + void *pNSPrincipalArray = NULL; +#if 0 // TODO: =-= sudu: fix it. + nsJVMMgr* pJVMMgr = JVM_GetJVMMgr(); + if (pJVMMgr != NULL) { + nsIJVMPlugin* pJVMPI = pJVMMgr->GetJVMPlugin(); + if (pJVMPI != NULL) { + err = pJVMPI->GetPrincipalArray(pJNIEnv, 0, &ppNSIPrincipalArray, &length); + if ((err == NS_OK) && (ppNSIPrincipalArray != NULL)) { + nsIPluginManager *pNSIPluginManager = NULL; + NS_DEFINE_IID(kIPluginManagerIID, NS_IPLUGINMANAGER_IID); + err = pJVMMgr->QueryInterface(kIPluginManagerIID, + (void**)&pNSIPluginManager); + + if( (err == NS_OK) + && (pNSIPluginManager != NULL ) + ) + { + nsCCapsManager *pNSCCapsManager = NULL; + NS_DEFINE_IID(kICapsManagerIID, NS_ICAPSMANAGER_IID); + err = pNSIPluginManager->QueryInterface(kICapsManagerIID, (void**)&pNSCCapsManager); + if( (err == NS_OK) + && (pNSCCapsManager != NULL) + ) + { + PRInt32 i=0; + nsPrincipal *pNSPrincipal = NULL; + pNSPrincipalArray = nsCapsNewPrincipalArray(length); + if (pNSPrincipalArray != NULL) + { + while( iGetNSPrincipal(ppNSIPrincipalArray[i], &pNSPrincipal); + nsCapsSetPrincipalArrayElement(pNSPrincipalArray, i, pNSPrincipal); + i++; + } + } + pNSCCapsManager->Release(); + } + pNSIPluginManager->Release(); + } + } + //pJVMPI->Release(); + } + pJVMMgr->Release(); + } +#endif + if ( (pNSPrincipalArray != NULL) + &&(length != 0) + ) + { + return LM_GetJSPrincipalsFromJavaCaller(pJSContext, pNSPrincipalArray); + } + + return NULL; +} + +static jobject PR_CALLBACK +get_java_wrapper_impl(JNIEnv *pJNIEnv, jint jsobject) +{ + nsresult err = NS_OK; + jobject pJSObjectWrapper = NULL; + nsJVMMgr* pJVMMgr = JVM_GetJVMMgr(); + if (pJVMMgr != NULL) { + nsIJVMPlugin* pJVMPI = pJVMMgr->GetJVMPlugin(); + if (pJVMPI != NULL) { + err = pJVMPI->GetJavaWrapper(pJNIEnv, jsobject, &pJSObjectWrapper); + //pJVMPI->Release(); + } + pJVMMgr->Release(); + } + if ( err != NS_OK ) + { + return NULL; + } + return pJSObjectWrapper; +} + +static JSBool PR_CALLBACK +enter_js_from_java_impl(JNIEnv *jEnv, char **errp) +{ +#ifdef OJI + ThreadLocalStorageAtIndex0 *priv = NULL; + if ( PR_GetCurrentThread() == NULL ) + { + PR_AttachThread(PR_USER_THREAD, PR_PRIORITY_NORMAL, NULL); + priv = (ThreadLocalStorageAtIndex0 *)malloc(sizeof(ThreadLocalStorageAtIndex0)); + priv->refcount=1; + PR_SetThreadPrivate(tlsIndex_g, (void *)priv); + } + else + { + priv = (ThreadLocalStorageAtIndex0 *)PR_GetThreadPrivate(tlsIndex_g); + if(priv != NULL) + { + priv->refcount++; + } + } + + return LM_LockJS(errp); +#else + return JS_TRUE; +#endif +} + +static void PR_CALLBACK +exit_js_impl(JNIEnv *jEnv) +{ + ThreadLocalStorageAtIndex0 *priv = NULL; + + LM_UnlockJS(); + + if ( (PR_GetCurrentThread() != NULL ) + && ((priv = (ThreadLocalStorageAtIndex0 *)PR_GetThreadPrivate(tlsIndex_g)) != NULL) + ) + { + priv->refcount--; + if(priv->refcount == 0) + { + PR_SetThreadPrivate(tlsIndex_g, NULL); + PR_DetachThread(); + free(priv); + } + } + return; +} + +static PRBool PR_CALLBACK +create_java_vm_impl(SystemJavaVM* *jvm, JNIEnv* *initialEnv, void* initargs) +{ + const char* classpath = (const char*)initargs; // unused (should it be?) + *jvm = (SystemJavaVM*)JVM_GetJVMMgr(); // unused in the browser + *initialEnv = JVM_GetJNIEnv(); + return (*jvm != NULL && *initialEnv != NULL); +} + +static PRBool PR_CALLBACK +destroy_java_vm_impl(SystemJavaVM* jvm, JNIEnv* initialEnv) +{ + JVM_ReleaseJNIEnv(initialEnv); + // need to release jvm + return PR_TRUE; +} + +static JNIEnv* PR_CALLBACK +attach_current_thread_impl(SystemJavaVM* jvm) +{ + return JVM_GetJNIEnv(); +} + +static PRBool PR_CALLBACK +detach_current_thread_impl(SystemJavaVM* jvm, JNIEnv* env) +{ + JVM_ReleaseJNIEnv(env); + return PR_TRUE; +} + +static SystemJavaVM* PR_CALLBACK +get_java_vm_impl(JNIEnv* env) +{ + // only one SystemJavaVM for the whole browser, so it doesn't depend on env + return (SystemJavaVM*)JVM_GetJVMMgr(); +} + +#endif /* MOCHA */ + +PR_END_EXTERN_C + + +/* + * Callbacks for client-specific jsjava glue + */ +JSJCallbacks jsj_callbacks = { + map_jsj_thread_to_js_context_impl, + map_js_context_to_jsj_thread_impl, + map_java_object_to_js_object_impl, + get_JSPrincipals_from_java_caller_impl, + enter_js_from_java_impl, + exit_js_impl, + NULL, // error_print + get_java_wrapper_impl, + create_java_vm_impl, + destroy_java_vm_impl, + attach_current_thread_impl, + detach_current_thread_impl, + get_java_vm_impl +}; + +////////////////////////////////////////////////////////////////////////////////