280 lines
7.9 KiB
C++
280 lines
7.9 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 "nsRepository.h"
|
|
#include "nsIServiceManager.h"
|
|
#include "nsCOMPtr.h"
|
|
|
|
#include "nsIAllocator.h"
|
|
#include "nsHashtable.h"
|
|
|
|
|
|
#include "nsIInterfaceInfoManager.h"
|
|
#include "xptcall.h"
|
|
|
|
|
|
|
|
static uint32 zero_methods_descriptor;
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////
|
|
// nsProxyEventClass
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
static NS_DEFINE_IID(kProxyEventClassIID, NS_PROXYEVENT_CLASS_IID);
|
|
|
|
NS_IMPL_ISUPPORTS(nsProxyEventClass, kProxyEventClassIID)
|
|
|
|
// static
|
|
nsProxyEventClass*
|
|
nsProxyEventClass::GetNewOrUsedClass(REFNSIID aIID)
|
|
{
|
|
/* find in our hash table */
|
|
|
|
nsProxyObjectManager *manager = nsProxyObjectManager::GetInstance();
|
|
nsHashtable *iidToClassMap = manager->GetIIDToProxyClassMap();
|
|
|
|
|
|
nsProxyEventClass* clazz = NULL;
|
|
nsIDKey key(aIID);
|
|
|
|
if(iidToClassMap->Exists(&key))
|
|
{
|
|
clazz = (nsProxyEventClass*) iidToClassMap->Get(&key);
|
|
NS_ADDREF(clazz);
|
|
}
|
|
else
|
|
{
|
|
nsIInterfaceInfoManager* iimgr;
|
|
if(NULL != (iimgr = XPTI_GetInterfaceInfoManager()))
|
|
{
|
|
nsIInterfaceInfo* info;
|
|
if(NS_SUCCEEDED(iimgr->GetInfoForIID(&aIID, &info)))
|
|
{
|
|
/*
|
|
Check to see if IsISupportsDescendent
|
|
*/
|
|
nsIInterfaceInfo* oldest = info;
|
|
nsIInterfaceInfo* parent;
|
|
|
|
NS_ADDREF(oldest);
|
|
while(NS_SUCCEEDED(oldest->GetParent(&parent)))
|
|
{
|
|
NS_RELEASE(oldest);
|
|
oldest = parent;
|
|
}
|
|
|
|
PRBool IsISupportsDescendent = PR_FALSE;
|
|
nsID* iid;
|
|
if(NS_SUCCEEDED(oldest->GetIID(&iid)))
|
|
{
|
|
IsISupportsDescendent = iid->Equals(nsISupports::GetIID());
|
|
nsAllocator::Free(iid);
|
|
}
|
|
NS_RELEASE(oldest);
|
|
|
|
NS_ASSERTION(IsISupportsDescendent,"!IsISupportsDescendent");
|
|
|
|
if (IsISupportsDescendent)
|
|
{
|
|
clazz = new nsProxyEventClass(aIID, info);
|
|
if(!clazz->mDescriptors)
|
|
NS_RELEASE(clazz); // sets clazz to NULL
|
|
}
|
|
NS_RELEASE(info);
|
|
}
|
|
NS_RELEASE(iimgr);
|
|
}
|
|
}
|
|
return clazz;
|
|
}
|
|
|
|
|
|
nsProxyEventClass::nsProxyEventClass(REFNSIID aIID, nsIInterfaceInfo* aInfo)
|
|
: mInfo(aInfo),
|
|
mIID(aIID),
|
|
mDescriptors(NULL)
|
|
{
|
|
NS_ADDREF(mInfo);
|
|
|
|
NS_INIT_REFCNT();
|
|
NS_ADDREF_THIS();
|
|
|
|
/* add use to the used classes */
|
|
nsIDKey key(aIID);
|
|
|
|
nsProxyObjectManager *manager = nsProxyObjectManager::GetInstance();
|
|
nsHashtable *iidToClassMap = manager->GetIIDToProxyClassMap();
|
|
|
|
iidToClassMap->Put(&key, this);
|
|
|
|
uint16 methodCount;
|
|
if(NS_SUCCEEDED(mInfo->GetMethodCount(&methodCount)))
|
|
{
|
|
if(methodCount)
|
|
{
|
|
int wordCount = (methodCount/32)+1;
|
|
if(NULL != (mDescriptors = new uint32[wordCount]))
|
|
{
|
|
int i;
|
|
// init flags to 0;
|
|
for(i = wordCount-1; i >= 0; i--)
|
|
mDescriptors[i] = 0;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
mDescriptors = &zero_methods_descriptor;
|
|
}
|
|
}
|
|
}
|
|
|
|
nsProxyEventClass::~nsProxyEventClass()
|
|
{
|
|
if(mDescriptors && mDescriptors != &zero_methods_descriptor)
|
|
delete [] mDescriptors;
|
|
|
|
nsIDKey key(mIID);
|
|
|
|
nsProxyObjectManager *manager = nsProxyObjectManager::GetInstance();
|
|
nsHashtable *iidToClassMap = manager->GetIIDToProxyClassMap();
|
|
iidToClassMap->Remove(&key);
|
|
|
|
NS_RELEASE(mInfo);
|
|
}
|
|
|
|
nsProxyEventObject*
|
|
nsProxyEventClass::CallQueryInterfaceOnProxy(nsProxyEventObject* self, REFNSIID aIID)
|
|
{
|
|
|
|
nsISupports* aInstancePtr;
|
|
|
|
// The functions we will call: QueryInterface(REFNSIID aIID, void** aInstancePtr)
|
|
|
|
nsXPTCMiniVariant *var = new nsXPTCMiniVariant[2];
|
|
if (var == nsnull) return nsnull;
|
|
|
|
(&var[0])->val.p = (void*)&aIID;
|
|
(&var[1])->val.p = &aInstancePtr;
|
|
|
|
nsIInterfaceInfoManager *iim = XPTI_GetInterfaceInfoManager();
|
|
nsIInterfaceInfo *nsISupportsInfo;
|
|
const nsXPTMethodInfo *mi;
|
|
|
|
iim->GetInfoForName("nsISupports", &nsISupportsInfo);
|
|
nsISupportsInfo->GetMethodInfo(0, &mi); // 0 is QueryInterface
|
|
|
|
nsresult rv = self->CallMethod(0, mi, var);
|
|
|
|
aInstancePtr = (nsISupports*) *((void**)var[1].val.p);
|
|
|
|
delete [] var;
|
|
|
|
if (rv == NS_OK)
|
|
{
|
|
nsProxyEventObject* proxyObj = nsProxyEventObject::GetNewOrUsedProxy(self->GetQueue(), aInstancePtr, aIID);
|
|
if(proxyObj)
|
|
{
|
|
return proxyObj;
|
|
}
|
|
}
|
|
|
|
return nsnull;
|
|
}
|
|
|
|
|
|
/***************************************************************************/
|
|
// 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 (hence it is declared in this implementation file).
|
|
|
|
/* eea90d45-b059-11d2-915e-c12b696c9333 */
|
|
#define NS_PROXYEVENT_IDENTITY_CLASS_IID \
|
|
{ 0xeea90d45, 0xb059, 0x11d2, \
|
|
{ 0x91, 0x5e, 0xc1, 0x2b, 0x69, 0x6c, 0x93, 0x33 } }
|
|
|
|
class ProxyEventClassIdentity
|
|
{
|
|
// no instance methods...
|
|
public:
|
|
NS_DEFINE_STATIC_IID_ACCESSOR(NS_PROXYEVENT_IDENTITY_CLASS_IID)
|
|
|
|
static void* GetSingleton()
|
|
{
|
|
static ProxyEventClassIdentity* singleton = NULL;
|
|
if(!singleton)
|
|
singleton = new ProxyEventClassIdentity();
|
|
return (void*) singleton;
|
|
}
|
|
};
|
|
|
|
NS_IMETHODIMP
|
|
nsProxyEventClass::DelegatedQueryInterface(nsProxyEventObject* self,
|
|
REFNSIID aIID,
|
|
void** aInstancePtr)
|
|
{
|
|
if(aIID.Equals(nsISupports::GetIID()))
|
|
{
|
|
nsProxyEventObject* root = self->GetRootProxyObject();
|
|
*aInstancePtr = (void*) root;
|
|
NS_ADDREF(root);
|
|
return NS_OK;
|
|
}
|
|
else if(aIID.Equals(self->GetIID()))
|
|
{
|
|
*aInstancePtr = (void*) self;
|
|
NS_ADDREF(self);
|
|
return NS_OK;
|
|
}
|
|
else if(aIID.Equals(ProxyEventClassIdentity::GetIID()))
|
|
{
|
|
*aInstancePtr = ProxyEventClassIdentity::GetSingleton();
|
|
return NS_OK;
|
|
}
|
|
else
|
|
{
|
|
*aInstancePtr = CallQueryInterfaceOnProxy(self, aIID);
|
|
if (*aInstancePtr == nsnull)
|
|
return NS_NOINTERFACE;
|
|
else
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
*aInstancePtr = NULL;
|
|
return NS_NOINTERFACE;
|
|
}
|
|
|
|
|
|
|
|
nsProxyEventObject*
|
|
nsProxyEventClass::GetRootProxyObject(nsProxyEventObject* anObject)
|
|
{
|
|
nsProxyEventObject* result = CallQueryInterfaceOnProxy(anObject, nsISupports::GetIID());
|
|
return result ? result : anObject;
|
|
} |