// @method string|Py_nsISupports|__repr__|Called to create a representation of a Py_nsISupports object /*static */PyObject * PyXPCOM_TypeObject::Py_repr(PyObject *self) { // @comm The repr of this object displays both the object's address, and its attached nsISupports's address Py_nsISupports *pis = (Py_nsISupports *)self; // Try and get the IID name. char *iid_repr = nsnull; nsCOMPtr<nsIInterfaceInfoManager> iim(do_GetService( NS_INTERFACEINFOMANAGER_SERVICE_CONTRACTID)); if (iim!=nsnull) iim->GetNameForIID(&pis->m_iid, &iid_repr); if (iid_repr==nsnull) // no IIM available, or it doesnt know the name. iid_repr = pis->m_iid.ToString(); // XXX - need some sort of buffer overflow. char buf[512]; #ifdef VBOX snprintf(buf, sizeof(buf), "<XPCOM object (%s) at %p/%p>", iid_repr, (void *)self, (void *)pis->m_obj.get()); #else sprintf(buf, "<XPCOM object (%s) at 0x%p/0x%p>", iid_repr, (void *)self, (void *)pis->m_obj.get()); #endif nsMemory::Free(iid_repr); #if PY_MAJOR_VERSION <= 2 return PyString_FromString(buf); #else return PyUnicode_FromString(buf); #endif }
static const void * find (const void *(*match) (nsIInterfaceInfo *, void *), void *item) { nsCOMPtr <nsIInterfaceInfoManager> iim (do_GetService (NS_INTERFACEINFOMANAGER_SERVICE_CONTRACTID)); nsIEnumerator *Interfaces = nsnull; nsISupports *is_Interface; nsIInterfaceInfo *Interface; nsresult rv; const void *ret = NULL; if (NS_FAILED (iim->EnumerateInterfaces (&Interfaces))) { NS_ASSERTION (0, "failed to get interface enumeration"); goto done; } if (NS_FAILED (rv = Interfaces->First ())) { NS_ASSERTION (0, "failed to go to first item in interface enumeration"); goto done; } do { if (NS_FAILED (rv = Interfaces->CurrentItem (&is_Interface))) { /* maybe something should be done, * debugging info at least? */ Interfaces->Next (); continue; } rv = is_Interface-> QueryInterface (NS_GET_IID (nsIInterfaceInfo), (void **) &Interface); if (!NS_FAILED (rv)) ret = (*match) (Interface, item); else abort (); if (ret) break; NS_RELEASE (Interface); NS_RELEASE (is_Interface); Interfaces->Next (); } while (Interfaces->IsDone () == NS_ENUMERATOR_FALSE); done: NS_IF_RELEASE (Interfaces); NS_IF_RELEASE (iim); NS_IF_RELEASE (is_Interface); return ret; }
nsresult nsScriptNameSpaceManager::FillHashWithDOMInterfaces() { nsCOMPtr<nsIInterfaceInfoManager> iim(do_GetService(NS_INTERFACEINFOMANAGER_SERVICE_CONTRACTID)); NS_ENSURE_TRUE(iim, NS_ERROR_UNEXPECTED); // First look for all interfaces whose name starts with nsIDOM nsCOMPtr<nsIEnumerator> domInterfaces; nsresult rv = iim->EnumerateInterfacesWhoseNamesStartWith(NS_DOM_INTERFACE_PREFIX, getter_AddRefs(domInterfaces)); NS_ENSURE_SUCCESS(rv, rv); nsCOMPtr<nsISupports> entry; rv = domInterfaces->First(); if (NS_FAILED(rv)) { // Empty interface list? NS_WARNING("What, no nsIDOM interfaces installed?"); return NS_OK; } bool found_old; nsCOMPtr<nsIInterfaceInfo> if_info; const char *if_name = nsnull; const nsIID *iid; for ( ; domInterfaces->IsDone() == NS_ENUMERATOR_FALSE; domInterfaces->Next()) { rv = domInterfaces->CurrentItem(getter_AddRefs(entry)); NS_ENSURE_SUCCESS(rv, rv); nsCOMPtr<nsIInterfaceInfo> if_info(do_QueryInterface(entry)); if_info->GetNameShared(&if_name); if_info->GetIIDShared(&iid); rv = RegisterInterface(if_name + sizeof(NS_DOM_INTERFACE_PREFIX) - 1, iid, &found_old); #ifdef DEBUG NS_ASSERTION(!found_old, "Whaaa, interface name already in hash!"); #endif } // Next, look for externally registered DOM interfaces rv = RegisterExternalInterfaces(false); return rv; }
/*static*/ nsresult nsJavaXPTCStub::GetNewOrUsed(JNIEnv* env, jobject aJavaObject, const nsIID& aIID, void** aResult) { nsJavaXPTCStub* stub; jint hash = env->CallStaticIntMethod(systemClass, hashCodeMID, aJavaObject); nsresult rv = gJavaToXPTCStubMap->Find(hash, aIID, &stub); NS_ENSURE_SUCCESS(rv, rv); if (stub) { // stub is already AddRef'd and QI'd *aResult = stub; return NS_OK; } // If there is no corresponding XPCOM object, then that means that the // parameter is a non-generated class (that is, it is not one of our // Java stubs that represent an exising XPCOM object). So we need to // create an XPCOM stub, that can route any method calls to the class. // Get interface info for class nsCOMPtr<nsIInterfaceInfoManager> iim(do_GetService(NS_INTERFACEINFOMANAGER_SERVICE_CONTRACTID, &rv)); NS_ENSURE_SUCCESS(rv, rv); nsCOMPtr<nsIInterfaceInfo> iinfo; rv = iim->GetInfoForIID(&aIID, getter_AddRefs(iinfo)); NS_ENSURE_SUCCESS(rv, rv); // Create XPCOM stub stub = new nsJavaXPTCStub(aJavaObject, iinfo, &rv); if (!stub) return NS_ERROR_OUT_OF_MEMORY; if (NS_FAILED(rv)) { delete stub; return rv; } rv = gJavaToXPTCStubMap->Add(hash, stub); if (NS_FAILED(rv)) { delete stub; return rv; } NS_ADDREF(stub); *aResult = stub; return NS_OK; }
/*static*/PyObject * Py_nsIID::PyTypeMethod_getattr(PyObject *self, char *name) { Py_nsIID *me = (Py_nsIID *)self; if (strcmp(name, "name")==0) { char *iid_repr = nsnull; nsCOMPtr<nsIInterfaceInfoManager> iim(do_GetService( NS_INTERFACEINFOMANAGER_SERVICE_CONTRACTID)); if (iim!=nsnull) iim->GetNameForIID(&me->m_iid, &iid_repr); if (iid_repr==nsnull) iid_repr = me->m_iid.ToString(); PyObject *ret; if (iid_repr != nsnull) { ret = PyString_FromString(iid_repr); nsMemory::Free(iid_repr); } else ret = PyString_FromString("<cant get IID info!>"); return ret; } return PyErr_Format(PyExc_AttributeError, "IID objects have no attribute '%s'", name); }
nsresult nsScriptNameSpaceManager::RegisterExternalInterfaces(bool aAsProto) { nsresult rv; nsCOMPtr<nsICategoryManager> cm = do_GetService(NS_CATEGORYMANAGER_CONTRACTID, &rv); NS_ENSURE_SUCCESS(rv, rv); nsCOMPtr<nsIInterfaceInfoManager> iim(do_GetService(NS_INTERFACEINFOMANAGER_SERVICE_CONTRACTID)); NS_ENSURE_TRUE(iim, NS_ERROR_NOT_AVAILABLE); nsCOMPtr<nsISimpleEnumerator> enumerator; rv = cm->EnumerateCategory(JAVASCRIPT_DOM_INTERFACE, getter_AddRefs(enumerator)); NS_ENSURE_SUCCESS(rv, rv); nsXPIDLCString IID_string; nsCAutoString category_entry; const char* if_name; nsCOMPtr<nsISupports> entry; nsCOMPtr<nsIInterfaceInfo> if_info; bool found_old, dom_prefix; while (NS_SUCCEEDED(enumerator->GetNext(getter_AddRefs(entry)))) { nsCOMPtr<nsISupportsCString> category(do_QueryInterface(entry)); if (!category) { NS_WARNING("Category entry not an nsISupportsCString!"); continue; } rv = category->GetData(category_entry); NS_ENSURE_SUCCESS(rv, rv); rv = cm->GetCategoryEntry(JAVASCRIPT_DOM_INTERFACE, category_entry.get(), getter_Copies(IID_string)); NS_ENSURE_SUCCESS(rv, rv); nsIID primary_IID; if (!primary_IID.Parse(IID_string) || primary_IID.Equals(NS_GET_IID(nsISupports))) { NS_ERROR("Invalid IID registered with the script namespace manager!"); continue; } iim->GetInfoForIID(&primary_IID, getter_AddRefs(if_info)); while (if_info) { const nsIID *iid; if_info->GetIIDShared(&iid); NS_ENSURE_TRUE(iid, NS_ERROR_UNEXPECTED); if (iid->Equals(NS_GET_IID(nsISupports))) { break; } if_info->GetNameShared(&if_name); dom_prefix = (strncmp(if_name, NS_DOM_INTERFACE_PREFIX, sizeof(NS_DOM_INTERFACE_PREFIX) - 1) == 0); const char* name; if (dom_prefix) { if (!aAsProto) { // nsIDOM* interfaces have already been registered. break; } name = if_name + sizeof(NS_DOM_INTERFACE_PREFIX) - 1; } else { name = if_name + sizeof(NS_INTERFACE_PREFIX) - 1; } if (aAsProto) { RegisterClassProto(name, iid, &found_old); } else { RegisterInterface(name, iid, &found_old); } if (found_old) { break; } nsCOMPtr<nsIInterfaceInfo> tmp(if_info); tmp->GetParent(getter_AddRefs(if_info)); } } return NS_OK; }
int main (int argc, char **argv) { int i; nsIID *iid1, *iid2, *iid3; char *name1, *name2, *name3; nsIInterfaceInfo *info2, *info3, *info4, *info5; nsCOMPtr<nsIInterfaceInfoManager> iim (do_GetService(NS_INTERFACEINFOMANAGER_SERVICE_CONTRACTID)); fprintf(stderr, "\ngetting iid for 'nsISupports'\n"); iim->GetIIDForName("nsISupports", &iid1); iim->GetNameForIID(iid1, &name1); fprintf(stderr, "%s iid %s\n", name1, iid1->ToString()); fprintf(stderr, "\ngetting iid for 'nsIInputStream'\n"); iim->GetIIDForName("nsIInputStream", &iid2); iim->GetNameForIID(iid2, &name2); fprintf(stderr, "%s iid %s\n", name2, iid2->ToString()); fprintf(stderr, "iid: %s, name: %s\n", iid1->ToString(), name1); fprintf(stderr, "iid: %s, name: %s\n", iid2->ToString(), name2); fprintf(stderr, "\ngetting info for iid2 from above\n"); iim->GetInfoForIID(iid2, &info2); #ifdef DEBUG // ((nsInterfaceInfo *)info2)->print(stderr); #endif fprintf(stderr, "\ngetting iid for 'nsIInputStream'\n"); iim->GetIIDForName("nsIInputStream", &iid3); iim->GetNameForIID(iid3, &name3); fprintf(stderr, "%s iid %s\n", name3, iid2->ToString()); iim->GetInfoForIID(iid3, &info3); #ifdef DEBUG // ((nsInterfaceInfo *)info3)->print(stderr); #endif fprintf(stderr, "\ngetting info for name 'nsIBidirectionalEnumerator'\n"); iim->GetInfoForName("nsIBidirectionalEnumerator", &info4); #ifdef DEBUG // ((nsInterfaceInfo *)info4)->print(stderr); #endif fprintf(stderr, "\nparams work?\n"); fprintf(stderr, "\ngetting info for name 'nsIServiceManager'\n"); iim->GetInfoForName("nsIComponentManager", &info5); #ifdef DEBUG // ((nsInterfaceInfo *)info5)->print(stderr); #endif // XXX: nsIServiceManager is no more; what do we test with? if (info5 == NULL) { fprintf(stderr, "\nNo nsIComponentManager; cannot continue.\n"); return 1; } uint16 methodcount; info5->GetMethodCount(&methodcount); const nsXPTMethodInfo *mi; for (i = 0; i < methodcount; i++) { info5->GetMethodInfo(i, &mi); fprintf(stderr, "method %d, name %s\n", i, mi->GetName()); } // 4 is getServiceByContractID, which has juicy params. info5->GetMethodInfo(6, &mi); const nsXPTParamInfo& param2 = mi->GetParam(1); // should be IID for the service nsIID *nsISL; info5->GetIIDForParam(6, ¶m2, &nsISL); fprintf(stderr, "iid assoc'd with param 1 of method 6 - createInstanceByContractID - %s\n", nsISL->ToString()); // if we look up the name? char *nsISLname; iim->GetNameForIID(nsISL, &nsISLname); fprintf(stderr, "which is called %s\n", nsISLname); fprintf(stderr, "\nNow check the last param\n"); const nsXPTParamInfo& param3 = mi->GetParam(3); if (param3.GetType().TagPart() != nsXPTType::T_INTERFACE_IS) { fprintf(stderr, "Param 3 is not type interface is\n"); // Not returning an error, because this could legitamately change } // lets see what arg this refers to uint8 argnum; info5->GetInterfaceIsArgNumberForParam(6, ¶m3, &argnum); fprintf(stderr, "param 3 referrs to param %d of method 6 - createInstanceByContractID\n", (uint32_t)argnum); // Get the type of the parameter referred to const nsXPTParamInfo& arg_param = mi->GetParam(argnum); const nsXPTType& arg_type = arg_param.GetType(); // Check to make sure it refers to the proper param if(!arg_type.IsPointer() || arg_type.TagPart() != nsXPTType::T_IID) { fprintf(stderr, "Param 3 of method 6 refers to a non IID parameter\n"); // Not returning an error, because this could legitamately change } return 0; }
/** * 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; }
NS_IMETHODIMP nsJavaXPTCStub::QueryInterface(const nsID &aIID, void **aInstancePtr) { nsresult rv; LOG(("JavaStub::QueryInterface()\n")); *aInstancePtr = nsnull; nsJavaXPTCStub *master = mMaster ? mMaster : this; // This helps us differentiate between the help classes. if (aIID.Equals(NS_GET_IID(nsJavaXPTCStub))) { *aInstancePtr = master; NS_ADDREF(this); return NS_OK; } // always return the master stub for nsISupports if (aIID.Equals(NS_GET_IID(nsISupports))) { *aInstancePtr = master->mXPTCStub; NS_ADDREF(master); return NS_OK; } // All Java objects support weak references if (aIID.Equals(NS_GET_IID(nsISupportsWeakReference))) { *aInstancePtr = static_cast<nsISupportsWeakReference*>(master); NS_ADDREF(master); return NS_OK; } // does any existing stub support the requested IID? nsJavaXPTCStub *stub = master->FindStubSupportingIID(aIID); if (stub) { *aInstancePtr = stub->mXPTCStub; NS_ADDREF(stub); return NS_OK; } JNIEnv* env = GetJNIEnv(); // Query Java object LOG(("\tCalling Java object queryInterface\n")); jobject javaObject = env->CallObjectMethod(mJavaWeakRef, getReferentMID); jmethodID qiMID = 0; jclass clazz = env->GetObjectClass(javaObject); if (clazz) { char* sig = "(Ljava/lang/String;)Lorg/mozilla/interfaces/nsISupports;"; qiMID = env->GetMethodID(clazz, "queryInterface", sig); NS_ASSERTION(qiMID, "Failed to get queryInterface method ID"); } if (qiMID == 0) { env->ExceptionClear(); return NS_NOINTERFACE; } // construct IID string jstring iid_jstr = nsnull; char* iid_str = aIID.ToString(); if (iid_str) { iid_jstr = env->NewStringUTF(iid_str); } if (!iid_str || !iid_jstr) { env->ExceptionClear(); return NS_ERROR_OUT_OF_MEMORY; } PR_Free(iid_str); // call queryInterface method jobject obj = env->CallObjectMethod(javaObject, qiMID, iid_jstr); if (env->ExceptionCheck()) { env->ExceptionClear(); return NS_ERROR_FAILURE; } if (!obj) return NS_NOINTERFACE; // Get interface info for new java object nsCOMPtr<nsIInterfaceInfoManager> iim(do_GetService(NS_INTERFACEINFOMANAGER_SERVICE_CONTRACTID, &rv)); NS_ENSURE_SUCCESS(rv, rv); nsCOMPtr<nsIInterfaceInfo> iinfo; rv = iim->GetInfoForIID(&aIID, getter_AddRefs(iinfo)); if (NS_FAILED(rv)) return rv; stub = new nsJavaXPTCStub(obj, iinfo, &rv); if (!stub) return NS_ERROR_OUT_OF_MEMORY; if (NS_FAILED(rv)) { delete stub; return rv; } // add stub to the master's list of children, so we can preserve // symmetry in future QI calls. the master will delete each child // when it is destroyed. the refcount of each child is bound to // the refcount of the master. this is done to deal with code // like this: // // nsCOMPtr<nsIBar> bar = ...; // nsIFoo *foo; // { // nsCOMPtr<nsIFoo> temp = do_QueryInterface(bar); // foo = temp; // } // foo->DoStuff(); // // while this code is not valid XPCOM (since it is using |foo| // after having called Release on it), such code is unfortunately // very common in the mozilla codebase. the assumption this code // is making is that so long as |bar| is alive, it should be valid // to access |foo| even if the code doesn't own a strong reference // to |foo|! clearly wrong, but we need to support it anyways. stub->mMaster = master; master->mChildren.AppendElement(stub); *aInstancePtr = stub->mXPTCStub; NS_ADDREF(stub); return NS_OK; }
nsresult nsJavaXPTCStub::GetRetvalSig(const nsXPTParamInfo* aParamInfo, const XPTMethodDescriptor* aMethodInfo, PRUint16 aMethodIndex, nsXPTCMiniVariant* aDispatchParams, nsACString &aRetvalSig) { PRUint8 type = aParamInfo->GetType().TagPart(); switch (type) { case nsXPTType::T_I8: aRetvalSig.Append('B'); break; case nsXPTType::T_I16: case nsXPTType::T_U8: aRetvalSig.Append('S'); break; case nsXPTType::T_I32: case nsXPTType::T_U16: aRetvalSig.Append('I'); break; case nsXPTType::T_I64: case nsXPTType::T_U32: aRetvalSig.Append('J'); break; case nsXPTType::T_FLOAT: aRetvalSig.Append('F'); break; case nsXPTType::T_U64: case nsXPTType::T_DOUBLE: aRetvalSig.Append('D'); break; case nsXPTType::T_BOOL: aRetvalSig.Append('Z'); break; case nsXPTType::T_CHAR: case nsXPTType::T_WCHAR: aRetvalSig.Append('C'); break; case nsXPTType::T_CHAR_STR: case nsXPTType::T_WCHAR_STR: case nsXPTType::T_IID: case nsXPTType::T_ASTRING: case nsXPTType::T_DOMSTRING: case nsXPTType::T_UTF8STRING: case nsXPTType::T_CSTRING: aRetvalSig.AppendLiteral("Ljava/lang/String;"); break; case nsXPTType::T_INTERFACE: { nsID iid; nsresult rv = GetIIDForMethodParam(mIInfo, aMethodInfo, *aParamInfo, type, 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; aRetvalSig.AppendLiteral("Lorg/mozilla/interfaces/"); aRetvalSig.AppendASCII(iface_name); aRetvalSig.Append(';'); nsMemory::Free(iface_name); break; } case nsXPTType::T_INTERFACE_IS: aRetvalSig.AppendLiteral("Lorg/mozilla/interfaces/nsISupports;"); break; case nsXPTType::T_VOID: aRetvalSig.Append('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 NS_OK; }
int main (int argc, char **argv) { int i; nsIID *iid1, *iid2, *iid3; char *name1, *name2, *name3; nsIInterfaceInfo *info2, *info3, *info4, *info5; nsCOMPtr<nsIInterfaceInfoManager> iim (do_GetService(NS_INTERFACEINFOMANAGER_SERVICE_CONTRACTID)); fprintf(stderr, "\ngetting iid for 'nsISupports'\n"); iim->GetIIDForName("nsISupports", &iid1); iim->GetNameForIID(iid1, &name1); fprintf(stderr, "%s iid %s\n", name1, iid1->ToString()); fprintf(stderr, "\ngetting iid for 'nsIInputStream'\n"); iim->GetIIDForName("nsIInputStream", &iid2); iim->GetNameForIID(iid2, &name2); fprintf(stderr, "%s iid %s\n", name2, iid2->ToString()); fprintf(stderr, "iid: %s, name: %s\n", iid1->ToString(), name1); fprintf(stderr, "iid: %s, name: %s\n", iid2->ToString(), name2); fprintf(stderr, "\ngetting info for iid2 from above\n"); iim->GetInfoForIID(iid2, &info2); #ifdef DEBUG // ((nsInterfaceInfo *)info2)->print(stderr); #endif fprintf(stderr, "\ngetting iid for 'nsIInputStream'\n"); iim->GetIIDForName("nsIInputStream", &iid3); iim->GetNameForIID(iid3, &name3); fprintf(stderr, "%s iid %s\n", name3, iid2->ToString()); iim->GetInfoForIID(iid3, &info3); #ifdef DEBUG // ((nsInterfaceInfo *)info3)->print(stderr); #endif fprintf(stderr, "\ngetting info for name 'nsIBidirectionalEnumerator'\n"); iim->GetInfoForName("nsIBidirectionalEnumerator", &info4); #ifdef DEBUG // ((nsInterfaceInfo *)info4)->print(stderr); #endif fprintf(stderr, "\nparams work?\n"); fprintf(stderr, "\ngetting info for name 'nsIServiceManager'\n"); iim->GetInfoForName("nsIServiceManager", &info5); #ifdef DEBUG // ((nsInterfaceInfo *)info5)->print(stderr); #endif // XXX: nsIServiceManager is no more; what do we test with? if (info5 == NULL) { fprintf(stderr, "\nNo nsIServiceManager; cannot continue.\n"); return 1; } uint16 methodcount; info5->GetMethodCount(&methodcount); const nsXPTMethodInfo *mi; for (i = 0; i < methodcount; i++) { info5->GetMethodInfo(i, &mi); fprintf(stderr, "method %d, name %s\n", i, mi->GetName()); } // 7 is GetServiceWithListener, which has juicy params. info5->GetMethodInfo(7, &mi); // uint8 paramcount = mi->GetParamCount(); nsXPTParamInfo param2 = mi->GetParam(2); // should be IID for nsIShutdownListener nsIID *nsISL; info5->GetIIDForParam(7, ¶m2, &nsISL); // const nsIID *nsISL = param2.GetInterfaceIID(info5); fprintf(stderr, "iid assoc'd with param 2 of method 7 of GetServiceWithListener - %s\n", nsISL->ToString()); // if we look up the name? char *nsISLname; iim->GetNameForIID(nsISL, &nsISLname); fprintf(stderr, "which is called %s\n", nsISLname); fprintf(stderr, "\nhow about one defined in a different typelib\n"); nsXPTParamInfo param3 = mi->GetParam(3); // should be IID for nsIShutdownListener nsIID *nsISS; info5->GetIIDForParam(7, ¶m3, &nsISS); // const nsIID *nsISS = param3.GetInterfaceIID(info5); fprintf(stderr, "iid assoc'd with param 3 of method 7 of GetServiceWithListener - %s\n", nsISS->ToString()); // if we look up the name? char *nsISSname; iim->GetNameForIID(nsISS, &nsISSname); fprintf(stderr, "which is called %s\n", nsISSname); return 0; }