New xpcom liveconnect apis

This commit is contained in:
sudu%netscape.com 1998-09-17 18:13:55 +00:00
parent 81e368f2cc
commit ace5839c75
16 changed files with 337 additions and 28 deletions

View File

@ -16,7 +16,9 @@
DEPTH = ../..
ifdef MOZ_OJI
DIRS = liveconnect
endif
LIBRARY_NAME = js

View File

@ -21,7 +21,9 @@ srcdir = @srcdir@
include $(DEPTH)/config/autoconf.mk
ifdef MOZ_OJI
DIRS = liveconnect
endif
LIBRARY_NAME = js

View File

@ -21,7 +21,9 @@
#//------------------------------------------------------------------------
DEPTH=..\..
!ifdef MOZ_OJI
DIRS = liveconnect
!endif
#//------------------------------------------------------------------------
#//

View File

@ -30,6 +30,7 @@
#define nsIJVMPlugin_h___
#include "nsIPlugin.h"
#include "nsIPrincipal.h"
#include "jni.h"
////////////////////////////////////////////////////////////////////////////////
@ -50,6 +51,7 @@ struct nsJVMInitArgs {
*/
#define nsJVMInitArgs_Version 0x00010000L
class nsIJVMPlugin : public nsIPlugin {
public:
@ -81,12 +83,22 @@ public:
// Returns the current classpath in use by the JVM.
NS_IMETHOD
GetClassPath(const char* *result) = 0;
#if 0
NS_IMETHOD
GetPluginInstance(jobject javaObject, nsIPluginInstance* *result) = 0;
NS_IMETHOD
GetPluginInstance(JNIEnv* jenv, nsIPluginInstance* *result) = 0;
#endif
NS_IMETHOD
GetJavaWrapper(JNIEnv* jenv, jint obj, jobject *jobj) = 0;
// nsIPrincipals is a array of pointers to principals associated with this
// java object trying to run a JS script.
#if 0
NS_IMETHOD
GetPrincipalArray(JNIEnv *pJNIEnv, PRInt32 frameIndex, nsIPrincipal ***principalArray, PRInt32 *length) = 0;
#endif
NS_IMETHOD
GetJavaVM(JavaVM* *result) = 0;

View File

@ -38,6 +38,8 @@
#include "nsIJVMPluginTagInfo.h"
#include "nsISymantecDebugManager.h"
#include "nsISymantecDebugger.h"
#include "nsICapsManager.h"
#include "nsILiveconnect.h"
////////////////////////////////////////////////////////////////////////////////

View File

@ -16,7 +16,10 @@ LIBRARY_NAME = oji
CPPSRCS = jvmmgr.cpp \
scd.cpp
REQUIRES = img java js lay layer plugin plugimpl pref style util xpcom raptor oji
REQUIRES = img java js lay layer plugin plugimpl pref style util xpcom raptor oji caps
LCFLAGS += -DJSJDLL=\"$(JSJDLL)\"
INCLUDES += -I$(DIST)/include/private
endif # MOZ_OJI
EXPORTS = jvmmgr.h

View File

@ -21,7 +21,9 @@ LIBRARY_NAME = oji
CPPSRCS = jvmmgr.cpp \
scd.cpp
REQUIRES = img java js lay layer plugin plugimpl pref style util xpcom raptor oji
REQUIRES = img java js lay layer plugin plugimpl pref style util xpcom raptor oji caps
LCFLAGS += -DJSJDLL=\"$(JSJDLL)\"
INCLUDES += -I$(DIST)/include/private
endif # MOZ_OJI
EXPORTS = jvmmgr.h

View File

@ -28,6 +28,8 @@
#include "np.h"
#include "prio.h"
#include "prmem.h"
#include "prthread.h"
#include "pprthred.h"
#include "plstr.h"
#include "jni.h"
#include "jsjava.h"
@ -35,6 +37,9 @@
#include "libmocha.h"
#include "libevent.h"
#endif
#include "nsICapsManager.h"
#include "nsCCapsManager.h"
#include "nsILiveconnect.h"
#include "xpgetstr.h"
extern "C" int XP_PROGRESS_STARTING_JAVA;
@ -53,6 +58,8 @@ void stopAsyncCursors(void);
}
#endif // XP_MAC
static PRUintn tlsIndex_g = 0;
static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
static NS_DEFINE_IID(kIJVMManagerIID, NS_IJVMMANAGER_IID);
static NS_DEFINE_IID(kIJVMPluginIID, NS_IJVMPLUGIN_IID);
@ -87,6 +94,7 @@ nsJVMMgr::nsJVMMgr(nsISupports* outer)
fClassPathAdditions(new nsVector())
{
NS_INIT_AGGREGATED(outer);
PR_NewThreadPrivateIndex(&tlsIndex_g, NULL);
}
nsJVMMgr::~nsJVMMgr()
@ -164,7 +172,7 @@ map_jsj_thread_to_js_context_impl(JSJavaThreadState *jsj_env, JNIEnv *env, char
PRBool jvmMochaPrefsEnabled = PR_FALSE;
*errp = NULL;
#if 0
nsJVMMgr* pJVMMgr = JVM_GetJVMMgr();
if (pJVMMgr != NULL) {
nsIJVMPlugin* pJVMPI = pJVMMgr->GetJVMPlugin();
@ -201,7 +209,7 @@ map_jsj_thread_to_js_context_impl(JSJavaThreadState *jsj_env, JNIEnv *env, char
*errp = strdup("Java thread could not be associated with a JSContext");
return NULL;
}
#endif
return cx;
}
@ -259,36 +267,32 @@ map_js_context_to_jsj_thread_impl(JSContext *cx, char **errp)
** to get to the javascript JSObject.
*/
static JSObject* PR_CALLBACK
map_java_object_to_js_object_impl(JNIEnv *env, jobject applet, char **errp)
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 (!applet) {
if (!pNSIPluginInstanceIn) {
env->ThrowNew(env->FindClass("java/lang/NullPointerException"),0);
return 0;
}
if (!env->IsInstanceOf(applet,
env->FindClass("java/applet/Applet"))) {
env->ThrowNew(env->FindClass("java/lang/IllegalArgumentException"),
"JSObject.getWindow() requires a java.applet.Applet argument");
return 0;
}
nsJVMMgr* pJVMMgr = JVM_GetJVMMgr();
if (pJVMMgr != NULL) {
nsIJVMPlugin* pJVMPI = pJVMMgr->GetJVMPlugin();
jvmMochaPrefsEnabled = LM_GetMochaEnabled();
if (pJVMPI != NULL) {
jobject javaObject = applet;
//jobject javaObject = applet;
nsIPluginInstance* pPIT;
nsresult err = pJVMPI->GetPluginInstance(javaObject, &pPIT);
//nsresult err = pJVMPI->GetPluginInstance(javaObject, &pPIT);
pPIT = (nsIPluginInstance*)pNSIPluginInstanceIn;
if ( (err == NS_OK) && (pPIT != NULL) ) {
nsIJVMPluginInstance* pJVMPIT;
if (pPIT->QueryInterface(kIJVMPluginInstanceIID,
@ -367,19 +371,137 @@ get_java_vm_impl(char **errp)
return pJavaVM;
}
#ifdef OJI
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( i<length )
{
err = pNSCCapsManager->GetNSPrincipal(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;
}
PR_IMPLEMENT(jobject)
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)
{
LM_UnlockJS();
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;
}
#endif /* OJI */
#endif /* MOCHA */
@ -393,16 +515,17 @@ static JSJCallbacks jsj_callbacks = {
map_jsj_thread_to_js_context_impl,
map_js_context_to_jsj_thread_impl,
map_java_object_to_js_object_impl,
NULL,
get_JSPrincipals_from_java_caller_impl,
#ifdef OJI
enter_js_from_java_impl,
exit_js_impl,
#else
NULL,
NULL,
NULL,
#endif
NULL,
get_java_vm_impl
get_java_vm_impl,
get_java_wrapper_impl
};
////////////////////////////////////////////////////////////////////////////////
@ -731,6 +854,9 @@ nsJVMMgr::MaybeStartupLiveConnect()
do {
if (IsLiveConnectEnabled() && StartupJVM() == nsJVMStatus_Running) {
NS_DEFINE_CID(kCLiveconnectCID, NS_CLIVECONNECT_CID);
nsRepository::RegisterFactory(kCLiveconnectCID, (const char *)JSJDLL,
PR_FALSE, PR_FALSE);
JSJ_Init(&jsj_callbacks);
nsIJVMPlugin* plugin = GetJVMPlugin();
if (plugin) {
@ -1190,22 +1316,26 @@ static void PR_CALLBACK detach_JNIEnv(void* env)
PR_IMPLEMENT(JNIEnv*)
JVM_GetJNIEnv(void)
{
JNIEnv* env = NULL;
/* Use NSPR thread private data to manage the per-thread JNIEnv* association. */
#ifdef NOT_YET /* Talked to patrick about it and he said it was ok to remove it
for now. This code should be in the jvm plugin code which should also*/
static ThreadLocalStorage<JNIEnv*> localEnv(&detach_JNIEnv);
JNIEnv* env = localEnv.get();
env = localEnv.get();
if (env != NULL)
return env;
#endif
nsIJVMPlugin* jvm = GetRunningJVM();
if (jvm) {
(void)jvm->GetJNIEnv(&env);
// jvm->Release(); // GetRunningJVM no longer calls AddRef
}
#ifdef NOT_YET
/* Associate the JNIEnv with the current thread. */
localEnv.set(env);
#endif
return env;
}
@ -1221,6 +1351,7 @@ JVM_MaybeStartupLiveConnect()
return result;
}
PR_IMPLEMENT(PRBool)
JVM_MaybeShutdownLiveConnect(void)
{
@ -1257,6 +1388,22 @@ JVM_ShutdownJVM(void)
return status;
}
PR_IMPLEMENT(void)
JVM_ReleaseJNIEnv(JNIEnv *pJNIEnv)
{
nsJVMMgr *pNSJVMMgr = JVM_GetJVMMgr();
if (pNSJVMMgr != NULL)
{
nsIJVMPlugin *pNSIJVMPlugin = pNSJVMMgr->GetJVMPlugin();
if (pNSIJVMPlugin != NULL)
{
pNSIJVMPlugin->ReleaseJNIEnv(pJNIEnv);
}
}
return;
}
PR_END_EXTERN_C
////////////////////////////////////////////////////////////////////////////////

View File

@ -43,6 +43,11 @@ typedef enum nsJVMStatus {
class nsIPluginTagInfo2;
class nsSymantecDebugManager;
struct ThreadLocalStorageAtIndex0 {
PRUint32 refcount;
};
typedef struct ThreadLocalStorageAtIndex0 ThreadLocalStorageAtIndex0;
/*******************************************************************************
* JVMMgr is the interface to the JVM manager that the browser sees. All
* files that want to include java services should include this header file.
@ -212,6 +217,9 @@ JVM_GetJavaVM(void);
PR_EXTERN(JNIEnv*)
JVM_GetJNIEnv(void);
PR_IMPLEMENT(void)
JVM_ReleaseJNIEnv(JNIEnv *pJNIEnv);
PR_EXTERN(PRBool)
JVM_MaybeStartupLiveConnect(void);

View File

@ -61,6 +61,7 @@ LINCS= $(LINCS) -I_jri \
# ns/dist/public/win16
#
!if "$(MOZ_BITS)" == "32"
-I$(PUBLIC)/caps \
-I$(PUBLIC)/js \
-I$(PUBLIC)/java \
-I$(PUBLIC)/libimg \
@ -74,6 +75,7 @@ LINCS= $(LINCS) -I_jri \
-I$(PUBLIC)/oji \
-I$(PUBLIC)/plugimpl \
!endif
-I$(DIST)/include/private \
-I$(DEPTH)/lib/layout \
-I$(DEPTH)/lib/libstyle \
-I$(DEPTH)/lib/libjar \

View File

@ -26,7 +26,7 @@ CPPSRCS = nsplugin.cpp npglue.cpp
EXPORTS = nppg.h npglue.h nppriv.h
REQUIRES = lay layer js style applet nspr dbm img util java pref xpcom raptor netcnvts plugin plugimpl oji ojiimpl
REQUIRES = lay layer js style applet nspr dbm img util java pref xpcom raptor netcnvts plugin plugimpl oji ojiimpl caps
ifeq ($(subst /,_,$(shell uname -s)),OS2)
CPPSRCS = npwplat.cpp
@ -39,6 +39,7 @@ ifeq ($(subst /,_,$(shell uname -s)),OS2)
INCLUDES += -I$(DEPTH)/cmd/os2fe/nfc/include -I$(DEPTH)/cmd/os2fe -I$(DEPTH)/cmd/winfe
endif
INCLUDES += -I.
INCLUDES += -I. -I$(DIST)/include/private
$(LIBRARY): $(OBJS)

View File

@ -47,5 +47,8 @@ INCLUDES += -I$(DEPTH)/cmd/os2fe/nfc/include -I$(DEPTH)/cmd/os2fe -I$(DEPTH)/cmd
endif
INCLUDES += -I$(srcdir)/.
# XXX Add -I$(DIST)/include/private to the above line. Replace DIST to something else in
# autoconf world.
# cyeh asked me to put in this note as we could not figure out a equivalent right now.
$(LIBRARY): $(OBJS)

View File

@ -29,6 +29,7 @@ EXPORTS = \
LIBRARY_NAME = plug
LINCS = -I$(DIST)\include \
-I$(DIST)\include\private \
-I$(PUBLIC)\plugin \
-I$(PUBLIC)\java \
-I$(PUBLIC)\pref \
@ -38,7 +39,8 @@ LINCS = -I$(DIST)\include \
-I$(PUBLIC)\xpcom \
-I$(PUBLIC)\raptor \
-I$(PUBLIC)\oji \
-I$(PUBLIC)\ojiimpl
-I$(PUBLIC)\ojiimpl \
-I$(PUBLIC)\caps
OBJS = .\$(OBJDIR)\npassoc.obj \
.\$(OBJDIR)\nsplugin.obj \

View File

@ -32,6 +32,7 @@
#ifdef OJI
#include "jni.h"
#include "jvmmgr.h"
#include "nsCaps.h"
#endif
#ifdef ANTHRAX
@ -3996,6 +3997,12 @@ NPL_Init()
* available.
*/
NPL_RegisterDefaultConverters();
/*
** Initialize caps manager so that factory for nsCCapsManager gets registered.
** Since nsICapsManager is aggregated with nsIPluginManager, we need to initialize
** caps well upfront. =-= sudu.
*/
nsCapsInitialize();
/* call the platform specific FE code to enumerate and register plugins */
FE_RegisterPlugins();

View File

@ -381,6 +381,10 @@ protected:
virtual ~nsPluginManager(void);
// aggregated interfaces:
nsIJVMManager* GetJVMMgr(const nsIID& aIID);
nsICapsManager* GetCapsManager(const nsIID& aIID);
nsILiveconnect* GetLiveconnect(const nsIID& aIID);
nsISupports* fJVMMgr;
nsISupports* fMalloc;
nsISupports* fFileUtils;
@ -389,6 +393,8 @@ protected:
void* fOldCursor;
nsHashtable* fAllocatedMenuIDs;
nsISupports* fCapsManager;
nsISupports* fLiveconnect;
};
extern nsPluginManager* thePluginManager;

View File

@ -43,8 +43,14 @@
#include <TArray.h>
#endif
#include "prthread.h"
#include "pprthred.h"
#include "prtypes.h"
#include "nsHashtable.h"
#include "nsMalloc.h"
#include "nsICapsManager.h"
#include "nsCCapsManager.h"
#include "nsILiveconnect.h"
#include "intl_csi.h"
@ -100,7 +106,7 @@ nsresult fromNPError[] = {
nsPluginManager* thePluginManager = NULL;
nsPluginManager::nsPluginManager(nsISupports* outer)
: fJVMMgr(NULL), fMalloc(NULL), fFileUtils(NULL), fAllocatedMenuIDs(NULL)
: fJVMMgr(NULL), fMalloc(NULL), fAllocatedMenuIDs(NULL), fCapsManager(NULL), fLiveconnect(NULL)
{
NS_INIT_AGGREGATED(outer);
}
@ -120,6 +126,16 @@ nsPluginManager::~nsPluginManager(void)
fFileUtils = NULL;
}
if (fCapsManager) {
fCapsManager->Release();
fCapsManager = NULL;
}
if (fLiveconnect) {
fCapsManager->Release();
fCapsManager = NULL;
}
#ifdef XP_MAC
if (fAllocatedMenuIDs != NULL) {
// Fix me, delete all the elements before deleting the table.
@ -140,6 +156,7 @@ nsPluginManager::Create(nsISupports* outer, const nsIID& aIID, void* *aInstanceP
return NS_ERROR_OUT_OF_MEMORY;
mgr->AddRef();
*aInstancePtr = mgr->GetInner();
*aInstancePtr = (outer != NULL)? (void *)mgr->GetInner(): (void *)mgr;
return NS_OK;
}
@ -216,6 +233,17 @@ nsPluginManager::AggregatedQueryInterface(const nsIID& aIID, void** aInstancePtr
(void**)&fJVMMgr);
if (fJVMMgr && fJVMMgr->QueryInterface(aIID, aInstancePtr) == NS_OK)
return NS_OK;
nsICapsManager* pNSICapsManager = GetCapsManager(aIID);
if (pNSICapsManager) {
*aInstancePtr = (void*) ((nsISupports*)pNSICapsManager);
return NS_OK;
}
nsILiveconnect* pNSILiveconnect = GetLiveconnect(aIID);
if (pNSILiveconnect) {
*aInstancePtr = (void*) ((nsISupports*)pNSILiveconnect);
return NS_OK;
}
#endif
if (fMalloc == NULL)
nsMalloc::Create((nsIPluginManager*)this, kISupportsIID,
@ -232,6 +260,86 @@ nsPluginManager::AggregatedQueryInterface(const nsIID& aIID, void** aInstancePtr
return NS_NOINTERFACE;
}
nsICapsManager*
nsPluginManager::GetCapsManager(const nsIID& aIID)
{
nsICapsManager* result = NULL;
nsresult err = NS_OK;
PRThread *threadAttached = NULL;
#ifdef OJI
if (fCapsManager == NULL) {
if ( PR_GetCurrentThread() == NULL )
{
threadAttached = PR_AttachThread(PR_USER_THREAD, PR_PRIORITY_NORMAL, NULL);
}
NS_DEFINE_CID(kCCapsManagerCID, NS_CCAPSMANAGER_CID);
nsresult err = NS_OK;
err = nsRepository::CreateInstance(kCCapsManagerCID,
(nsIPluginManager*)this, /* outer */
kISupportsIID,
(void **)&fCapsManager);
NS_DEFINE_IID(kICapsManagerIID, NS_ICAPSMANAGER_IID);
if ( (err == NS_OK)
&& (fCapsManager != NULL)
&& (err = (fCapsManager->QueryInterface(kICapsManagerIID, (void**)&result)) == NS_OK)
)
{
((nsCCapsManager*)result)->SetSystemPrivilegeManager();
result->Release();
}
}
if ( (err == NS_OK)
&&(fCapsManager->QueryInterface(aIID, (void**)&result) != NS_OK)
)
{
result = NULL;
}
if (threadAttached != NULL )
{
PR_DetachThread();
}
#endif
return result;
}
nsILiveconnect*
nsPluginManager::GetLiveconnect(const nsIID& aIID)
{
nsILiveconnect* result = NULL;
PRThread *threadAttached = NULL;
#ifdef OJI
nsresult err = NS_OK;
if (fLiveconnect == NULL) {
if ( PR_GetCurrentThread() == NULL )
{
threadAttached = PR_AttachThread(PR_USER_THREAD, PR_PRIORITY_NORMAL, NULL);
}
NS_DEFINE_CID(kCLiveconnectCID, NS_CLIVECONNECT_CID);
nsresult err = NS_OK;
err = nsRepository::CreateInstance(kCLiveconnectCID,
(nsIPluginManager*)this, /* outer */
kISupportsIID,
(void **)&fLiveconnect);
}
if ( (err == NS_OK)
&&(fLiveconnect->QueryInterface(aIID, (void**)&result) != NS_OK)
)
{
result = NULL;
}
if (threadAttached != NULL )
{
PR_DetachThread();
}
#endif
return result;
}
NS_METHOD
nsPluginManager::BeginWaitCursor(void)
{