extern "C" NS_EXPORT jobject JNICALL JXUTILS_NATIVE(wrapXPCOMObject) (JNIEnv* env, jobject, jlong aXPCOMObject, jstring aIID) { nsresult rv; jobject javaObject = nullptr; nsISupports* xpcomObject = reinterpret_cast<nsISupports*>(aXPCOMObject); if (!xpcomObject || !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)) { // XXX Should we be passing something other than NULL for aObjectLoader? rv = NativeInterfaceToJavaObject(env, xpcomObject, iid, nullptr, &javaObject); } 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 javaObject; }
extern "C" NS_EXPORT jobject JNICALL XPCOM_NATIVE(newLocalFile) (JNIEnv *env, jobject, jstring aPath, jboolean aFollowLinks) { // Create a Mozilla string from the jstring const jchar* buf = nullptr; if (aPath) { buf = env->GetStringChars(aPath, nullptr); if (!buf) return nullptr; // exception already thrown } nsAutoString path_str(reinterpret_cast<const PRUnichar*>(buf)); env->ReleaseStringChars(aPath, buf); // Make call to given function nsCOMPtr<nsIFile> file; nsresult rv = NS_NewLocalFile(path_str, aFollowLinks, getter_AddRefs(file)); if (NS_SUCCEEDED(rv)) { jobject javaProxy; rv = NativeInterfaceToJavaObject(env, file, NS_GET_IID(nsILocalFile), nullptr, &javaProxy); if (NS_SUCCEEDED(rv)) return javaProxy; } ThrowException(env, rv, "Failure in newLocalFile"); return nullptr; }
nsresult InitXPCOM_Impl(JNIEnv* env, jobject aMozBinDirectory, jobject aAppFileLocProvider, jobject* aResult) { nsresult rv; // create an nsILocalFile from given java.io.File nsCOMPtr<nsIFile> directory; if (aMozBinDirectory) { rv = File_to_nsILocalFile(env, aMozBinDirectory, getter_AddRefs(directory)); NS_ENSURE_SUCCESS(rv, rv); } // create nsAppFileLocProviderProxy from given Java object nsCOMPtr<nsIDirectoryServiceProvider> provider; if (aAppFileLocProvider) { rv = NS_NewAppFileLocProviderProxy(aAppFileLocProvider, getter_AddRefs(provider)); NS_ENSURE_SUCCESS(rv, rv); } // init XPCOM nsCOMPtr<nsIServiceManager> servMan; rv = NS_InitXPCOM2(getter_AddRefs(servMan), directory, provider); NS_ENSURE_SUCCESS(rv, rv); // create Java proxy for service manager returned by NS_InitXPCOM2 return NativeInterfaceToJavaObject(env, servMan, NS_GET_IID(nsIServiceManager), nullptr, aResult); }
extern "C" NS_EXPORT jobject JNICALL XPCOM_NATIVE(getServiceManager) (JNIEnv *env, jobject) { // Call XPCOM method nsCOMPtr<nsIServiceManager> sm; nsresult rv = NS_GetServiceManager(getter_AddRefs(sm)); if (NS_SUCCEEDED(rv)) { jobject javaProxy; rv = NativeInterfaceToJavaObject(env, sm, NS_GET_IID(nsIServiceManager), nullptr, &javaProxy); if (NS_SUCCEEDED(rv)) return javaProxy; } ThrowException(env, rv, "Failure in getServiceManager"); return nullptr; }
extern "C" NS_EXPORT jobject JNICALL XPCOM_NATIVE(getComponentRegistrar) (JNIEnv *env, jobject) { // Call XPCOM method nsCOMPtr<nsIComponentRegistrar> cr; nsresult rv = NS_GetComponentRegistrar(getter_AddRefs(cr)); if (NS_SUCCEEDED(rv)) { jobject javaProxy; rv = NativeInterfaceToJavaObject(env, cr, NS_GET_IID(nsIComponentRegistrar), nullptr, &javaProxy); if (NS_SUCCEEDED(rv)) return javaProxy; } ThrowException(env, rv, "Failure in getComponentRegistrar"); return nullptr; }
/** * Handle 'in', 'inout', and 'out' params */ nsresult nsJavaXPTCStub::SetupJavaParams(const nsXPTParamInfo &aParamInfo, const XPTMethodDescriptor* aMethodInfo, PRUint16 aMethodIndex, nsXPTCMiniVariant* aDispatchParams, nsXPTCMiniVariant &aVariant, jvalue &aJValue, nsACString &aMethodSig) { nsresult rv = NS_OK; JNIEnv* env = GetJNIEnv(); const nsXPTType &type = aParamInfo.GetType(); PRUint8 tag = type.TagPart(); switch (tag) { case nsXPTType::T_I8: { if (!aParamInfo.IsOut()) { // 'in' aJValue.b = aVariant.val.i8; aMethodSig.Append('B'); } else { // 'inout' & 'out' if (aVariant.val.p) { jbyteArray array = env->NewByteArray(1); if (!array) { rv = NS_ERROR_OUT_OF_MEMORY; break; } env->SetByteArrayRegion(array, 0, 1, (jbyte*) aVariant.val.p); aJValue.l = array; } else { aJValue.l = nsnull; } aMethodSig.AppendLiteral("[B"); } } break; case nsXPTType::T_I16: case nsXPTType::T_U8: { if (!aParamInfo.IsOut()) { // 'in' aJValue.s = (tag == nsXPTType::T_I16) ? aVariant.val.i16 : aVariant.val.u8; aMethodSig.Append('S'); } else { // 'inout' & 'out' if (aVariant.val.p) { jshortArray array = env->NewShortArray(1); if (!array) { rv = NS_ERROR_OUT_OF_MEMORY; break; } env->SetShortArrayRegion(array, 0, 1, (jshort*) aVariant.val.p); aJValue.l = array; } else { aJValue.l = nsnull; } aMethodSig.AppendLiteral("[S"); } } break; case nsXPTType::T_I32: case nsXPTType::T_U16: { if (!aParamInfo.IsOut()) { // 'in' aJValue.i = (tag == nsXPTType::T_I32) ? aVariant.val.i32 : aVariant.val.u16; aMethodSig.Append('I'); } else { // 'inout' & 'out' if (aVariant.val.p) { jintArray array = env->NewIntArray(1); if (!array) { rv = NS_ERROR_OUT_OF_MEMORY; break; } env->SetIntArrayRegion(array, 0, 1, (jint*) aVariant.val.p); aJValue.l = array; } else { aJValue.l = nsnull; } aMethodSig.AppendLiteral("[I"); } } break; case nsXPTType::T_I64: case nsXPTType::T_U32: { if (!aParamInfo.IsOut()) { // 'in' aJValue.j = (tag == nsXPTType::T_I64) ? aVariant.val.i64 : aVariant.val.u32; aMethodSig.Append('J'); } else { // 'inout' & 'out' if (aVariant.val.p) { jlongArray array = env->NewLongArray(1); if (!array) { rv = NS_ERROR_OUT_OF_MEMORY; break; } env->SetLongArrayRegion(array, 0, 1, (jlong*) aVariant.val.p); aJValue.l = array; } else { aJValue.l = nsnull; } aMethodSig.AppendLiteral("[J"); } } break; case nsXPTType::T_FLOAT: { if (!aParamInfo.IsOut()) { // 'in' aJValue.f = aVariant.val.f; aMethodSig.Append('F'); } else { // 'inout' & 'out' if (aVariant.val.p) { jfloatArray array = env->NewFloatArray(1); if (!array) { rv = NS_ERROR_OUT_OF_MEMORY; break; } env->SetFloatArrayRegion(array, 0, 1, (jfloat*) aVariant.val.p); aJValue.l = array; } else { aJValue.l = nsnull; } aMethodSig.AppendLiteral("[F"); } } break; // XXX how do we handle unsigned 64-bit values? case nsXPTType::T_U64: case nsXPTType::T_DOUBLE: { if (!aParamInfo.IsOut()) { // 'in' aJValue.d = (tag == nsXPTType::T_DOUBLE) ? aVariant.val.d : aVariant.val.u64; aMethodSig.Append('D'); } else { // 'inout' & 'out' if (aVariant.val.p) { jdoubleArray array = env->NewDoubleArray(1); if (!array) { rv = NS_ERROR_OUT_OF_MEMORY; break; } env->SetDoubleArrayRegion(array, 0, 1, (jdouble*) aVariant.val.p); aJValue.l = array; } else { aJValue.l = nsnull; } aMethodSig.AppendLiteral("[D"); } } break; case nsXPTType::T_BOOL: { if (!aParamInfo.IsOut()) { // 'in' aJValue.z = aVariant.val.b; aMethodSig.Append('Z'); } else { // 'inout' & 'out' if (aVariant.val.p) { jbooleanArray array = env->NewBooleanArray(1); if (!array) { rv = NS_ERROR_OUT_OF_MEMORY; break; } env->SetBooleanArrayRegion(array, 0, 1, (jboolean*) aVariant.val.p); aJValue.l = array; } else { aJValue.l = nsnull; } aMethodSig.AppendLiteral("[Z"); } } break; case nsXPTType::T_CHAR: case nsXPTType::T_WCHAR: { if (!aParamInfo.IsOut()) { // 'in' if (tag == nsXPTType::T_CHAR) aJValue.c = aVariant.val.c; else aJValue.c = aVariant.val.wc; aMethodSig.Append('C'); } else { // 'inout' & 'out' if (aVariant.val.p) { jcharArray array = env->NewCharArray(1); if (!array) { rv = NS_ERROR_OUT_OF_MEMORY; break; } env->SetCharArrayRegion(array, 0, 1, (jchar*) aVariant.val.p); aJValue.l = array; } else { aJValue.l = nsnull; } aMethodSig.AppendLiteral("[C"); } } break; case nsXPTType::T_CHAR_STR: case nsXPTType::T_WCHAR_STR: { void* ptr = nsnull; if (!aParamInfo.IsOut()) { // 'in' ptr = aVariant.val.p; } else if (aVariant.val.p) { // 'inout' & 'out' void** variant = static_cast<void**>(aVariant.val.p); ptr = *variant; } jobject str; if (ptr) { if (tag == nsXPTType::T_CHAR_STR) { str = env->NewStringUTF((const char*) ptr); } else { const PRUnichar* buf = (const PRUnichar*) ptr; str = env->NewString(buf, nsCRT::strlen(buf)); } if (!str) { rv = NS_ERROR_OUT_OF_MEMORY; break; } } else { str = nsnull; } if (!aParamInfo.IsOut()) { // 'in' aJValue.l = str; aMethodSig.AppendLiteral("Ljava/lang/String;"); } else { // 'inout' & 'out' if (aVariant.val.p) { aJValue.l = env->NewObjectArray(1, stringClass, str); if (aJValue.l == nsnull) { rv = NS_ERROR_OUT_OF_MEMORY; break; } } else { aJValue.l = nsnull; } aMethodSig.AppendLiteral("[Ljava/lang/String;"); } } break; case nsXPTType::T_IID: { nsID* iid = nsnull; if (!aParamInfo.IsOut()) { // 'in' iid = static_cast<nsID*>(aVariant.val.p); } else if (aVariant.val.p) { // 'inout' & 'out' nsID** variant = static_cast<nsID**>(aVariant.val.p); iid = *variant; } jobject str = nsnull; if (iid) { char iid_str[NSID_LENGTH]; iid->ToProvidedString(iid_str); str = env->NewStringUTF(iid_str); if (!str) { rv = NS_ERROR_OUT_OF_MEMORY; break; } } if (!aParamInfo.IsOut()) { // 'in' aJValue.l = str; aMethodSig.AppendLiteral("Ljava/lang/String;"); } else { // 'inout' & 'out' if (aVariant.val.p) { aJValue.l = env->NewObjectArray(1, stringClass, str); if (aJValue.l == nsnull) { rv = NS_ERROR_OUT_OF_MEMORY; break; } } else { aJValue.l = nsnull; } aMethodSig.AppendLiteral("[Ljava/lang/String;"); } } break; case nsXPTType::T_INTERFACE: case nsXPTType::T_INTERFACE_IS: { nsISupports* xpcom_obj = nsnull; if (!aParamInfo.IsOut()) { // 'in' xpcom_obj = static_cast<nsISupports*>(aVariant.val.p); } else if (aVariant.val.p) { // 'inout' & 'out' nsISupports** variant = static_cast<nsISupports**>(aVariant.val.p); xpcom_obj = *variant; } nsID iid; rv = GetIIDForMethodParam(mIInfo, aMethodInfo, aParamInfo, aParamInfo.GetType().TagPart(), aMethodIndex, aDispatchParams, PR_FALSE, iid); if (NS_FAILED(rv)) break; // get name of interface char* iface_name = nsnull; nsCOMPtr<nsIInterfaceInfoManager> iim(do_GetService(NS_INTERFACEINFOMANAGER_SERVICE_CONTRACTID, &rv)); if (NS_FAILED(rv)) break; rv = iim->GetNameForIID(&iid, &iface_name); if (NS_FAILED(rv) || !iface_name) break; jobject java_stub = nsnull; if (xpcom_obj) { // Get matching Java object for given xpcom object jobject objLoader = env->CallObjectMethod(mJavaWeakRef, getReferentMID); rv = NativeInterfaceToJavaObject(env, xpcom_obj, iid, objLoader, &java_stub); if (NS_FAILED(rv)) break; } if (!aParamInfo.IsOut()) { // 'in' aJValue.l = java_stub; } else { // 'inout' & 'out' if (aVariant.val.p) { aJValue.l = env->NewObjectArray(1, nsISupportsClass, java_stub); if (aJValue.l == nsnull) { rv = NS_ERROR_OUT_OF_MEMORY; break; } } else { aJValue.l = nsnull; } aMethodSig.Append('['); } if (tag != nsXPTType::T_INTERFACE_IS) { aMethodSig.AppendLiteral("Lorg/mozilla/interfaces/"); aMethodSig.AppendASCII(iface_name); aMethodSig.Append(';'); } else { aMethodSig.AppendLiteral("Lorg/mozilla/interfaces/nsISupports;"); } nsMemory::Free(iface_name); } break; case nsXPTType::T_ASTRING: case nsXPTType::T_DOMSTRING: { // This only handle 'in' or 'in dipper' params. In XPIDL, the 'out' // descriptor is mapped to 'in dipper'. NS_PRECONDITION(aParamInfo.IsIn(), "unexpected param descriptor"); if (!aParamInfo.IsIn()) { rv = NS_ERROR_UNEXPECTED; break; } nsString* str = static_cast<nsString*>(aVariant.val.p); if (!str) { rv = NS_ERROR_FAILURE; break; } jstring jstr = nsnull; if (!str->IsVoid()) { jstr = env->NewString(str->get(), str->Length()); if (!jstr) { rv = NS_ERROR_OUT_OF_MEMORY; break; } } aJValue.l = jstr; aMethodSig.AppendLiteral("Ljava/lang/String;"); } break; case nsXPTType::T_UTF8STRING: case nsXPTType::T_CSTRING: { // This only handle 'in' or 'in dipper' params. In XPIDL, the 'out' // descriptor is mapped to 'in dipper'. NS_PRECONDITION(aParamInfo.IsIn(), "unexpected param descriptor"); if (!aParamInfo.IsIn()) { rv = NS_ERROR_UNEXPECTED; break; } nsCString* str = static_cast<nsCString*>(aVariant.val.p); if (!str) { rv = NS_ERROR_FAILURE; break; } jstring jstr = nsnull; if (!str->IsVoid()) { jstr = env->NewStringUTF(str->get()); if (!jstr) { rv = NS_ERROR_OUT_OF_MEMORY; break; } } aJValue.l = jstr; aMethodSig.AppendLiteral("Ljava/lang/String;"); } break; // Pass the 'void*' address as a long case nsXPTType::T_VOID: { if (!aParamInfo.IsOut()) { // 'in' aJValue.j = reinterpret_cast<jlong>(aVariant.val.p); aMethodSig.Append('J'); } else { // 'inout' & 'out' if (aVariant.val.p) { jlongArray array = env->NewLongArray(1); if (!array) { rv = NS_ERROR_OUT_OF_MEMORY; break; } env->SetLongArrayRegion(array, 0, 1, (jlong*) aVariant.val.p); aJValue.l = array; } else { aJValue.l = nsnull; } aMethodSig.AppendLiteral("[J"); } } break; case nsXPTType::T_ARRAY: NS_WARNING("array types are not yet supported"); return NS_ERROR_NOT_IMPLEMENTED; break; case nsXPTType::T_PSTRING_SIZE_IS: case nsXPTType::T_PWSTRING_SIZE_IS: default: NS_WARNING("unexpected parameter type"); return NS_ERROR_UNEXPECTED; } return rv; }