diff --git a/mozilla/xpcom/proxy/public/nsProxyEvent.h b/mozilla/xpcom/proxy/public/nsProxyEvent.h index 100b30b13da..f0180aa5584 100644 --- a/mozilla/xpcom/proxy/public/nsProxyEvent.h +++ b/mozilla/xpcom/proxy/public/nsProxyEvent.h @@ -72,18 +72,21 @@ class nsProxyObject : public nsISupports public: NS_DECL_ISUPPORTS - NS_DEFINE_STATIC_IID_ACCESSOR(nsCOMTypeInfo::GetIID()) + NS_DEFINE_STATIC_IID_ACCESSOR(nsCOMTypeInfo::GetIID()) + nsProxyObject(); nsProxyObject(nsIEventQueue *destQueue, PRInt32 proxyType, nsISupports *realObject); nsProxyObject(nsIEventQueue *destQueue, PRInt32 proxyType, const nsCID &aClass, nsISupports *aDelegate, const nsIID &aIID); virtual ~nsProxyObject(); - nsresult Post(PRUint32 methodIndex, nsXPTMethodInfo *info, - nsXPTCMiniVariant *params, nsIInterfaceInfo *interfaceInfo); + nsresult Post( PRUint32 methodIndex, + nsXPTMethodInfo * info, + nsXPTCMiniVariant * params, + nsIInterfaceInfo * interfaceInfo); - nsresult NestedEventLoop(nsProxyObjectCallInfo *proxyInfo); - nsISupports* GetRealObject() const { return mRealObject; } + nsresult PostAndWait(nsProxyObjectCallInfo *proxyInfo); + nsISupports* GetRealObject(); nsIEventQueue* GetQueue(); PRInt32 GetProxyType() const { return mProxyType; } @@ -91,6 +94,20 @@ public: private: + + PRInt32 mProxyType; + + nsCOMPtr mDestQueue; /* destination queue */ + + nsCOMPtr mRealObject; /* the non-proxy object that this event is referring to. + This is a strong ref. */ + + + nsresult convertMiniVariantToVariant(nsXPTMethodInfo * methodInfo, + nsXPTCMiniVariant * params, + nsXPTCVariant **fullParam, + uint8 *paramCount); + #ifdef AUTOPROXIFICATION typedef enum { @@ -104,19 +121,7 @@ private: nsresult AutoProxyParameterList(PRUint32 methodIndex, nsXPTMethodInfo *methodInfo, nsXPTCMiniVariant * params, nsIInterfaceInfo *interfaceInfo, AutoProxyConvertTypes convertType); #endif - - nsIEventQueue *mDestQueue; /* destination queue */ - nsISupports *mRealObject; /* the non-proxy object that this event is referring to. - This is a strong ref. */ - - PRBool mRealObjectOwned; - PRInt32 mProxyType; - - nsresult convertMiniVariantToVariant(nsXPTMethodInfo *methodInfo, nsXPTCMiniVariant * params, - nsXPTCVariant **fullParam, uint8 *paramCount); - - - }; +}; class NS_EXPORT nsProxyObjectCallInfo @@ -124,6 +129,7 @@ class NS_EXPORT nsProxyObjectCallInfo public: nsProxyObjectCallInfo(nsProxyObject* owner, + nsXPTMethodInfo *methodInfo, PRUint32 methodIndex, nsXPTCVariant* parameterList, PRUint32 parameterCount, @@ -137,23 +143,35 @@ public: PLEvent* GetPLEvent() const { return mEvent; } nsresult GetResult() const { return mResult; } nsProxyObject* GetProxyObject() const { return mOwner; } + PRBool GetCompleted(); + void SetCompleted(); + void PostCompleted(); void SetResult(nsresult rv) {mResult = rv; } - void SetCompleted(); + + nsIEventQueue* GetCallersQueue(); + void SetCallersQueue(nsIEventQueue* queue); private: nsresult mResult; /* this is the return result of the called function */ + nsXPTMethodInfo *mMethodInfo; PRUint32 mMethodIndex; /* which method to be called? */ nsXPTCVariant *mParameterList; /* marshalled in parameter buffer */ PRUint32 mParameterCount; /* number of params */ PLEvent *mEvent; /* the current plevent */ PRInt32 mCompleted; /* is true when the method has been called. */ - - nsCOMPtr mOwner; /* this is the strong referenced nsProxyObject */ - + + nsIEventQueue* mCallersEventQ; /* this is the eventQ that we must post a message back to + when we are done invoking the method (only PROXY_SYNC). + this does not need to be a comptr because it will be + released by the created in PostAndWait() + */ + nsCOMPtr mOwner; /* this is the strong referenced nsProxyObject */ + + void RefCountInInterfacePointers(PRBool addRef); }; diff --git a/mozilla/xpcom/proxy/src/nsProxyEvent.cpp b/mozilla/xpcom/proxy/src/nsProxyEvent.cpp index 6d4a732ee60..69e37dd312c 100644 --- a/mozilla/xpcom/proxy/src/nsProxyEvent.cpp +++ b/mozilla/xpcom/proxy/src/nsProxyEvent.cpp @@ -22,7 +22,7 @@ #include "nsProxyObjectManager.h" #include "pratom.h" -#include "prmem.h" // for PR_NEW +#include "prmem.h" #include "xptcall.h" #include "nsRepository.h" @@ -37,8 +37,11 @@ static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID); static void* EventHandler(PLEvent *self); static void DestroyHandler(PLEvent *self); +static void* CompletedEventHandler(PLEvent *self); +static void CompletedDestroyHandler(PLEvent *self) ; -nsProxyObjectCallInfo::nsProxyObjectCallInfo(nsProxyObject* owner, +nsProxyObjectCallInfo::nsProxyObjectCallInfo( nsProxyObject* owner, + nsXPTMethodInfo *methodInfo, PRUint32 methodIndex, nsXPTCVariant* parameterList, PRUint32 parameterCount, @@ -50,33 +53,102 @@ nsProxyObjectCallInfo::nsProxyObjectCallInfo(nsProxyObject* owner, mParameterList = parameterList; mParameterCount = parameterCount; mEvent = event; + mMethodInfo = methodInfo; + mCallersEventQ = 0; + + RefCountInInterfacePointers(PR_TRUE); } nsProxyObjectCallInfo::~nsProxyObjectCallInfo() { + RefCountInInterfacePointers(PR_FALSE); + + // I am worried about order of destruction here. + // do not remove assignments. + + mOwner = 0; + mCallersEventQ = 0; + PR_FREEIF(mEvent); if (mParameterList) free( (void*) mParameterList); } -PRBool +void +nsProxyObjectCallInfo::RefCountInInterfacePointers(PRBool addRef) +{ + for (PRUint32 i = 0; i < mParameterCount; i++) + { + nsXPTParamInfo paramInfo = mMethodInfo->GetParam(i); + + if (paramInfo.GetType().IsInterfacePointer() ) + { + nsISupports* anInterface = nsnull; + + if (paramInfo.IsIn()) + { + anInterface = ((nsISupports*)mParameterList[i].val.p); + + if (anInterface) + { + if(addRef) + anInterface->AddRef(); + else + anInterface->Release(); + + } + } + } + } +} + +PRBool nsProxyObjectCallInfo::GetCompleted() { return (PRBool)mCompleted; } -void + +void nsProxyObjectCallInfo::SetCompleted() { PR_AtomicSet(&mCompleted, 1); } +void +nsProxyObjectCallInfo::PostCompleted() +{ + if (mCallersEventQ) + { + PLEvent *event = PR_NEW(PLEvent); + + PL_InitEvent(event, + this, + CompletedEventHandler, + CompletedDestroyHandler); + + mCallersEventQ->PostSynchronousEvent(event, nsnull); + PR_FREEIF(event); + } + else + { + // caller does not have an eventQ? This is an error! + SetCompleted(); + } +} + +nsIEventQueue* +nsProxyObjectCallInfo::GetCallersQueue() +{ + return mCallersEventQ; +} +void +nsProxyObjectCallInfo::SetCallersQueue(nsIEventQueue* queue) +{ + mCallersEventQ = queue; +} -#ifdef debug_DOUGT -static PRUint32 totalProxyObjects = 0; -static PRUint32 outstandingProxyObjects = 0; -#endif NS_IMPL_ISUPPORTS0(nsProxyObject) @@ -86,71 +158,66 @@ nsProxyObject::nsProxyObject() } nsProxyObject::nsProxyObject(nsIEventQueue *destQueue, PRInt32 proxyType, nsISupports *realObject) { -#ifdef debug_DOUGT -totalProxyObjects++; -outstandingProxyObjects++; -#endif - NS_INIT_REFCNT(); - NS_ADDREF_THIS(); mRealObject = realObject; + mDestQueue = do_QueryInterface(destQueue); mProxyType = proxyType; - mDestQueue = destQueue; } nsProxyObject::nsProxyObject(nsIEventQueue *destQueue, PRInt32 proxyType, const nsCID &aClass, nsISupports *aDelegate, const nsIID &aIID) { -#ifdef debug_DOUGT -totalProxyObjects++; -outstandingProxyObjects++; -#endif - NS_INIT_REFCNT(); - NS_ADDREF_THIS(); nsComponentManager::CreateInstance(aClass, aDelegate, aIID, - (void**) &mRealObject); + getter_AddRefs(mRealObject)); + mDestQueue = do_QueryInterface(destQueue); mProxyType = proxyType; - mDestQueue = destQueue; } nsProxyObject::~nsProxyObject() { -#ifdef debug_DOUGT -outstandingProxyObjects--; -printf("[proxyobjects] %d total used in system, %d outstading\n", totalProxyObjects, outstandingProxyObjects); -#endif + // I am worried about order of destruction here. + // do not remove assignments. + + mRealObject = 0; + mDestQueue = 0; } +// GetRealObject +// This function must return the real pointer to the object to be proxied. +// It must not be a comptr or be addreffed. +nsISupports* +nsProxyObject::GetRealObject() +{ + return mRealObject.get(); +} nsIEventQueue* nsProxyObject::GetQueue() { - if (mDestQueue) - NS_ADDREF(mDestQueue); return mDestQueue; } - + nsresult -nsProxyObject::NestedEventLoop(nsProxyObjectCallInfo *proxyInfo) +nsProxyObject::PostAndWait(nsProxyObjectCallInfo *proxyInfo) { if (proxyInfo == nsnull) return NS_ERROR_NULL_POINTER; - PLEvent* event = proxyInfo->GetPLEvent(); PRBool eventLoopCreated = PR_FALSE; nsresult rv; - +//--------------------- +//This block of code should be a function of the EventQueueServices NS_WITH_SERVICE(nsIEventQueueService, eventQService, kEventQueueServiceCID, &rv); if (NS_FAILED(rv)) return rv; - nsIEventQueue *eventQ; - rv = eventQService->GetThreadEventQueue(PR_CurrentThread(), &eventQ); + nsCOMPtr eventQ; + rv = eventQService->GetThreadEventQueue(PR_CurrentThread(), getter_AddRefs(eventQ)); if (NS_FAILED(rv)) { rv = eventQService->CreateThreadEventQueue(); @@ -158,36 +225,50 @@ nsProxyObject::NestedEventLoop(nsProxyObjectCallInfo *proxyInfo) if (NS_FAILED(rv)) return rv; - rv = eventQService->GetThreadEventQueue(PR_CurrentThread(), &eventQ); + rv = eventQService->GetThreadEventQueue(PR_CurrentThread(), getter_AddRefs(eventQ)); } else { - NS_RELEASE(eventQ); - rv = eventQService->PushThreadEventQueue(&eventQ); + eventQ = 0; + rv = eventQService->PushThreadEventQueue(getter_AddRefs(eventQ)); } if (NS_FAILED(rv)) return rv; +//--------------------- + + proxyInfo->SetCallersQueue(eventQ); + + PLEvent* event = proxyInfo->GetPLEvent(); + if (!event) + return NS_ERROR_NULL_POINTER; + + mDestQueue->PostEvent(event); while (! proxyInfo->GetCompleted()) { + //rv = eventQ->WaitForEvent(); + //if (NS_FAILED(rv)) break; + rv = eventQ->GetEvent(&event); if (NS_FAILED(rv)) break; + eventQ->HandleEvent(event); - - PR_Sleep( PR_MillisecondsToInterval(5) ); + + PR_Sleep(PR_MillisecondsToInterval(100)); } - - if (eventLoopCreated) { - NS_RELEASE(eventQ); eventQService->DestroyThreadEventQueue(); + eventQ = 0; } else { - eventQService->PopThreadEventQueue(eventQ); + nsIEventQueue *dumbAddref = eventQ; + NS_ADDREF(dumbAddref); // PopThreadEventQueue released the nsCOMPtr, + // then we crash while leaving this functions. + eventQService->PopThreadEventQueue(dumbAddref); // this is totally evil } return rv; @@ -217,10 +298,7 @@ nsProxyObject::Post( PRUint32 methodIndex, nsXPTMethodInfo *methodInfo, nsXPTCMi { nsresult rv = NS_OK; - if (mDestQueue == nsnull) - return NS_ERROR_OUT_OF_MEMORY; - - if (mRealObject == nsnull) + if (! mDestQueue || ! mRealObject) return NS_ERROR_OUT_OF_MEMORY; if (methodInfo->IsNotXPCOM()) @@ -231,28 +309,38 @@ nsProxyObject::Post( PRUint32 methodIndex, nsXPTMethodInfo *methodInfo, nsXPTCMi if (event == nsnull) return NS_ERROR_OUT_OF_MEMORY; - /////////////////////////////////////////////////////////////////////// - // Auto-proxification - /////////////////////////////////////////////////////////////////////// -#ifdef AUTOPROXIFICATION +#ifdef AUTOPROXIFICATION + // this should move into the nsProxyObjectCallInfo. rv = AutoProxyParameterList(methodIndex, methodInfo, params, interfaceInfo, convertInParameters); -#endif - /////////////////////////////////////////////////////////////////////// if (NS_FAILED(rv)) + { + delete event; return rv; - + } +#endif + nsXPTCVariant *fullParam; uint8 paramCount; rv = convertMiniVariantToVariant(methodInfo, params, &fullParam, ¶mCount); if (NS_FAILED(rv)) + { + delete event; return rv; + } - nsProxyObjectCallInfo *proxyInfo = new nsProxyObjectCallInfo(this, methodIndex, fullParam, paramCount, event); + nsProxyObjectCallInfo *proxyInfo = new nsProxyObjectCallInfo(this, + methodInfo, + methodIndex, + fullParam, // will be deleted by ~() + paramCount, + event); // will be deleted by ~() if (proxyInfo == nsnull) { + delete event; + free(fullParam); // allocated with malloc return NS_ERROR_OUT_OF_MEMORY; } @@ -269,12 +357,13 @@ nsProxyObject::Post( PRUint32 methodIndex, nsXPTMethodInfo *methodInfo, nsXPTCMi if (callDirectly) { EventHandler(event); + // there is no need to call the DestroyHandler() because + // there is no need to wake up the nested event loop. } else { - mDestQueue->PostEvent(event); - rv = NestedEventLoop(proxyInfo); - //mDestQueue->PostSynchronousEvent(event, nsnull); + rv = PostAndWait(proxyInfo); + if (NS_FAILED(rv)) return rv; } @@ -282,14 +371,9 @@ nsProxyObject::Post( PRUint32 methodIndex, nsXPTMethodInfo *methodInfo, nsXPTCMi rv = proxyInfo->GetResult(); delete proxyInfo; - /////////////////////////////////////////////////////////////////////// - // Auto-proxification - /////////////////////////////////////////////////////////////////////// #ifdef AUTOPROXIFICATION rv = AutoProxyParameterList(methodIndex, methodInfo, params, interfaceInfo, convertOutParameters); #endif - /////////////////////////////////////////////////////////////////////// - return rv; } @@ -298,16 +382,70 @@ nsProxyObject::Post( PRUint32 methodIndex, nsXPTMethodInfo *methodInfo, nsXPTCMi mDestQueue->PostEvent(event); return NS_OK; } - return NS_ERROR_UNEXPECTED; - } + + + +void DestroyHandler(PLEvent *self) +{ + nsProxyObjectCallInfo* owner = (nsProxyObjectCallInfo*)PL_GetEventOwner(self); + nsProxyObject* proxyObject = owner->GetProxyObject(); + + if (proxyObject == nsnull) + return; + + if (proxyObject->GetProxyType() & PROXY_ASYNC) + { + delete owner; + } + else + { + owner->PostCompleted(); + } + +} + +void* EventHandler(PLEvent *self) +{ + nsProxyObjectCallInfo *info = (nsProxyObjectCallInfo*)PL_GetEventOwner(self); + NS_ASSERTION(info, "No nsProxyObjectCallInfo!"); + + nsProxyObject *proxyObject = info->GetProxyObject(); + + if (proxyObject) + { + // invoke the magic of xptc... + nsresult rv = XPTC_InvokeByIndex( proxyObject->GetRealObject(), + info->GetMethodIndex(), + info->GetParameterCount(), + info->GetParameterList()); + info->SetResult(rv); + } + else + { + info->SetResult(NS_ERROR_OUT_OF_MEMORY); + } + return NULL; +} + +void CompletedDestroyHandler(PLEvent *self) +{ +} + +void* CompletedEventHandler(PLEvent *self) +{ + nsProxyObjectCallInfo* owner = (nsProxyObjectCallInfo*)PL_GetEventOwner(self); + owner->SetCompleted(); + return nsnull; +} + #ifdef AUTOPROXIFICATION // ssc@netscape.com wishes he could get rid of this instance of |NS_DEFINE_IID|, but |ProxyEventClassIdentity| is not visible from here static NS_DEFINE_IID(kProxyObject_Identity_Class_IID, NS_PROXYEVENT_IDENTITY_CLASS_IID); nsresult -nsProxyObject::AutoProxyParameterList(PRUint32 methodIndex, nsXPTMethodInfo *methodInfo, nsXPTCMiniVariant * params, +AutoProxyParameterList(PRUint32 methodIndex, nsXPTMethodInfo *methodInfo, nsXPTCMiniVariant * params, nsIInterfaceInfo *interfaceInfo, AutoProxyConvertTypes convertType) { nsresult rv = NS_OK; @@ -522,45 +660,3 @@ nsProxyObject::AutoProxyParameterList(PRUint32 methodIndex, nsXPTMethodInfo *met return rv; } #endif - - -void DestroyHandler(PLEvent *self) -{ - nsProxyObjectCallInfo* owner = (nsProxyObjectCallInfo*)PL_GetEventOwner(self); - nsProxyObject* proxyObject = owner->GetProxyObject(); - - if (proxyObject->GetProxyType() & PROXY_ASYNC) - { - delete owner; - } - else - { - owner->SetCompleted(); - } -} - -void* EventHandler(PLEvent *self) -{ - nsProxyObjectCallInfo *info = (nsProxyObjectCallInfo*)PL_GetEventOwner(self); - - if (info != nsnull) - { - nsProxyObject *proxyObject = info->GetProxyObject(); - - if (proxyObject) - { - // invoke the magic of xptc... - nsresult rv = XPTC_InvokeByIndex( proxyObject->GetRealObject(), - info->GetMethodIndex(), - info->GetParameterCount(), - info->GetParameterList()); - info->SetResult(rv); - } - else - { - info->SetResult(NS_ERROR_OUT_OF_MEMORY); - } - } - return NULL; -} - diff --git a/mozilla/xpcom/proxy/src/nsProxyEventClass.cpp b/mozilla/xpcom/proxy/src/nsProxyEventClass.cpp index ab10f5524f7..f0b2ec00beb 100644 --- a/mozilla/xpcom/proxy/src/nsProxyEventClass.cpp +++ b/mozilla/xpcom/proxy/src/nsProxyEventClass.cpp @@ -41,9 +41,6 @@ static uint32 zero_methods_descriptor; ////////////////////////////////////////////////////////////////////////////////////////////////// // nsProxyEventClass ////////////////////////////////////////////////////////////////////////////////////////////////// - -static NS_DEFINE_IID(kProxyEventClassIID, NS_PROXYEVENT_CLASS_IID); - NS_IMPL_ISUPPORTS(nsProxyEventClass, kProxyEventClassIID) // static @@ -60,7 +57,7 @@ nsProxyEventClass::GetNewOrUsedClass(REFNSIID aIID) return nsnull; } - nsProxyEventClass* clazz = NULL; + nsProxyEventClass* clazz = nsnull; nsIDKey key(aIID); if(iidToClassMap->Exists(&key)) @@ -70,22 +67,20 @@ nsProxyEventClass::GetNewOrUsedClass(REFNSIID aIID) } else { - nsIInterfaceInfoManager* iimgr; - if(NULL != (iimgr = XPTI_GetInterfaceInfoManager())) + nsCOMPtr iimgr = getter_AddRefs(XPTI_GetInterfaceInfoManager()); + if(iimgr) { - nsIInterfaceInfo* info; - if(NS_SUCCEEDED(iimgr->GetInfoForIID(&aIID, &info))) + nsCOMPtr info; + if(NS_SUCCEEDED(iimgr->GetInfoForIID(&aIID, getter_AddRefs(info)))) { /* Check to see if isISupportsDescendent */ - nsIInterfaceInfo* oldest = info; - nsIInterfaceInfo* parent; + nsCOMPtr oldest = info; + nsCOMPtr parent; - NS_ADDREF(oldest); - while(NS_SUCCEEDED(oldest->GetParent(&parent))) + while(NS_SUCCEEDED(oldest->GetParent(getter_AddRefs(parent)))) { - NS_RELEASE(oldest); oldest = parent; } @@ -96,8 +91,7 @@ nsProxyEventClass::GetNewOrUsedClass(REFNSIID aIID) isISupportsDescendent = iid->Equals(nsCOMTypeInfo::GetIID()); nsAllocator::Free(iid); } - NS_RELEASE(oldest); - + NS_VERIFY(isISupportsDescendent,"!isISupportsDescendent"); if (isISupportsDescendent) @@ -106,24 +100,24 @@ nsProxyEventClass::GetNewOrUsedClass(REFNSIID aIID) if(!clazz->mDescriptors) NS_RELEASE(clazz); // sets clazz to NULL } - NS_RELEASE(info); } - NS_RELEASE(iimgr); } } return clazz; } +nsProxyEventClass::nsProxyEventClass() +{ +} nsProxyEventClass::nsProxyEventClass(REFNSIID aIID, nsIInterfaceInfo* aInfo) -: mInfo(aInfo), - mIID(aIID), +: mIID(aIID), mDescriptors(NULL) { - NS_ADDREF(mInfo); - NS_INIT_REFCNT(); NS_ADDREF_THIS(); + + mInfo = aInfo; /* add use to the used classes */ nsIDKey key(aIID); @@ -168,8 +162,6 @@ nsProxyEventClass::~nsProxyEventClass() { iidToClassMap->Remove(&key); } - - NS_RELEASE(mInfo); } nsresult @@ -214,10 +206,9 @@ nsProxyEventClass::CallQueryInterfaceOnProxy(nsProxyEventObject* self, REFNSIID // This 'ProxyEventClassIdentity' class and singleton allow us to figure out if // any given nsISupports* is implemented by a nsProxy object. This is done // using a QueryInterface call on the interface pointer with our ID. If -// that call returns NS_OK and the pointer is to our singleton, then the -// interface must be implemented by a nsProxy object. NOTE: the -// 'ProxyEventClassIdentity' object is not a real XPCOM object and should not be -// used for anything else +// that call returns NS_OK and the pointer is to a nsProxyEventObject. It must +// be released when done. + // NS_PROXYEVENT_IDENTITY_CLASS_IID defined in nsProxyEventPrivate.h class ProxyEventClassIdentity { @@ -239,24 +230,47 @@ nsProxyEventClass::DelegatedQueryInterface(nsProxyEventObject* self, REFNSIID aIID, void** aInstancePtr) { - if(NULL == aInstancePtr) - { - NS_PRECONDITION(0, "null pointer"); - return NS_ERROR_NULL_POINTER; - } - - if(aIID.Equals(self->GetIID())) - { - *aInstancePtr = (void*) self; - NS_ADDREF(self); - return NS_OK; - } if(aIID.Equals(ProxyEventClassIdentity::GetIID())) { - *aInstancePtr = ProxyEventClassIdentity::GetSingleton(); + *aInstancePtr = (void**)self; //todo this should be a static cast + NS_ADDREF(self); return NS_OK; } - + + nsProxyEventObject* sibling; + + // This includes checking for nsISupports and the iid of self. + // And it also checks for other wrappers that have been constructed + // for this object. + if(nsnull != (sibling = self->Find(aIID))) + { + NS_ADDREF(sibling); + *aInstancePtr = (void*) sibling; + return NS_OK; + } + + // check if asking for an interface that we inherit from + nsCOMPtr current = GetInterfaceInfo(); + nsCOMPtr parent; + + while(NS_SUCCEEDED(current->GetParent(getter_AddRefs(parent))) && parent) + { + current = parent; + + nsIID* iid; + if(NS_SUCCEEDED(current->GetIID(&iid)) && iid) + { + PRBool found = aIID.Equals(*iid); + nsAllocator::Free(iid); + if(found) + { + *aInstancePtr = (void*) self; + NS_ADDREF(self); + return NS_OK; + } + } + } + return CallQueryInterfaceOnProxy(self, aIID, (nsProxyEventObject**)aInstancePtr); } diff --git a/mozilla/xpcom/proxy/src/nsProxyEventObject.cpp b/mozilla/xpcom/proxy/src/nsProxyEventObject.cpp index 65356ace859..81441e8b02a 100644 --- a/mozilla/xpcom/proxy/src/nsProxyEventObject.cpp +++ b/mozilla/xpcom/proxy/src/nsProxyEventObject.cpp @@ -25,6 +25,76 @@ #include "nsIInterfaceInfoManager.h" #include "xptcall.h" +static NS_DEFINE_IID(kProxyObject_Identity_Class_IID, NS_PROXYEVENT_IDENTITY_CLASS_IID); + + +#ifdef DEBUG_dougt +static PRMonitor* mon = nsnull; +static PRUint32 totalProxyObjects = 0; +static PRUint32 outstandingProxyObjects = 0; + +void +nsProxyEventObject::DebugDump(const char * message, PRUint32 hashKey) +{ + + if (mon == nsnull) + { + mon = PR_NewMonitor(); + } + + PR_EnterMonitor(mon); + + if (message) + { + printf("\n-=-=-=-=-=-=-=-=-=-=-=-=-\n"); + printf("%s\n", message); + + if(strcmp(message, "Create") == 0) + { + totalProxyObjects++; + outstandingProxyObjects++; + } + else if(strcmp(message, "Delete") == 0) + { + outstandingProxyObjects--; + } + } + printf("nsProxyEventObject @ %x with mRefCnt = %d\n", this, mRefCnt); + + PRBool isRoot = mRoot == nsnull; + printf("%s wrapper around @ %x\n", isRoot ? "ROOT":"non-root\n", GetRealObject()); + + if (mHashKey.HashValue()!=0) + printf("Hashkey: %d\n", mHashKey.HashValue()); + + char* name; + GetClass()->GetInterfaceInfo()->GetName(&name); + printf("interface name is %s\n", name); + if(name) + nsAllocator::Free(name); + char * iid = GetClass()->GetProxiedIID().ToString(); + printf("IID number is %s\n", iid); + delete iid; + printf("nsProxyEventClass @ %x\n", mClass); + + if(mNext) + { + if(isRoot) + { + printf("Additional wrappers for this object...\n"); + } + mNext->DebugDump(nsnull, 0); + } + + printf("[proxyobjects] %d total used in system, %d outstading\n", totalProxyObjects, outstandingProxyObjects); + + if (message) + printf("-=-=-=-=-=-=-=-=-=-=-=-=-\n"); + + PR_ExitMonitor(mon); +} +#endif + ////////////////////////////////////////////////////////////////////////////////////////////////// @@ -32,89 +102,101 @@ // nsProxyEventObject // ////////////////////////////////////////////////////////////////////////////////////////////////// - - - nsProxyEventObject* nsProxyEventObject::GetNewOrUsedProxy(nsIEventQueue *destQueue, PRInt32 proxyType, nsISupports *aObj, REFNSIID aIID) { - nsProxyEventObject* proxy = NULL; - nsProxyEventObject* root = NULL; + nsCOMPtr proxy = 0; + nsCOMPtr root = 0; + nsProxyEventObject* peo; - nsProxyEventClass* clazz = nsProxyEventClass::GetNewOrUsedClass(aIID); - if(!clazz) - return NULL; - - nsISupports* rootObject; - // always find the native root - if(NS_FAILED(aObj->QueryInterface(nsCOMTypeInfo::GetIID(), (void**)&rootObject))) - return NULL; - - - /* find in our hash table */ + // Get a class for this IID. + nsCOMPtr clazz = getter_AddRefs( nsProxyEventClass::GetNewOrUsedClass(aIID) ); + if(!clazz) return nsnull; - nsProxyObjectManager *manager = nsProxyObjectManager::GetInstance(); - nsHashtable *realToProxyMap = manager->GetRealObjectToProxyObjectMap(); - - if (realToProxyMap == nsnull) + // make sure that the object pass in is not a proxy. + nsCOMPtr aIdentificationObject; + if (NS_SUCCEEDED(aObj->QueryInterface(kProxyObject_Identity_Class_IID, getter_AddRefs(aIdentificationObject)))) { - if(clazz) - NS_RELEASE(clazz); - return nsnull; + // someone is asking us to create a proxy for a proxy. Lets get + // the real object and build aproxy for that! + aObj = aIdentificationObject->GetRealObject(); + aIdentificationObject = 0; + if (aObj == nsnull) return nsnull; } - nsVoidKey rootkey(rootObject); + // always find the native root if the |real| object. + nsCOMPtr rootObject; + if(NS_FAILED(aObj->QueryInterface(nsCOMTypeInfo::GetIID(), getter_AddRefs(rootObject)))) + return nsnull; + + // this will be our key in the hash table. + nsVoidKey rootkey( (void*) GetProxyHashKey(rootObject.get(), destQueue, proxyType) ); + + /* get our hash table */ + nsProxyObjectManager *manager = nsProxyObjectManager::GetInstance(); + if (manager == nsnull) return nsnull; + + nsHashtable *realToProxyMap = manager->GetRealObjectToProxyObjectMap(); + if (realToProxyMap == nsnull) return nsnull; + + // we need to do make sure that we addref the passed in object as well as ensure + // that it is of the requested IID; + nsCOMPtr requestedInterface; + if(NS_FAILED(aObj->QueryInterface(aIID, getter_AddRefs(requestedInterface)))) + return nsnull; + + /* find in our hash table */ if(realToProxyMap->Exists(&rootkey)) { - root = (nsProxyEventObject*) realToProxyMap->Get(&rootkey); + root = (nsProxyEventObject*) realToProxyMap->Get(&rootkey); proxy = root->Find(aIID); - + if(proxy) - { - NS_ADDREF(proxy); - goto return_wrapper; - } + goto return_proxy; } else { // build the root proxy - if (aObj == rootObject) + if (aObj == rootObject.get()) { // the root will do double duty as the interface wrapper - proxy = root = new nsProxyEventObject(destQueue, proxyType, aObj, clazz, nsnull); - if(root) - { - nsVoidKey aKey(root); - realToProxyMap->Put(&aKey, root); - - NS_ADDREF(proxy); // since we are double duty, we need to make sure that our refCnt - // reflects this. - } - goto return_wrapper; + peo = new nsProxyEventObject(destQueue, + proxyType, + requestedInterface, + clazz, + nsnull, + rootkey.HashValue()); + + proxy = do_QueryInterface(peo); + + if(proxy) + realToProxyMap->Put(&rootkey, peo); + + goto return_proxy; } else { // just a root proxy - nsProxyEventClass* rootClazz = nsProxyEventClass::GetNewOrUsedClass(nsCOMTypeInfo::GetIID()); - if(!rootClazz) - { - goto return_wrapper; - } - - root = new nsProxyEventObject(destQueue, proxyType, rootObject, rootClazz, nsnull); - NS_RELEASE(rootClazz); - - if(!root) - { - goto return_wrapper; - } + nsCOMPtr rootClazz = getter_AddRefs ( nsProxyEventClass::GetNewOrUsedClass( + nsCOMTypeInfo::GetIID()) ); - nsVoidKey aKey(root); - realToProxyMap->Put(&aKey, root); + peo = new nsProxyEventObject(destQueue, + proxyType, + rootObject, + rootClazz, + nsnull, + rootkey.HashValue()); + + if(!peo || !rootClazz) + return nsnull; + + root = do_QueryInterface(peo); + + realToProxyMap->Put(&rootkey, peo); } } // at this point we have a root and may need to build the specific proxy @@ -123,90 +205,94 @@ nsProxyEventObject::GetNewOrUsedProxy(nsIEventQueue *destQueue, if(!proxy) { - proxy = new nsProxyEventObject(destQueue, proxyType, aObj, clazz, root); + peo = new nsProxyEventObject(destQueue, + proxyType, + requestedInterface, + clazz, + root, + 0); + + proxy = do_QueryInterface(peo); + if(!proxy) - { - goto return_wrapper; - } + return nsnull; } + proxy->mNext = root->mNext; root->mNext = proxy; -return_wrapper: +return_proxy: - if(clazz) - NS_RELEASE(clazz); - - - // Since we do not want to extra references, we will release the rootObject. - // - // There are one or more references to aObj which is passed in. When we create - // a new proxy object via nsProxyEventObject(), that will addRef the aObj. Because - // we QI addref to insure that we have a nsISupports ptr, its refcount goes up by one. - // here we will decrement that. - // - if (rootObject) - NS_RELEASE(rootObject); - return proxy; + if(proxy) + { + peo = proxy; + NS_ADDREF(peo); + return peo; + } + + return nsnull; +} +nsProxyEventObject::nsProxyEventObject() +: mNext(nsnull), + mHashKey((void*)0) +{ } - - - - nsProxyEventObject::nsProxyEventObject(nsIEventQueue *destQueue, PRInt32 proxyType, nsISupports* aObj, nsProxyEventClass* aClass, - nsProxyEventObject* root) - : mClass(aClass), - mNext(NULL) + nsProxyEventObject* root, + PRUint32 hashValue) + : mNext(nsnull), + mHashKey((void*)hashValue) { NS_INIT_REFCNT(); - NS_ADDREF_THIS(); - - mProxyObject = new nsProxyObject(destQueue, proxyType, aObj); - mRoot = (root ? root : this); - - // if we have a root, lets addref it. - if (root) - NS_ADDREF(mRoot); + mRoot = root; + mClass = aClass; - NS_ADDREF(aClass); + mProxyObject = new nsProxyObject(destQueue, proxyType, aObj); + +#ifdef DEBUG_dougt +DebugDump("Create", 0); +#endif } nsProxyEventObject::~nsProxyEventObject() { - NS_IF_RELEASE(mProxyObject); - NS_IF_RELEASE(mClass); - - if (mRoot) +#ifdef DEBUG_dougt +DebugDump("Delete", 0); +#endif + if (mRoot != nsnull) { - if (mRoot != this) + nsProxyEventObject* cur = mRoot; + while(1) { - mRoot->RootRemoval(); - } - else - { - nsProxyObjectManager *manager = nsProxyObjectManager::GetInstance(); - nsHashtable *realToProxyMap = manager->GetRealObjectToProxyObjectMap(); - - if (realToProxyMap != nsnull) + if(cur->mNext == this) { - nsVoidKey key(this); - realToProxyMap->Remove(&key); + cur->mNext = mNext; + break; } + cur = cur->mNext; + NS_ASSERTION(cur, "failed to find wrapper in its own chain"); + } + } + else + { + nsProxyObjectManager *manager = nsProxyObjectManager::GetInstance(); + nsHashtable *realToProxyMap = manager->GetRealObjectToProxyObjectMap(); + + if (realToProxyMap != nsnull && mHashKey.HashValue() != 0) + { + realToProxyMap->Remove(&mHashKey); } } -} - -nsresult -nsProxyEventObject::RootRemoval() -{ - if (--mRefCnt <= 1) - NS_DELETEXPCOM(this); - return NS_OK; + // I am worried about ordering. + // do not remove assignments. + mProxyObject = 0; + mClass = 0; + mRoot = 0; } NS_IMPL_ADDREF(nsProxyEventObject); @@ -215,22 +301,44 @@ NS_IMPL_RELEASE(nsProxyEventObject); NS_IMETHODIMP nsProxyEventObject::QueryInterface(REFNSIID aIID, void** aInstancePtr) { - // TODO: we need to wrap the object if it is not a proxy. - + if( aIID.Equals(GetIID()) ) + { + *aInstancePtr = (void*) ( (nsISupports*)this ); //todo should use standard cast. + NS_ADDREF_THIS(); + return NS_OK; + } + return mClass->DelegatedQueryInterface(this, aIID, aInstancePtr); } +PRUint32 +nsProxyEventObject::GetProxyHashKey(nsISupports *rootProxy, nsIEventQueue *destQueue, PRInt32 proxyType) +{ // FIX I need to worry about nsCOMPtr for rootProxy, and destQueue! + + nsISupports* destQRoot; + if(NS_FAILED(destQueue->QueryInterface(nsCOMTypeInfo::GetIID(), (void**)&destQRoot))) + return 0; + PRInt32 value = (PRUint32)rootProxy + (PRUint32)destQRoot + proxyType; + NS_RELEASE(destQRoot); + return value; +} + nsProxyEventObject* nsProxyEventObject::Find(REFNSIID aIID) { - if(aIID.Equals(nsCOMTypeInfo::GetIID())) - return mRoot; + nsProxyEventObject* cur = (mRoot ? mRoot.get() : this); + + if(aIID.Equals(nsCOMTypeInfo::GetIID())) + { + return cur; + } - nsProxyEventObject* cur = mRoot; do { - if(aIID.Equals(GetIID())) + if(aIID.Equals(GetClass()->GetProxiedIID())) + { return cur; + } } while(NULL != (cur = cur->mNext)); @@ -241,11 +349,13 @@ nsProxyEventObject::Find(REFNSIID aIID) NS_IMETHODIMP nsProxyEventObject::GetInterfaceInfo(nsIInterfaceInfo** info) { + NS_ENSURE_ARG_POINTER(info); NS_ASSERTION(GetClass(), "proxy without class"); NS_ASSERTION(GetClass()->GetInterfaceInfo(), "proxy class without interface"); if(!(*info = GetClass()->GetInterfaceInfo())) return NS_ERROR_UNEXPECTED; + NS_ADDREF(*info); return NS_OK; } @@ -255,7 +365,10 @@ nsProxyEventObject::CallMethod(PRUint16 methodIndex, const nsXPTMethodInfo* info, nsXPTCMiniVariant * params) { - return mProxyObject->Post(methodIndex, (nsXPTMethodInfo*)info, params, GetClass()->GetInterfaceInfo()); + if (mProxyObject) + return mProxyObject->Post(methodIndex, (nsXPTMethodInfo*)info, params, GetClass()->GetInterfaceInfo()); + + return NS_ERROR_NULL_POINTER; } @@ -274,6 +387,3 @@ nsProxyEventObject::CallMethod(PRUint16 methodIndex, - - - diff --git a/mozilla/xpcom/proxy/src/nsProxyEventPrivate.h b/mozilla/xpcom/proxy/src/nsProxyEventPrivate.h index 445bb644738..397054c196e 100644 --- a/mozilla/xpcom/proxy/src/nsProxyEventPrivate.h +++ b/mozilla/xpcom/proxy/src/nsProxyEventPrivate.h @@ -22,6 +22,7 @@ #include "nscore.h" #include "nsISupports.h" #include "nsIFactory.h" +#include "nsHashtable.h" #include "plevent.h" #include "xptcall.h" // defines nsXPTCVariant @@ -44,28 +45,44 @@ class nsProxyEventClass; { 0xeea90d45, 0xb059, 0x11d2, \ { 0x91, 0x5e, 0xc1, 0x2b, 0x69, 0x6c, 0x93, 0x33 } } + +#define NS_PROXYEVENT_OBJECT_IID \ +{ 0xec373590, 0x9164, 0x11d3, \ +{0x8c, 0x73, 0x00, 0x00, 0x64, 0x65, 0x73, 0x74} } + +static NS_DEFINE_IID(kProxyEventClassIID, NS_PROXYEVENT_CLASS_IID); +static NS_DEFINE_IID(kProxyEventObjectIID, NS_PROXYEVENT_OBJECT_IID); + + class nsProxyEventClass : public nsISupports { public: - // all the interface method declarations... NS_DECL_ISUPPORTS - NS_IMETHOD DelegatedQueryInterface(nsProxyEventObject* self, REFNSIID aIID, void** aInstancePtr); - + + + static const nsIID& GetIID() {static nsIID iid = kProxyEventClassIID; return iid;} static nsProxyEventClass* GetNewOrUsedClass(REFNSIID aIID); + + NS_IMETHOD DelegatedQueryInterface( nsProxyEventObject* self, + REFNSIID aIID, + void** aInstancePtr); + - REFNSIID GetIID() const {return mIID;} nsIInterfaceInfo* GetInterfaceInfo() const {return mInfo;} - nsresult CallQueryInterfaceOnProxy(nsProxyEventObject* self, REFNSIID aIID, nsProxyEventObject** aInstancePtr); - + const nsIID& GetProxiedIID() const {return mIID; } protected: - + nsProxyEventClass(); nsProxyEventClass(REFNSIID aIID, nsIInterfaceInfo* aInfo); virtual ~nsProxyEventClass(); private: - nsIInterfaceInfo* mInfo; - nsIID mIID; - uint32* mDescriptors; + nsIID mIID; + nsCOMPtr mInfo; + uint32* mDescriptors; + + nsresult CallQueryInterfaceOnProxy(nsProxyEventObject* self, + REFNSIID aIID, + nsProxyEventObject** aInstancePtr); }; @@ -75,42 +92,53 @@ class nsProxyEventObject : public nsXPTCStubBase public: NS_DECL_ISUPPORTS - - NS_IMETHOD GetInterfaceInfo(nsIInterfaceInfo** info); - - // call this method and return result - NS_IMETHOD CallMethod(PRUint16 methodIndex, const nsXPTMethodInfo* info, nsXPTCMiniVariant* params); - + static const nsIID& GetIID() {static nsIID iid = kProxyEventObjectIID; return iid;} static nsProxyEventObject* GetNewOrUsedProxy(nsIEventQueue *destQueue, PRInt32 proxyType, nsISupports *aObj, REFNSIID aIID); + + static PRUint32 GetProxyHashKey( nsISupports *rootProxy, + nsIEventQueue *destQueue, + PRInt32 proxyType); + + + + NS_IMETHOD GetInterfaceInfo(nsIInterfaceInfo** info); + + // call this method and return result + NS_IMETHOD CallMethod(PRUint16 methodIndex, const nsXPTMethodInfo* info, nsXPTCMiniVariant* params); - REFNSIID GetIID() const { return GetClass()->GetIID();} nsProxyEventClass* GetClass() const { return mClass; } - nsIEventQueue* GetQueue() const { return mProxyObject->GetQueue(); } - nsISupports* GetRealObject() const { return mProxyObject->GetRealObject(); } - + nsIEventQueue* GetQueue() const { return (mProxyObject ? mProxyObject->GetQueue() : nsnull);} + nsISupports* GetRealObject() const { return (mProxyObject ? mProxyObject->GetRealObject(): nsnull);} + PRInt32 GetProxyType() const { return (mProxyObject ? mProxyObject->GetProxyType() : nsnull);} -protected: - virtual ~nsProxyEventObject(); - + nsProxyEventObject(); nsProxyEventObject(nsIEventQueue *destQueue, PRInt32 proxyType, nsISupports* aObj, nsProxyEventClass* aClass, - nsProxyEventObject* root); + nsProxyEventObject* root, + PRUint32 hashValue); + + virtual ~nsProxyEventObject(); nsProxyEventObject* Find(REFNSIID aIID); -private: - nsresult RootRemoval(); +#ifdef DEBUG_dougt + void DebugDump(const char * message, PRUint32 hashKey); +#endif - nsProxyObject* mProxyObject; - nsProxyEventClass* mClass; - nsProxyEventObject* mRoot; +protected: + nsVoidKey mHashKey; + + nsCOMPtr mProxyObject; + nsCOMPtr mClass; + nsCOMPtr mRoot; + nsProxyEventObject* mNext; }; diff --git a/mozilla/xpcom/proxy/src/nsProxyObjectManager.cpp b/mozilla/xpcom/proxy/src/nsProxyObjectManager.cpp index c8c12d1a994..4afafce6e35 100644 --- a/mozilla/xpcom/proxy/src/nsProxyObjectManager.cpp +++ b/mozilla/xpcom/proxy/src/nsProxyObjectManager.cpp @@ -77,16 +77,6 @@ NS_IMETHODIMP nsProxyCreateInstance::CreateInstanceByProgID(const char *aProgID, result); } - - - - - - - - - - ///////////////////////////////////////////////////////////////////////// // nsProxyObjectManager ///////////////////////////////////////////////////////////////////////// @@ -181,25 +171,12 @@ nsProxyObjectManager::GetProxyObject(nsIEventQueue *destQueue, REFNSIID aIID, ns } } - nsISupports* realObject; - - // we need to do make sure that we addref the passed in object as well as ensure - // that it is of the requested IID; - - rv = aObj->QueryInterface(aIID, (void**)&realObject); - - if ( NS_FAILED( rv ) ) - return rv; - // check to see if proxy is there or not. - *aProxyObject = nsProxyEventObject::GetNewOrUsedProxy(postQ, proxyType, realObject, aIID); + *aProxyObject = nsProxyEventObject::GetNewOrUsedProxy(postQ, proxyType, aObj, aIID); if (*aProxyObject == nsnull) - { - NS_RELEASE(aObj); - return NS_ERROR_NO_INTERFACE; //fix error code? - } - + return NS_ERROR_NO_INTERFACE; //fix error code? + return NS_OK; }