extern "C" NS_EXPORT void JNICALL XPCOM_NATIVE(shutdownXPCOM) (JNIEnv *env, jobject, jobject aServMgr) { nsresult rv; nsIServiceManager* servMgr = nullptr; if (aServMgr) { // Get native XPCOM instance nsISupports* instancePtr = nullptr; rv = JavaObjectToNativeInterface(env, aServMgr, NS_GET_IID(nsIServiceManager), (void**) &instancePtr); NS_ASSERTION(NS_SUCCEEDED(rv) && instancePtr != nullptr, "Failed to get XPCOM obj for ServiceMgr."); if (NS_SUCCEEDED(rv)) { rv = instancePtr->QueryInterface(NS_GET_IID(nsIServiceManager), (void**) &servMgr); NS_ASSERTION(NS_SUCCEEDED(rv), "QI for nsIServiceManager failed"); } // Even if we failed to get the matching xpcom object, we don't abort this // function. Just call NS_ShutdownXPCOM with a null service manager. } // Free globals before calling NS_ShutdownXPCOM(), since we need some // XPCOM services. FreeJavaGlobals(env); rv = NS_ShutdownXPCOM(servMgr); if (NS_FAILED(rv)) ThrowException(env, rv, "NS_ShutdownXPCOM failed"); }
extern "C" NS_EXPORT jlong JNICALL JXUTILS_NATIVE(wrapJavaObject) (JNIEnv* env, jobject, jobject aJavaObject, jstring aIID) { nsresult rv; void* xpcomObject = nullptr; if (!aJavaObject || !aIID) { rv = NS_ERROR_NULL_POINTER; } else { const char* str = env->GetStringUTFChars(aIID, nullptr); if (!str) { rv = NS_ERROR_OUT_OF_MEMORY; } else { nsID iid; if (iid.Parse(str)) { rv = JavaObjectToNativeInterface(env, aJavaObject, iid, &xpcomObject); if (NS_SUCCEEDED(rv)) { rv = ((nsISupports*) xpcomObject)->QueryInterface(iid, &xpcomObject); } } else { rv = NS_ERROR_INVALID_ARG; } env->ReleaseStringUTFChars(aIID, str); } } if (NS_FAILED(rv)) { ThrowException(env, rv, "Failed to create XPCOM proxy for Java object"); } return reinterpret_cast<jlong>(xpcomObject); }
/** * Handle 'inout', 'out', and 'retval' params */ nsresult nsJavaXPTCStub::FinalizeJavaParams(const nsXPTParamInfo &aParamInfo, const XPTMethodDescriptor *aMethodInfo, PRUint16 aMethodIndex, nsXPTCMiniVariant* aDispatchParams, nsXPTCMiniVariant &aVariant, jvalue &aJValue) { nsresult rv = NS_OK; JNIEnv* env = GetJNIEnv(); const nsXPTType &type = aParamInfo.GetType(); PRUint8 tag = type.TagPart(); switch (tag) { case nsXPTType::T_I8: { jbyte value; if (aParamInfo.IsRetval()) { // 'retval' value = aJValue.b; } else if (aJValue.l) { // 'inout' & 'out' env->GetByteArrayRegion((jbyteArray) aJValue.l, 0, 1, &value); } if (aVariant.val.p) *((PRInt8 *) aVariant.val.p) = value; } break; case nsXPTType::T_U8: case nsXPTType::T_I16: { jshort value = 0; if (aParamInfo.IsRetval()) { // 'retval' value = aJValue.s; } else if (aJValue.l) { // 'inout' & 'out' env->GetShortArrayRegion((jshortArray) aJValue.l, 0, 1, &value); } if (aVariant.val.p) { if (tag == nsXPTType::T_U8) *((PRUint8 *) aVariant.val.p) = value; else *((PRInt16 *) aVariant.val.p) = value; } } break; case nsXPTType::T_U16: case nsXPTType::T_I32: { jint value = 0; if (aParamInfo.IsRetval()) { // 'retval' value = aJValue.i; } else if (aJValue.l) { // 'inout' & 'out' env->GetIntArrayRegion((jintArray) aJValue.l, 0, 1, &value); } if (aVariant.val.p) { if (tag == nsXPTType::T_U16) *((PRUint16 *) aVariant.val.p) = value; else *((PRInt32 *) aVariant.val.p) = value; } } break; case nsXPTType::T_U32: case nsXPTType::T_I64: { jlong value = 0; if (aParamInfo.IsRetval()) { // 'retval' value = aJValue.j; } else if (aJValue.l) { // 'inout' & 'out' env->GetLongArrayRegion((jlongArray) aJValue.l, 0, 1, &value); } if (aVariant.val.p) { if (tag == nsXPTType::T_U32) *((PRUint32 *) aVariant.val.p) = value; else *((PRInt64 *) aVariant.val.p) = value; } } break; case nsXPTType::T_FLOAT: { if (aParamInfo.IsRetval()) { // 'retval' *((float *) aVariant.val.p) = aJValue.f; } else if (aJValue.l) { // 'inout' & 'out' env->GetFloatArrayRegion((jfloatArray) aJValue.l, 0, 1, (jfloat*) aVariant.val.p); } } break; // XXX how do we handle 64-bit values? case nsXPTType::T_U64: case nsXPTType::T_DOUBLE: { jdouble value = 0; if (aParamInfo.IsRetval()) { // 'retval' value = aJValue.d; } else if (aJValue.l) { // 'inout' & 'out' env->GetDoubleArrayRegion((jdoubleArray) aJValue.l, 0, 1, &value); } if (aVariant.val.p) { if (tag == nsXPTType::T_DOUBLE) *((double *) aVariant.val.p) = value; else *((PRUint64 *) aVariant.val.p) = static_cast<PRUint64>(value); } } break; case nsXPTType::T_BOOL: { if (aParamInfo.IsRetval()) { // 'retval' *((PRBool *) aVariant.val.p) = aJValue.z; } else if (aJValue.l) { // 'inout' & 'out' env->GetBooleanArrayRegion((jbooleanArray) aJValue.l, 0, 1, (jboolean*) aVariant.val.p); } } break; case nsXPTType::T_CHAR: case nsXPTType::T_WCHAR: { if (aParamInfo.IsRetval()) { // 'retval' if (type.TagPart() == nsXPTType::T_CHAR) *((char *) aVariant.val.p) = aJValue.c; else *((PRUnichar *) aVariant.val.p) = aJValue.c; } else if (aJValue.l) { // 'inout' & 'out' jchar* array = env->GetCharArrayElements((jcharArray) aJValue.l, nsnull); if (!array) { rv = NS_ERROR_OUT_OF_MEMORY; break; } if (type.TagPart() == nsXPTType::T_CHAR) *((char *) aVariant.val.p) = array[0]; else *((PRUnichar *) aVariant.val.p) = array[0]; env->ReleaseCharArrayElements((jcharArray) aJValue.l, array, JNI_ABORT); } } break; case nsXPTType::T_CHAR_STR: { jstring str = nsnull; if (aParamInfo.IsRetval()) { // 'retval' str = (jstring) aJValue.l; } else { // 'inout' & 'out' str = (jstring) env->GetObjectArrayElement((jobjectArray) aJValue.l, 0); } char** variant = static_cast<char**>(aVariant.val.p); if (str) { // Get string buffer const char* char_ptr = env->GetStringUTFChars(str, nsnull); if (!char_ptr) { rv = NS_ERROR_OUT_OF_MEMORY; break; } // If new string is different from one passed in, free old string // and replace with new string. if (aParamInfo.IsRetval() || *variant == nsnull || strcmp(*variant, char_ptr) != 0) { if (!aParamInfo.IsRetval() && *variant) PR_Free(*variant); *variant = strdup(char_ptr); if (*variant == nsnull) { rv = NS_ERROR_OUT_OF_MEMORY; // don't 'break'; fall through to release chars } } // Release string buffer env->ReleaseStringUTFChars(str, char_ptr); } else { // If we were passed in a string, delete it now, and set to null. // (Only for 'inout' & 'out' params) if (*variant && !aParamInfo.IsRetval()) { PR_Free(*variant); } *variant = nsnull; } } break; case nsXPTType::T_WCHAR_STR: { jstring str = nsnull; if (aParamInfo.IsRetval()) { // 'retval' str = (jstring) aJValue.l; } else { // 'inout' & 'out' str = (jstring) env->GetObjectArrayElement((jobjectArray) aJValue.l, 0); } PRUnichar** variant = static_cast<PRUnichar**>(aVariant.val.p); if (str) { // Get string buffer const jchar* wchar_ptr = env->GetStringChars(str, nsnull); if (!wchar_ptr) { rv = NS_ERROR_OUT_OF_MEMORY; break; } // If new string is different from one passed in, free old string // and replace with new string. We if (aParamInfo.IsRetval() || *variant == nsnull || nsCRT::strcmp(*variant, wchar_ptr) != 0) { if (!aParamInfo.IsRetval() && *variant) PR_Free(*variant); PRUint32 length = nsCRT::strlen(wchar_ptr); *variant = (PRUnichar*) PR_Malloc((length + 1) * sizeof(PRUnichar)); if (*variant) { memcpy(*variant, wchar_ptr, length * sizeof(PRUnichar)); (*variant)[length] = 0; } else { rv = NS_ERROR_OUT_OF_MEMORY; // don't 'break'; fall through to release chars } } // Release string buffer env->ReleaseStringChars(str, wchar_ptr); } else { // If we were passed in a string, delete it now, and set to null. // (Only for 'inout' & 'out' params) if (*variant && !aParamInfo.IsRetval()) { PR_Free(*variant); } *variant = nsnull; } } break; case nsXPTType::T_IID: { jstring str = nsnull; if (aParamInfo.IsRetval()) { // 'retval' str = (jstring) aJValue.l; } else { // 'inout' & 'out' str = (jstring) env->GetObjectArrayElement((jobjectArray) aJValue.l, 0); } nsID** variant = static_cast<nsID**>(aVariant.val.p); if (str) { // Get string buffer const char* char_ptr = env->GetStringUTFChars(str, nsnull); if (!char_ptr) { rv = NS_ERROR_OUT_OF_MEMORY; break; } if (!aParamInfo.IsRetval() && *variant) { // If we were given an nsID, set it to the new string nsID* oldIID = *variant; oldIID->Parse(char_ptr); } else { // If the argument that was passed in was null, then we need to // create a new nsID. nsID* newIID = new nsID; if (newIID) { newIID->Parse(char_ptr); *variant = newIID; } else { rv = NS_ERROR_OUT_OF_MEMORY; // don't 'break'; fall through to release chars } } // Release string buffer env->ReleaseStringUTFChars(str, char_ptr); } else { // If we were passed in an nsID, delete it now, and set to null. // (Free only 'inout' & 'out' params) if (*variant && !aParamInfo.IsRetval()) { delete *variant; } *variant = nsnull; } } break; case nsXPTType::T_INTERFACE: case nsXPTType::T_INTERFACE_IS: { jobject java_obj = nsnull; if (aParamInfo.IsRetval()) { // 'retval' java_obj = aJValue.l; } else if (aJValue.l) { // 'inout' & 'out' java_obj = env->GetObjectArrayElement((jobjectArray) aJValue.l, 0); } void* xpcom_obj = nsnull; if (java_obj) { // Get IID for this param nsID iid; rv = GetIIDForMethodParam(mIInfo, aMethodInfo, aParamInfo, aParamInfo.GetType().TagPart(), aMethodIndex, aDispatchParams, PR_FALSE, iid); if (NS_FAILED(rv)) break; // If the requested interface is nsIWeakReference, then we look for or // create a stub for the nsISupports interface. Then we create a weak // reference from that stub. PRBool isWeakRef; if (iid.Equals(NS_GET_IID(nsIWeakReference))) { isWeakRef = PR_TRUE; iid = NS_GET_IID(nsISupports); } else { isWeakRef = PR_FALSE; } rv = JavaObjectToNativeInterface(env, java_obj, iid, &xpcom_obj); if (NS_FAILED(rv)) break; rv = ((nsISupports*) xpcom_obj)->QueryInterface(iid, &xpcom_obj); if (NS_FAILED(rv)) break; // If the function expects a weak reference, then we need to // create it here. if (isWeakRef) { nsISupports* isupports = (nsISupports*) xpcom_obj; nsCOMPtr<nsISupportsWeakReference> supportsweak = do_QueryInterface(isupports); if (supportsweak) { nsWeakPtr weakref; supportsweak->GetWeakReference(getter_AddRefs(weakref)); NS_RELEASE(isupports); xpcom_obj = weakref; NS_ADDREF((nsISupports*) xpcom_obj); } else { xpcom_obj = nsnull; } } } // For 'inout' params, if the resulting xpcom value is different than the // one passed in, then we must release the incoming xpcom value. nsISupports** variant = static_cast<nsISupports**>(aVariant.val.p); if (aParamInfo.IsIn() && *variant) { nsCOMPtr<nsISupports> in = do_QueryInterface(*variant); nsCOMPtr<nsISupports> out = do_QueryInterface((nsISupports*) xpcom_obj); if (in != out) { NS_RELEASE(*variant); } } *(static_cast<void**>(aVariant.val.p)) = xpcom_obj; } break; case nsXPTType::T_ASTRING: case nsXPTType::T_DOMSTRING: { NS_PRECONDITION(aParamInfo.IsDipper(), "string argument is not dipper"); if (!aParamInfo.IsDipper()) { rv = NS_ERROR_UNEXPECTED; break; } jstring jstr = (jstring) aJValue.l; nsString* variant = static_cast<nsString*>(aVariant.val.p); if (jstr) { // Get string buffer const jchar* wchar_ptr = env->GetStringChars(jstr, nsnull); if (!wchar_ptr) { rv = NS_ERROR_OUT_OF_MEMORY; break; } variant->Assign(wchar_ptr); // release String buffer env->ReleaseStringChars(jstr, wchar_ptr); } else { variant->SetIsVoid(PR_TRUE); } } break; case nsXPTType::T_UTF8STRING: case nsXPTType::T_CSTRING: { NS_PRECONDITION(aParamInfo.IsDipper(), "string argument is not dipper"); if (!aParamInfo.IsDipper()) { rv = NS_ERROR_UNEXPECTED; break; } jstring jstr = (jstring) aJValue.l; nsCString* variant = static_cast<nsCString*>(aVariant.val.p); if (jstr) { // Get string buffer const char* char_ptr = env->GetStringUTFChars(jstr, nsnull); if (!char_ptr) { rv = NS_ERROR_OUT_OF_MEMORY; break; } variant->Assign(char_ptr); // release String buffer env->ReleaseStringUTFChars(jstr, char_ptr); } else { variant->SetIsVoid(PR_TRUE); } } break; case nsXPTType::T_VOID: { if (aParamInfo.IsRetval()) { // 'retval' aVariant.val.p = reinterpret_cast<void*>(aJValue.j); } else if (aJValue.l) { // 'inout' & 'out' env->GetLongArrayRegion((jlongArray) aJValue.l, 0, 1, (jlong*) aVariant.val.p); } } break; default: NS_WARNING("unexpected parameter type"); return NS_ERROR_UNEXPECTED; } return rv; }