Example #1
0
nsresult PyG_Base::HandleNativeGatewayError(const char *szMethodName)
{
	nsresult rc = NS_OK;
	if (PyErr_Occurred()) {
		// The error handling - fairly involved, but worth it as
		// good error reporting is critical for users to know WTF 
		// is going on - especially with TypeErrors etc in their
		// return values (ie, after the Python code has successfully
		// exited, but we encountered errors unpacking their
		// result values for the COM caller - there is literally no 
		// way to catch these exceptions from Python code, as their
		// is no Python function directly on the call-stack)

		// First line of attack in an error is to call-back on the policy.
		// If the callback of the error handler succeeds and returns an
		// integer (for the nsresult), we take no further action.

		// If this callback fails, we log _2_ exceptions - the error
		// handler error, and the original error.

		PRBool bProcessMainError = PR_TRUE; // set to false if our exception handler does its thing!
		PyObject *exc_typ, *exc_val, *exc_tb;
		PyErr_Fetch(&exc_typ, &exc_val, &exc_tb);

		PyObject *err_result = PyObject_CallMethod(m_pPyObject, 
	                                       (char*)"_GatewayException_",
					       (char*)"z(OOO)",
					       szMethodName,
		                               exc_typ ? exc_typ : Py_None, // should never be NULL, but defensive programming...
		                               exc_val ? exc_val : Py_None, // may well be NULL.
					       exc_tb ? exc_tb : Py_None); // may well be NULL.
		if (err_result == NULL) {
			PyXPCOM_LogError("The exception handler _CallMethodException_ failed!\n");
		} else if (err_result == Py_None) {
			// The exception handler has chosen not to do anything with
			// this error, so we still need to print it!
			;
		} else if (PyInt_Check(err_result)) {
			// The exception handler has given us the nresult.
			rc = PyInt_AsLong(err_result);
			bProcessMainError = PR_FALSE;
		} else {
			// The exception handler succeeded, but returned other than
			// int or None.
			PyXPCOM_LogError("The _CallMethodException_ handler returned object of type '%s' - None or an integer expected\n", err_result->ob_type->tp_name);
		}
		Py_XDECREF(err_result);
		PyErr_Restore(exc_typ, exc_val, exc_tb);
		if (bProcessMainError) {
			PyXPCOM_LogError("The function '%s' failed\n", szMethodName);
			rc = PyXPCOM_SetCOMErrorFromPyException();
		}
		PyErr_Clear();
	}
	return rc;
}
// nsIArray impl
NS_IMETHODIMP nsPyArgArray::GetLength(PRUint32 *aLength)
{
  CEnterLeavePython _celp;
  int size = PySequence_Length(mObject);
  if (size==-1) {
    return PyXPCOM_SetCOMErrorFromPyException();
  }
  *aLength = (PRUint32) size;
  return NS_OK;
}
/* void queryElementAt (in unsigned long index, in nsIIDRef uuid, [iid_is (uuid), retval] out nsQIResult result); */
NS_IMETHODIMP nsPyArgArray::QueryElementAt(PRUint32 index, const nsIID & uuid, void * *result)
{
  *result = nsnull;
  // for now let Python check index validity.  Probably won't get the correct
  // hresult, but its not even clear what that is :)

  if (uuid.Equals(NS_GET_IID(nsIVariant)) || uuid.Equals(NS_GET_IID(nsISupports))) {
    CEnterLeavePython _celp;
    PyObject *sub = PySequence_GetItem(mObject, index);
    if (sub==NULL) {
        return PyXPCOM_SetCOMErrorFromPyException();
    }
    nsresult rv = PyObject_AsVariant(sub, (nsIVariant **)result);
    Py_DECREF(sub);
    return rv;
  }
  NS_WARNING("nsPyArgArray only handles nsIVariant");
  return NS_ERROR_NO_INTERFACE;
}