зеркало из https://github.com/mozilla/pjs.git
dougt's changes from earlier in the week. He was unable to leave them
in at that time because he didn't have my |nsCOMPtr| fixes. Those went in last night. So, on brendans suggestion, I'm reinstating dougt's previous checkin.
This commit is contained in:
Родитель
34a64c7050
Коммит
ace7038d48
|
@ -76,18 +76,21 @@ class nsProxyObject : public nsISupports
|
|||
public:
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(nsCOMTypeInfo<nsISupports>::GetIID())
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(nsCOMTypeInfo<nsISupports>::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; }
|
||||
|
||||
|
@ -95,6 +98,20 @@ public:
|
|||
|
||||
|
||||
private:
|
||||
|
||||
PRInt32 mProxyType;
|
||||
|
||||
nsCOMPtr<nsIEventQueue> mDestQueue; /* destination queue */
|
||||
|
||||
nsCOMPtr<nsISupports> 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
|
||||
{
|
||||
|
@ -108,19 +125,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
|
||||
|
@ -128,6 +133,7 @@ class NS_EXPORT nsProxyObjectCallInfo
|
|||
public:
|
||||
|
||||
nsProxyObjectCallInfo(nsProxyObject* owner,
|
||||
nsXPTMethodInfo *methodInfo,
|
||||
PRUint32 methodIndex,
|
||||
nsXPTCVariant* parameterList,
|
||||
PRUint32 parameterCount,
|
||||
|
@ -141,23 +147,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<nsProxyObject> 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<nsProxyObject> mOwner; /* this is the strong referenced nsProxyObject */
|
||||
|
||||
void RefCountInInterfacePointers(PRBool addRef);
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
#include "nsProxyObjectManager.h"
|
||||
|
||||
#include "pratom.h"
|
||||
#include "prmem.h" // for PR_NEW
|
||||
#include "prmem.h"
|
||||
#include "xptcall.h"
|
||||
|
||||
#include "nsRepository.h"
|
||||
|
@ -41,8 +41,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,
|
||||
|
@ -54,33 +57,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)
|
||||
|
||||
|
@ -90,71 +162,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<nsIEventQueue> eventQ;
|
||||
rv = eventQService->GetThreadEventQueue(PR_CurrentThread(), getter_AddRefs(eventQ));
|
||||
if (NS_FAILED(rv))
|
||||
{
|
||||
rv = eventQService->CreateThreadEventQueue();
|
||||
|
@ -162,36 +229,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;
|
||||
|
@ -221,10 +302,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())
|
||||
|
@ -235,28 +313,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;
|
||||
}
|
||||
|
||||
|
@ -273,12 +361,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;
|
||||
}
|
||||
|
@ -286,14 +375,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;
|
||||
}
|
||||
|
||||
|
@ -302,16 +386,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;
|
||||
|
@ -526,45 +664,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;
|
||||
}
|
||||
|
||||
|
|
|
@ -45,9 +45,6 @@ static uint32 zero_methods_descriptor;
|
|||
//////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// nsProxyEventClass
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static NS_DEFINE_IID(kProxyEventClassIID, NS_PROXYEVENT_CLASS_IID);
|
||||
|
||||
NS_IMPL_ISUPPORTS(nsProxyEventClass, kProxyEventClassIID)
|
||||
|
||||
// static
|
||||
|
@ -64,7 +61,7 @@ nsProxyEventClass::GetNewOrUsedClass(REFNSIID aIID)
|
|||
return nsnull;
|
||||
}
|
||||
|
||||
nsProxyEventClass* clazz = NULL;
|
||||
nsProxyEventClass* clazz = nsnull;
|
||||
nsIDKey key(aIID);
|
||||
|
||||
if(iidToClassMap->Exists(&key))
|
||||
|
@ -74,22 +71,20 @@ nsProxyEventClass::GetNewOrUsedClass(REFNSIID aIID)
|
|||
}
|
||||
else
|
||||
{
|
||||
nsIInterfaceInfoManager* iimgr;
|
||||
if(NULL != (iimgr = XPTI_GetInterfaceInfoManager()))
|
||||
nsCOMPtr<nsIInterfaceInfoManager> iimgr = getter_AddRefs(XPTI_GetInterfaceInfoManager());
|
||||
if(iimgr)
|
||||
{
|
||||
nsIInterfaceInfo* info;
|
||||
if(NS_SUCCEEDED(iimgr->GetInfoForIID(&aIID, &info)))
|
||||
nsCOMPtr<nsIInterfaceInfo> info;
|
||||
if(NS_SUCCEEDED(iimgr->GetInfoForIID(&aIID, getter_AddRefs(info))))
|
||||
{
|
||||
/*
|
||||
Check to see if isISupportsDescendent
|
||||
*/
|
||||
nsIInterfaceInfo* oldest = info;
|
||||
nsIInterfaceInfo* parent;
|
||||
nsCOMPtr<nsIInterfaceInfo> oldest = info;
|
||||
nsCOMPtr<nsIInterfaceInfo> parent;
|
||||
|
||||
NS_ADDREF(oldest);
|
||||
while(NS_SUCCEEDED(oldest->GetParent(&parent)))
|
||||
while(NS_SUCCEEDED(oldest->GetParent(getter_AddRefs(parent))))
|
||||
{
|
||||
NS_RELEASE(oldest);
|
||||
oldest = parent;
|
||||
}
|
||||
|
||||
|
@ -100,8 +95,7 @@ nsProxyEventClass::GetNewOrUsedClass(REFNSIID aIID)
|
|||
isISupportsDescendent = iid->Equals(nsCOMTypeInfo<nsISupports>::GetIID());
|
||||
nsAllocator::Free(iid);
|
||||
}
|
||||
NS_RELEASE(oldest);
|
||||
|
||||
|
||||
NS_VERIFY(isISupportsDescendent,"!isISupportsDescendent");
|
||||
|
||||
if (isISupportsDescendent)
|
||||
|
@ -110,24 +104,25 @@ nsProxyEventClass::GetNewOrUsedClass(REFNSIID aIID)
|
|||
if(!clazz->mDescriptors)
|
||||
NS_RELEASE(clazz); // sets clazz to NULL
|
||||
}
|
||||
NS_RELEASE(info);
|
||||
}
|
||||
NS_RELEASE(iimgr);
|
||||
}
|
||||
}
|
||||
return clazz;
|
||||
}
|
||||
|
||||
nsProxyEventClass::nsProxyEventClass()
|
||||
{
|
||||
NS_WARNING("This constructor should never be called");
|
||||
}
|
||||
|
||||
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);
|
||||
|
@ -172,8 +167,6 @@ nsProxyEventClass::~nsProxyEventClass()
|
|||
{
|
||||
iidToClassMap->Remove(&key);
|
||||
}
|
||||
|
||||
NS_RELEASE(mInfo);
|
||||
}
|
||||
|
||||
nsresult
|
||||
|
@ -218,10 +211,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
|
||||
{
|
||||
|
@ -243,24 +235,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<nsIInterfaceInfo> current = GetInterfaceInfo();
|
||||
nsCOMPtr<nsIInterfaceInfo> 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);
|
||||
}
|
||||
|
|
|
@ -29,6 +29,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
|
||||
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -36,89 +106,112 @@
|
|||
// nsProxyEventObject
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
nsProxyEventObject*
|
||||
nsProxyEventObject::GetNewOrUsedProxy(nsIEventQueue *destQueue,
|
||||
PRInt32 proxyType,
|
||||
nsISupports *aObj,
|
||||
REFNSIID aIID)
|
||||
{
|
||||
nsProxyEventObject* proxy = NULL;
|
||||
nsProxyEventObject* root = NULL;
|
||||
|
||||
nsCOMPtr<nsProxyEventObject> proxy = 0;
|
||||
nsCOMPtr<nsProxyEventObject> 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<nsISupports>::GetIID(), (void**)&rootObject)))
|
||||
return NULL;
|
||||
|
||||
|
||||
/* find in our hash table */
|
||||
// Get a class for this IID.
|
||||
nsCOMPtr<nsProxyEventClass> 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<nsProxyEventObject> 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<nsISupports> rootObject;
|
||||
if(NS_FAILED(aObj->QueryInterface(nsCOMTypeInfo<nsISupports>::GetIID(), getter_AddRefs(rootObject))))
|
||||
return nsnull;
|
||||
|
||||
/* 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<nsISupports> requestedInterface;
|
||||
if(NS_FAILED(aObj->QueryInterface(aIID, getter_AddRefs(requestedInterface))))
|
||||
return nsnull;
|
||||
|
||||
|
||||
// this will be our key in the hash table.
|
||||
nsVoidKey rootkey( (void*) GetProxyHashKey(rootObject.get(), destQueue, proxyType) );
|
||||
|
||||
// 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)
|
||||
|
||||
if(proxy)
|
||||
{
|
||||
NS_ADDREF(proxy);
|
||||
goto return_wrapper;
|
||||
peo = proxy;
|
||||
NS_ADDREF(peo);
|
||||
return peo;
|
||||
}
|
||||
}
|
||||
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)
|
||||
peo = new nsProxyEventObject(destQueue,
|
||||
proxyType,
|
||||
requestedInterface,
|
||||
clazz,
|
||||
nsnull,
|
||||
rootkey.HashValue());
|
||||
|
||||
proxy = do_QueryInterface(peo);
|
||||
|
||||
if(proxy)
|
||||
{
|
||||
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.
|
||||
realToProxyMap->Put(&rootkey, peo);
|
||||
peo = proxy;
|
||||
NS_ADDREF(peo);
|
||||
return peo;
|
||||
}
|
||||
goto return_wrapper;
|
||||
}
|
||||
else
|
||||
{
|
||||
// just a root proxy
|
||||
nsProxyEventClass* rootClazz = nsProxyEventClass::GetNewOrUsedClass(nsCOMTypeInfo<nsISupports>::GetIID());
|
||||
if(!rootClazz)
|
||||
{
|
||||
goto return_wrapper;
|
||||
}
|
||||
|
||||
root = new nsProxyEventObject(destQueue, proxyType, rootObject, rootClazz, nsnull);
|
||||
NS_RELEASE(rootClazz);
|
||||
|
||||
if(!root)
|
||||
{
|
||||
goto return_wrapper;
|
||||
}
|
||||
nsCOMPtr<nsProxyEventClass> rootClazz = getter_AddRefs ( nsProxyEventClass::GetNewOrUsedClass(
|
||||
nsCOMTypeInfo<nsISupports>::GetIID()) );
|
||||
|
||||
nsVoidKey aKey(root);
|
||||
realToProxyMap->Put(&aKey, root);
|
||||
if (!rootClazz)
|
||||
return nsnull;
|
||||
|
||||
peo = new nsProxyEventObject(destQueue,
|
||||
proxyType,
|
||||
rootObject,
|
||||
rootClazz,
|
||||
nsnull,
|
||||
rootkey.HashValue());
|
||||
|
||||
if(!peo)
|
||||
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
|
||||
|
@ -127,90 +220,89 @@ 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:
|
||||
peo = proxy;
|
||||
NS_ADDREF(peo);
|
||||
return peo;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
nsProxyEventObject::nsProxyEventObject()
|
||||
: mNext(nsnull),
|
||||
mHashKey((void*)0)
|
||||
{
|
||||
NS_WARNING("This constructor should never be called");
|
||||
}
|
||||
|
||||
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);
|
||||
|
@ -219,22 +311,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<nsISupports>::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<nsISupports>::GetIID()))
|
||||
return mRoot;
|
||||
nsProxyEventObject* cur = (mRoot ? mRoot.get() : this);
|
||||
|
||||
if(aIID.Equals(nsCOMTypeInfo<nsISupports>::GetIID()))
|
||||
{
|
||||
return cur;
|
||||
}
|
||||
|
||||
nsProxyEventObject* cur = mRoot;
|
||||
do
|
||||
{
|
||||
if(aIID.Equals(GetIID()))
|
||||
if(aIID.Equals(GetClass()->GetProxiedIID()))
|
||||
{
|
||||
return cur;
|
||||
}
|
||||
|
||||
} while(NULL != (cur = cur->mNext));
|
||||
|
||||
|
@ -245,11 +359,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;
|
||||
}
|
||||
|
@ -259,7 +375,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;
|
||||
}
|
||||
|
||||
|
||||
|
@ -278,6 +397,3 @@ nsProxyEventObject::CallMethod(PRUint16 methodIndex,
|
|||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include "nscore.h"
|
||||
#include "nsISupports.h"
|
||||
#include "nsIFactory.h"
|
||||
#include "nsHashtable.h"
|
||||
|
||||
#include "plevent.h"
|
||||
#include "xptcall.h" // defines nsXPTCVariant
|
||||
|
@ -48,28 +49,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<nsIInterfaceInfo> mInfo;
|
||||
uint32* mDescriptors;
|
||||
|
||||
nsresult CallQueryInterfaceOnProxy(nsProxyEventObject* self,
|
||||
REFNSIID aIID,
|
||||
nsProxyEventObject** aInstancePtr);
|
||||
};
|
||||
|
||||
|
||||
|
@ -79,42 +96,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<nsProxyObject> mProxyObject;
|
||||
nsCOMPtr<nsProxyEventClass> mClass;
|
||||
nsCOMPtr<nsProxyEventObject> mRoot;
|
||||
|
||||
nsProxyEventObject* mNext;
|
||||
};
|
||||
|
||||
|
|
|
@ -81,16 +81,6 @@ NS_IMETHODIMP nsProxyCreateInstance::CreateInstanceByProgID(const char *aProgID,
|
|||
result);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// nsProxyObjectManager
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
@ -185,25 +175,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;
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче