523 lines
13 KiB
C++
523 lines
13 KiB
C++
/* -*- 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.1 (the "License"); you may not use this file
|
|
* except in compliance with the License. You may obtain a copy of
|
|
* the License at http://www.mozilla.org/NPL/
|
|
*
|
|
* Software distributed under the License is distributed on an "AS
|
|
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
|
* implied. See the License for the specific language governing
|
|
* rights and limitations under the License.
|
|
*
|
|
* The Original Code is mozilla.org code.
|
|
*
|
|
* The Initial Developer of the Original Code is Netscape
|
|
* Communications Corporation. Portions created by Netscape are
|
|
* Copyright (C) 1998 Netscape Communications Corporation. All
|
|
* Rights Reserved.
|
|
*
|
|
* Contributor(s):
|
|
*/
|
|
|
|
#include "nsJVMManager.h"
|
|
#include "nsIServiceManager.h"
|
|
#include "nsIJVMPrefsWindow.h"
|
|
#include "ProxyJNI.h"
|
|
#include "lcglue.h"
|
|
#include "nsCSecurityContext.h"
|
|
#include "nsISecurityContext.h"
|
|
|
|
static NS_DEFINE_CID(kJVMManagerCID, NS_JVMMANAGER_CID);
|
|
static NS_DEFINE_IID(kIJVMManagerIID, NS_IJVMMANAGER_IID);
|
|
static NS_DEFINE_IID(kIJVMConsoleIID, NS_IJVMCONSOLE_IID);
|
|
static NS_DEFINE_IID(kIJVMPrefsWindowIID, NS_IJVMPREFSWINDOW_IID);
|
|
static NS_DEFINE_IID(kISymantecDebuggerIID, NS_ISYMANTECDEBUGGER_IID);
|
|
static NS_DEFINE_IID(kISecurityContextIID, NS_ISECURITYCONTEXT_IID);
|
|
|
|
PR_BEGIN_EXTERN_C
|
|
|
|
#ifdef PRE_SERVICE_MANAGER
|
|
extern nsPluginManager* thePluginManager;
|
|
#endif
|
|
|
|
PR_IMPLEMENT(nsJVMManager*)
|
|
JVM_GetJVMMgr(void)
|
|
{
|
|
#ifdef PRE_SERVICE_MANAGER
|
|
nsresult result = NS_OK;
|
|
if (thePluginManager == NULL) {
|
|
result = nsPluginManager::Create(NULL, kIPluginManagerIID, (void**)&thePluginManager);
|
|
if (result != NS_OK)
|
|
return NULL;
|
|
}
|
|
nsJVMManager* mgr = NULL;
|
|
result = thePluginManager->QueryInterface(kIJVMManagerIID, (void**)&mgr);
|
|
if (result != NS_OK)
|
|
return NULL;
|
|
return mgr;
|
|
#else
|
|
nsJVMManager* mgr = NULL;
|
|
nsresult err = nsServiceManager::GetService(kJVMManagerCID, kIJVMManagerIID,
|
|
(nsISupports**)&mgr);
|
|
if (err != NS_OK)
|
|
return NULL;
|
|
return mgr;
|
|
#endif
|
|
}
|
|
|
|
PR_IMPLEMENT(void)
|
|
JVM_ReleaseJVMMgr(nsJVMManager* mgr)
|
|
{
|
|
nsresult err = nsServiceManager::ReleaseService(kJVMManagerCID, (nsISupports*)((nsIJVMManager*)mgr));
|
|
PR_ASSERT(err == NS_OK);
|
|
}
|
|
|
|
static nsIJVMPlugin*
|
|
GetRunningJVM(void)
|
|
{
|
|
nsIJVMPlugin* jvm = NULL;
|
|
nsJVMManager* jvmMgr = JVM_GetJVMMgr();
|
|
if (jvmMgr) {
|
|
nsJVMStatus status = jvmMgr->GetJVMStatus();
|
|
if (status == nsJVMStatus_Enabled)
|
|
status = jvmMgr->StartupJVM();
|
|
if (status == nsJVMStatus_Running) {
|
|
jvm = jvmMgr->GetJVMPlugin();
|
|
}
|
|
// jvmMgr->Release();
|
|
}
|
|
return jvm;
|
|
}
|
|
|
|
PR_IMPLEMENT(nsJVMStatus)
|
|
JVM_StartupJVM(void)
|
|
{
|
|
nsIJVMPlugin* jvm = GetRunningJVM();
|
|
return JVM_GetJVMStatus();
|
|
}
|
|
|
|
PR_IMPLEMENT(nsJVMStatus)
|
|
JVM_ShutdownJVM(void)
|
|
{
|
|
nsJVMStatus status = nsJVMStatus_Failed;
|
|
nsJVMManager* mgr = JVM_GetJVMMgr();
|
|
if (mgr) {
|
|
status = mgr->ShutdownJVM();
|
|
// mgr->Release();
|
|
}
|
|
return status;
|
|
}
|
|
|
|
|
|
PR_IMPLEMENT(nsJVMStatus)
|
|
JVM_GetJVMStatus(void)
|
|
{
|
|
nsJVMStatus status = nsJVMStatus_Disabled;
|
|
nsJVMManager* mgr = JVM_GetJVMMgr();
|
|
if (mgr) {
|
|
status = mgr->GetJVMStatus();
|
|
// mgr->Release();
|
|
}
|
|
return status;
|
|
}
|
|
|
|
PR_IMPLEMENT(PRBool)
|
|
JVM_AddToClassPath(const char* dirPath)
|
|
{
|
|
nsresult err = NS_ERROR_FAILURE;
|
|
nsJVMManager* mgr = JVM_GetJVMMgr();
|
|
if (mgr) {
|
|
err = mgr->AddToClassPath(dirPath);
|
|
// mgr->Release();
|
|
}
|
|
return err == NS_OK;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// This will get the JVMConsole if one is available. You have to Release it
|
|
// when you're done with it.
|
|
static nsIJVMConsole*
|
|
GetConsole(void)
|
|
{
|
|
nsIJVMConsole* console = NULL;
|
|
nsIJVMPlugin* jvm = GetRunningJVM();
|
|
if (jvm) {
|
|
jvm->QueryInterface(kIJVMConsoleIID, (void**)&console);
|
|
// jvm->Release(); // GetRunningJVM no longer calls AddRef
|
|
}
|
|
return console;
|
|
}
|
|
|
|
PR_IMPLEMENT(void)
|
|
JVM_ShowConsole(void)
|
|
{
|
|
nsIJVMConsole* console = GetConsole();
|
|
if (console) {
|
|
console->Show();
|
|
console->Release();
|
|
}
|
|
}
|
|
|
|
PR_IMPLEMENT(void)
|
|
JVM_HideConsole(void)
|
|
{
|
|
nsJVMStatus status = JVM_GetJVMStatus();
|
|
if (status == nsJVMStatus_Running) {
|
|
nsIJVMConsole* console = GetConsole();
|
|
if (console) {
|
|
console->Hide();
|
|
console->Release();
|
|
}
|
|
}
|
|
}
|
|
|
|
PR_IMPLEMENT(PRBool)
|
|
JVM_IsConsoleVisible(void)
|
|
{
|
|
PRBool result = PR_FALSE;
|
|
nsJVMStatus status = JVM_GetJVMStatus();
|
|
if (status == nsJVMStatus_Running) {
|
|
nsIJVMConsole* console = GetConsole();
|
|
if (console) {
|
|
nsresult err = console->IsVisible(&result);
|
|
PR_ASSERT(err != NS_OK ? result == PR_FALSE : PR_TRUE);
|
|
console->Release();
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
PR_IMPLEMENT(void)
|
|
JVM_PrintToConsole(const char* msg)
|
|
{
|
|
nsJVMStatus status = JVM_GetJVMStatus();
|
|
if (status != nsJVMStatus_Running)
|
|
return;
|
|
nsIJVMConsole* console = GetConsole();
|
|
if (console) {
|
|
console->Print(msg);
|
|
console->Release();
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// This will get the JVMPrefsWindow if one is available. You have to Release it
|
|
// when you're done with it.
|
|
static nsIJVMPrefsWindow*
|
|
GetPrefsWindow(void)
|
|
{
|
|
nsIJVMPrefsWindow* prefsWin = NULL;
|
|
nsIJVMPlugin* jvm = GetRunningJVM();
|
|
if (jvm) {
|
|
jvm->QueryInterface(kIJVMPrefsWindowIID, (void**)&prefsWin);
|
|
// jvm->Release(); // GetRunningJVM no longer calls AddRef
|
|
}
|
|
return prefsWin;
|
|
}
|
|
|
|
PR_IMPLEMENT(void)
|
|
JVM_ShowPrefsWindow(void)
|
|
{
|
|
nsIJVMPrefsWindow* prefsWin = GetPrefsWindow();
|
|
if (prefsWin) {
|
|
prefsWin->Show();
|
|
prefsWin->Release();
|
|
}
|
|
}
|
|
|
|
PR_IMPLEMENT(void)
|
|
JVM_HidePrefsWindow(void)
|
|
{
|
|
nsJVMStatus status = JVM_GetJVMStatus();
|
|
if (status == nsJVMStatus_Running) {
|
|
nsIJVMPrefsWindow* prefsWin = GetPrefsWindow();
|
|
if (prefsWin) {
|
|
prefsWin->Hide();
|
|
prefsWin->Release();
|
|
}
|
|
}
|
|
}
|
|
|
|
PR_IMPLEMENT(PRBool)
|
|
JVM_IsPrefsWindowVisible(void)
|
|
{
|
|
PRBool result = PR_FALSE;
|
|
nsJVMStatus status = JVM_GetJVMStatus();
|
|
if (status == nsJVMStatus_Running) {
|
|
nsIJVMPrefsWindow* prefsWin = GetPrefsWindow();
|
|
if (prefsWin) {
|
|
nsresult err = prefsWin->IsVisible(&result);
|
|
PR_ASSERT(err != NS_OK ? result == PR_FALSE : PR_TRUE);
|
|
prefsWin->Release();
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
PR_IMPLEMENT(void)
|
|
JVM_StartDebugger(void)
|
|
{
|
|
nsIJVMPlugin* jvm = GetRunningJVM();
|
|
if (jvm) {
|
|
nsISymantecDebugger* debugger;
|
|
if (jvm->QueryInterface(kISymantecDebuggerIID, (void**)&debugger) == NS_OK) {
|
|
// XXX should we make sure the vm is started first?
|
|
debugger->StartDebugger(nsSymantecDebugPort_SharedMemory);
|
|
debugger->Release();
|
|
}
|
|
// jvm->Release(); // GetRunningJVM no longer calls AddRef
|
|
}
|
|
}
|
|
|
|
|
|
PR_IMPLEMENT(JNIEnv*)
|
|
JVM_GetJNIEnv(void)
|
|
{
|
|
/* get proxy env for current thread. */
|
|
JVMContext* context = GetJVMContext();
|
|
JNIEnv* env = context->proxyEnv;
|
|
if (env != NULL)
|
|
return env;
|
|
|
|
// Create a Proxy JNI to associate with this NSPR thread.
|
|
nsIJVMPlugin* jvmPlugin = GetRunningJVM();
|
|
if (jvmPlugin != NULL)
|
|
env = CreateProxyJNI(jvmPlugin);
|
|
|
|
/* Associate the JNIEnv with the current thread. */
|
|
context->proxyEnv = env;
|
|
|
|
return env;
|
|
}
|
|
|
|
PR_IMPLEMENT(void)
|
|
JVM_ReleaseJNIEnv(JNIEnv* env)
|
|
{
|
|
/**
|
|
* this is now done when the NSPR thread is shutdown. JNIEnvs are always tied to the
|
|
* lifetime of threads.
|
|
*/
|
|
}
|
|
|
|
PR_IMPLEMENT(nsresult)
|
|
JVM_SpendTime(PRUint32 timeMillis)
|
|
{
|
|
#ifdef XP_MAC
|
|
nsresult result = NS_ERROR_NOT_INITIALIZED;
|
|
nsIJVMPlugin* jvm = GetRunningJVM();
|
|
if (jvm != NULL)
|
|
result = jvm->SpendTime(timeMillis);
|
|
return result;
|
|
#else
|
|
return NS_ERROR_NOT_IMPLEMENTED;
|
|
#endif
|
|
}
|
|
|
|
PR_IMPLEMENT(PRBool)
|
|
JVM_MaybeStartupLiveConnect()
|
|
{
|
|
PRBool result = PR_FALSE;
|
|
nsJVMManager* mgr = JVM_GetJVMMgr();
|
|
if (mgr) {
|
|
result = mgr->MaybeStartupLiveConnect();
|
|
// mgr->Release();
|
|
}
|
|
return result;
|
|
}
|
|
|
|
|
|
PR_IMPLEMENT(PRBool)
|
|
JVM_MaybeShutdownLiveConnect(void)
|
|
{
|
|
PRBool result = PR_FALSE;
|
|
nsJVMManager* mgr = JVM_GetJVMMgr();
|
|
if (mgr) {
|
|
result = mgr->MaybeShutdownLiveConnect();
|
|
// mgr->Release();
|
|
}
|
|
return result;
|
|
}
|
|
|
|
PR_IMPLEMENT(PRBool)
|
|
JVM_IsLiveConnectEnabled(void)
|
|
{
|
|
PRBool result = PR_FALSE;
|
|
nsJVMManager* mgr = JVM_GetJVMMgr();
|
|
if (mgr) {
|
|
result = mgr->IsLiveConnectEnabled();
|
|
// mgr->Release();
|
|
}
|
|
return result;
|
|
}
|
|
|
|
|
|
static
|
|
JVMSecurityStack *
|
|
findPrevNode(JSStackFrame *pCurrentFrame)
|
|
{
|
|
JVMContext* context = GetJVMContext();
|
|
JVMSecurityStack *pSecInfoBottom = context->securityStack;
|
|
if (pSecInfoBottom == NULL)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
JVMSecurityStack *pSecInfoTop = pSecInfoBottom->prev;
|
|
if (pCurrentFrame == NULL)
|
|
{
|
|
return pSecInfoTop;
|
|
}
|
|
if ( pSecInfoBottom->pJavaToJSFrame == pCurrentFrame )
|
|
{
|
|
return NULL;
|
|
}
|
|
JVMSecurityStack *pTempSecNode = pSecInfoTop;
|
|
|
|
while( pTempSecNode->pJSToJavaFrame != pCurrentFrame )
|
|
{
|
|
pTempSecNode = pTempSecNode->prev;
|
|
if ( pTempSecNode == pSecInfoTop )
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
if( pTempSecNode->pJSToJavaFrame == pCurrentFrame )
|
|
{
|
|
return pTempSecNode;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
PR_IMPLEMENT(PRBool)
|
|
JVM_NSISecurityContextImplies(JSStackFrame *pCurrentFrame, const char* target, const char* action)
|
|
{
|
|
JVMSecurityStack *pSecInfo = findPrevNode(pCurrentFrame);
|
|
|
|
if (pSecInfo == NULL)
|
|
{
|
|
return PR_FALSE;
|
|
}
|
|
|
|
nsISecurityContext *pNSISecurityContext = (nsISecurityContext *)pSecInfo->pNSISecurityContext;
|
|
PRBool bAllowedAccess = PR_FALSE;
|
|
if (pNSISecurityContext != NULL)
|
|
{
|
|
pNSISecurityContext->Implies(target, action, &bAllowedAccess);
|
|
}
|
|
return bAllowedAccess;
|
|
}
|
|
|
|
PR_IMPLEMENT(void *)
|
|
JVM_GetJavaPrincipalsFromStackAsNSVector(JSStackFrame *pCurrentFrame)
|
|
{
|
|
JVMSecurityStack *pSecInfo = findPrevNode(pCurrentFrame);
|
|
|
|
if (pSecInfo == NULL)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
JVMContext* context = GetJVMContext();
|
|
JSContext *pJSCX = context->js_context;
|
|
if (pJSCX == NULL)
|
|
{
|
|
//TODO: Get to the new context from DOM.
|
|
//pJSCX = LM_GetCrippledContext();
|
|
}
|
|
/*
|
|
** TODO: Get raman's help here. I don't know how we are going to give back a nsPrincipals array.
|
|
** Tom's new code should now use a different signature and accept a nsIPrincipal vector object
|
|
** instead in lm_taint.c and then call into caps. Caps needs to change to accommodate this.
|
|
void *pNSPrincipalArray = ConvertNSIPrincipalToNSPrincipalArray(NULL, pJSCX, pSecInfo->pNSIPrincipaArray,
|
|
pSecInfo->numPrincipals, pSecInfo->pNSISecurityContext);
|
|
if (pNSPrincipalArray != NULL)
|
|
{
|
|
return pNSPrincipalArray;
|
|
}
|
|
*/
|
|
return NULL;
|
|
}
|
|
|
|
|
|
PR_IMPLEMENT(JSPrincipals*)
|
|
JVM_GetJavaPrincipalsFromStack(JSStackFrame *pCurrentFrame)
|
|
{
|
|
JVMSecurityStack *pSecInfo = findPrevNode(pCurrentFrame);
|
|
|
|
if (pSecInfo == NULL)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
JVMContext* context = GetJVMContext();
|
|
JSContext *pJSCX = context->js_context;
|
|
if (pJSCX == NULL)
|
|
{
|
|
//TODO: Get to the new context from DOM.
|
|
//pJSCX = LM_GetCrippledContext();
|
|
}
|
|
/* TODO:
|
|
** Get raman's help here. We should not need to convert nsIPrincipal to nsPrincipal anymore.
|
|
** But we should convert from nsIPrincipal array to a nsIPrincipal array object represented as
|
|
** nsVector. Use this vector to pass into Tom's code to get to the JSPrinciapals
|
|
void *pNSPrincipalArray = ConvertNSIPrincipalArrayToObject(NULL, pJSCX, pSecInfo->pNSIPrincipaArray,
|
|
pSecInfo->numPrincipals, pSecInfo->pNSISecurityContext);
|
|
if (pNSPrincipalArray != NULL)
|
|
{
|
|
return LM_GetJSPrincipalsFromJavaCaller(pJSCX, pNSPrincipalArray, pSecInfo->pNSISecurityContext);
|
|
}
|
|
*/
|
|
return NULL;
|
|
}
|
|
|
|
PR_IMPLEMENT(JSStackFrame*)
|
|
JVM_GetEndJSFrameFromParallelStack(JSStackFrame *pCurrentFrame)
|
|
{
|
|
JVMSecurityStack *pSecInfo = findPrevNode(pCurrentFrame);
|
|
|
|
if (pSecInfo == NULL)
|
|
{
|
|
return NULL;
|
|
}
|
|
return pSecInfo->pJavaToJSFrame;
|
|
}
|
|
|
|
PR_IMPLEMENT(JSStackFrame**)
|
|
JVM_GetStartJSFrameFromParallelStack()
|
|
{
|
|
JVMContext* context = GetJVMContext();
|
|
return &context->js_startframe;
|
|
}
|
|
|
|
PR_IMPLEMENT(nsISecurityContext*)
|
|
JVM_GetJSSecurityContext()
|
|
{
|
|
JVMContext* context = GetJVMContext();
|
|
JVMSecurityStack *securityStack = context->securityStack;
|
|
JVMSecurityStack *securityStackTop = NULL;
|
|
JSContext *cx = context->js_context;
|
|
|
|
if(securityStack != NULL) {
|
|
securityStackTop = securityStack->prev;
|
|
JSStackFrame *fp = NULL;
|
|
securityStackTop->pJSToJavaFrame = JS_FrameIterator(cx, &fp);
|
|
}
|
|
|
|
nsCSecurityContext *securityContext = new nsCSecurityContext(cx);
|
|
if (securityContext == nsnull) {
|
|
return nsnull;
|
|
}
|
|
|
|
NS_ADDREF(securityContext);
|
|
return securityContext;
|
|
}
|
|
|
|
PR_END_EXTERN_C
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|