Mozilla/mozilla/xpcom/proxy/src/nsProxyEventObject.cpp
scc%netscape.com a2d0be4d64 |nsISupports::GetIID()| --> |nsCOMTypeInfo<nsISupports>::GetIID()|
git-svn-id: svn://10.0.0.236/trunk@37444 18797224-902f-48f8-a5cc-f745e15eee43
1999-06-29 21:01:31 +00:00

299 lines
7.2 KiB
C++

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#include "nsProxyEvent.h"
#include "nsProxyObjectManager.h"
#include "nsProxyEventPrivate.h"
#include "nsHashtable.h"
#include "nsIInterfaceInfoManager.h"
#include "xptcall.h"
//////////////////////////////////////////////////////////////////////////////////////////////////
//
// nsProxyEventObject
//
//////////////////////////////////////////////////////////////////////////////////////////////////
nsProxyEventObject*
nsProxyEventObject::GetNewOrUsedProxy(nsIEventQueue *destQueue,
ProxyType proxyType,
nsISupports *aObj,
REFNSIID aIID)
{
nsProxyEventObject* proxy = NULL;
nsProxyEventObject* root = NULL;
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 */
nsProxyObjectManager *manager = nsProxyObjectManager::GetInstance();
nsHashtable *realToProxyMap = manager->GetRealObjectToProxyObjectMap();
if (realToProxyMap == nsnull)
{
if(clazz)
NS_RELEASE(clazz);
return nsnull;
}
nsVoidKey rootkey(rootObject);
if(realToProxyMap->Exists(&rootkey))
{
root = (nsProxyEventObject*) realToProxyMap->Get(&rootkey);
proxy = root->Find(aIID);
if(proxy)
{
NS_ADDREF(proxy);
goto return_wrapper;
}
}
else
{
// build the root proxy
if (aObj == rootObject)
{
// 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);
}
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;
}
nsVoidKey aKey(root);
realToProxyMap->Put(&aKey, root);
}
}
// at this point we have a root and may need to build the specific proxy
NS_ASSERTION(root,"bad root");
NS_ASSERTION(clazz,"bad clazz");
if(!proxy)
{
proxy = new nsProxyEventObject(destQueue, proxyType, aObj, clazz, root);
if(!proxy)
{
goto return_wrapper;
}
}
proxy->mNext = root->mNext;
root->mNext = proxy;
return_wrapper:
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(nsIEventQueue *destQueue,
ProxyType proxyType,
nsISupports* aObj,
nsProxyEventClass* aClass,
nsProxyEventObject* root)
: mClass(aClass),
mNext(NULL)
{
mRoot = (root ? root : this);
mProxyObject = new nsProxyObject(destQueue, proxyType, aObj);
NS_INIT_REFCNT();
NS_ADDREF_THIS();
NS_ADDREF(aClass);
}
nsProxyEventObject::~nsProxyEventObject()
{
NS_PRECONDITION(0 == mRefCnt, "refcounting error");
if(mRoot == this && GetClass())
{
nsProxyObjectManager *manager = nsProxyObjectManager::GetInstance();
nsHashtable *realToProxyMap = manager->GetRealObjectToProxyObjectMap();
if (realToProxyMap != nsnull)
{
nsVoidKey key(this);
realToProxyMap->Remove(&key);
}
}
if (mProxyObject != nsnull)
mProxyObject->Release();
NS_RELEASE(mClass);
if(mNext)
NS_DELETEXPCOM(mNext); // cascaded delete
}
NS_IMETHODIMP
nsProxyEventObject::QueryInterface(REFNSIID aIID, void** aInstancePtr)
{
if(NULL == aInstancePtr)
{
NS_PRECONDITION(0, "null pointer");
return NS_ERROR_NULL_POINTER;
}
return mClass->DelegatedQueryInterface(this, aIID, aInstancePtr);
}
nsrefcnt
nsProxyEventObject::AddRef(void)
{
NS_PRECONDITION(mRoot, "bad root");
if(1 == ++mRefCnt && mRoot && mRoot != this)
NS_ADDREF(mRoot);
return mRefCnt;
}
nsrefcnt
nsProxyEventObject::Release(void)
{
NS_PRECONDITION(mRoot, "bad root");
NS_PRECONDITION(0 != mRefCnt, "dup release");
if(0 == --mRefCnt)
{
if(mRoot == this)
{
NS_DELETEXPCOM(this); // cascaded delete
}
else
{
mRoot->Release();
}
return 0;
}
return mRefCnt;
}
nsProxyEventObject*
nsProxyEventObject::Find(REFNSIID aIID)
{
if(aIID.Equals(nsCOMTypeInfo<nsISupports>::GetIID()))
return mRoot;
nsProxyEventObject* cur = mRoot;
do
{
if(aIID.Equals(GetIID()))
return cur;
} while(NULL != (cur = cur->mNext));
return NULL;
}
NS_IMETHODIMP
nsProxyEventObject::GetInterfaceInfo(nsIInterfaceInfo** 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;
}
NS_IMETHODIMP
nsProxyEventObject::CallMethod(PRUint16 methodIndex,
const nsXPTMethodInfo* info,
nsXPTCMiniVariant * params)
{
return mProxyObject->Post(methodIndex, (nsXPTMethodInfo*)info, params, GetClass()->GetInterfaceInfo());
}