Exemple #1
0
NS_IMETHODIMP
PyG_Base::QueryInterface(REFNSIID iid, void** ppv)
{
#ifdef PYXPCOM_DEBUG_FULL
	{
		char *sziid = iid.ToString();
		LogF("PyGatewayBase::QueryInterface: %s", sziid);
		Allocator::Free(sziid);
	}
#endif
	NS_PRECONDITION(ppv, "NULL pointer");
	if (ppv==nsnull)
		return NS_ERROR_NULL_POINTER;
	*ppv = nsnull;
	// If one of our native interfaces (but NOT nsISupports if we have a base)
	// return this.
	// It is important is that nsISupports come from the base object
	// to ensure that we live by XPCOM identity rules (other interfaces need
	// not abide by this rule - only nsISupports.)
	if ( (m_pBaseObject==NULL || !iid.Equals(NS_GET_IID(nsISupports)))
	   && (*ppv=ThisAsIID(iid)) != NULL ) {
		AddRef();
		return NS_OK;
	}
	// If we have a "base object", then we need to delegate _every_ remaining 
	// QI to it.
	if (m_pBaseObject != NULL)
		return m_pBaseObject->QueryInterface(iid, ppv);

	// Call the Python policy to see if it (says it) supports the interface
	PRBool supports = PR_FALSE;
	{ // temp scope for Python lock
		CEnterLeavePython celp;

		PyObject * ob = Py_nsIID::PyObjectFromIID(iid);
		// must say this is an 'internal' call, else we recurse QI into
		// oblivion.
		PyObject * this_interface_ob = Py_nsISupports::PyObjectFromInterface(
		                                       (nsXPTCStubBase *)this,
		                                       iid, PR_FALSE, PR_TRUE);
		if ( !ob || !this_interface_ob) {
			Py_XDECREF(ob);
			Py_XDECREF(this_interface_ob);
			return NS_ERROR_OUT_OF_MEMORY;
		}

		PyObject *result = PyObject_CallMethod(m_pPyObject, (char*)"_QueryInterface_",
		                                                    (char*)"OO", 
		                                                    this_interface_ob, ob);
		Py_DECREF(ob);
		Py_DECREF(this_interface_ob);

		if ( result ) {
			if (Py_nsISupports::InterfaceFromPyObject(result, iid, (nsISupports **)ppv, PR_TRUE)) {
				// If OK, but NULL, _QI_ returned None, which simply means
				// "no such interface"
				supports = (*ppv!=NULL);
				// result has been QI'd and AddRef'd all ready for return.
			} else {
				// Dump this message and any Python exception before
				// reporting the fact that QI failed - this error
				// may provide clues!
				PyXPCOM_LogError("The _QueryInterface_ method returned an object of type '%s', but an interface was expected\n", result->ob_type->tp_name);
				// supports remains false
			}
			Py_DECREF(result);
		} else {
			NS_ABORT_IF_FALSE(PyErr_Occurred(), "Got NULL result, but no Python error flagged!");
			NS_WARN_IF_FALSE(!supports, "Have failure with success flag set!");
			PyXPCOM_LogError("The _QueryInterface_ processing failed.\n");
			// supports remains false.
			// We have reported the error, and are returning to COM,
			// so we should clear it.
			PyErr_Clear();
		}
	} // end of temp scope for Python lock - lock released here!
	if ( !supports )
		return NS_ERROR_NO_INTERFACE;
	return NS_OK;
}