Bug 173146 - add support to XPConnect for IDispatch interfaces. Final implementation, this is the result of the code walk through with jband, jst, adam, and rpots. sr=jst, r=adam, a=asa
This commit is contained in:
Родитель
8408d2611f
Коммит
09c839447b
|
@ -79,7 +79,7 @@ interface nsIDispatchSupport : nsISupports
|
|||
* @param className contract ID or class ID of the desired component to instantiate
|
||||
* @return The IDispatch interface pointer if instantiated
|
||||
*/
|
||||
IDispatch CreateInstance(in string className, in PRBool testScriptability);
|
||||
IDispatch CreateInstance(in astring className, in PRBool testScriptability);
|
||||
};
|
||||
|
||||
%{ C++
|
||||
|
|
|
@ -125,6 +125,7 @@
|
|||
#define NS_ERROR_XPC_COM_ERROR GENERATE_XPC_FAILURE(55)
|
||||
#define NS_ERROR_XPC_COM_INVALID_CLASS_ID GENERATE_XPC_FAILURE(56)
|
||||
#define NS_ERROR_XPC_COM_CREATE_FAILED GENERATE_XPC_FAILURE(57)
|
||||
#define NS_ERROR_XPC_IDISPATCH_NOT_ENABLED GENERATE_XPC_FAILURE(58)
|
||||
#endif
|
||||
// any new errors here should have an associated entry added in xpc.msg
|
||||
/***************************************************************************/
|
||||
|
|
|
@ -44,42 +44,45 @@
|
|||
|
||||
VARTYPE XPCDispConvert::JSTypeToCOMType(XPCCallContext& ccx, jsval val)
|
||||
{
|
||||
if(JSVAL_IS_STRING(val))
|
||||
if(JSVAL_IS_PRIMITIVE(val))
|
||||
{
|
||||
return VT_BSTR;
|
||||
if(JSVAL_IS_STRING(val))
|
||||
{
|
||||
return VT_BSTR;
|
||||
}
|
||||
if(JSVAL_IS_INT(val))
|
||||
{
|
||||
return VT_I4;
|
||||
}
|
||||
if(JSVAL_IS_DOUBLE(val))
|
||||
{
|
||||
return VT_R8;
|
||||
}
|
||||
if(JSVAL_IS_BOOLEAN(val))
|
||||
{
|
||||
return VT_BOOL;
|
||||
}
|
||||
if(JSVAL_IS_VOID(val))
|
||||
{
|
||||
return VT_EMPTY;
|
||||
}
|
||||
if(JSVAL_IS_NULL(val))
|
||||
{
|
||||
return VT_NULL;
|
||||
}
|
||||
}
|
||||
if(JSVAL_IS_INT(val))
|
||||
{
|
||||
return VT_I4;
|
||||
}
|
||||
if(JSVAL_IS_DOUBLE(val))
|
||||
{
|
||||
return VT_R8;
|
||||
}
|
||||
if(JSVAL_IS_OBJECT(val))
|
||||
else
|
||||
{
|
||||
if(JS_IsArrayObject(ccx, JSVAL_TO_OBJECT(val)))
|
||||
return VT_ARRAY | VT_VARIANT;
|
||||
return VT_DISPATCH;
|
||||
}
|
||||
if(JSVAL_IS_BOOLEAN(val))
|
||||
{
|
||||
return VT_BOOL;
|
||||
}
|
||||
if(JSVAL_IS_VOID(val))
|
||||
{
|
||||
return VT_EMPTY;
|
||||
}
|
||||
if(JSVAL_IS_NULL(val))
|
||||
{
|
||||
return VT_NULL;
|
||||
}
|
||||
NS_ERROR("XPCDispConvert::JSTypeToCOMType was unable to identify the type of the jsval");
|
||||
return VT_EMPTY;
|
||||
}
|
||||
|
||||
JSBool XPCDispConvert::JSArrayToCOMArray(XPCCallContext& ccx, JSObject *obj,
|
||||
VARIANT & var, nsresult& err)
|
||||
VARIANT & var, nsresult& err)
|
||||
{
|
||||
err = NS_OK;
|
||||
jsuint len;
|
||||
|
@ -89,115 +92,264 @@ JSBool XPCDispConvert::JSArrayToCOMArray(XPCCallContext& ccx, JSObject *obj,
|
|||
err = NS_ERROR_XPC_NOT_ENOUGH_ELEMENTS_IN_ARRAY;
|
||||
return PR_FALSE;
|
||||
}
|
||||
// Create the safe array and populate it
|
||||
SAFEARRAY * array = SafeArrayCreateVector(VT_VARIANT, 0, len);
|
||||
for(long index = 0; index < len; ++index)
|
||||
// Create the safe array of variants and populate it
|
||||
SAFEARRAY * array = nsnull;
|
||||
VARIANT* varArray = 0;
|
||||
for(jsuint index = 0; index < len; ++index)
|
||||
{
|
||||
_variant_t arrayVar;
|
||||
jsval val;
|
||||
if(JS_GetElement(ccx, obj, index, &val) &&
|
||||
JSToCOM(ccx, val, arrayVar, err))
|
||||
if(JS_GetElement(ccx, obj, index, &val))
|
||||
{
|
||||
SafeArrayPutElement(array, &index, &arrayVar);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(err == NS_OK)
|
||||
err = NS_ERROR_FAILURE;
|
||||
// This cleans up the elements as well
|
||||
SafeArrayDestroyData(array);
|
||||
return JS_FALSE;
|
||||
if (!JSVAL_IS_VOID(val))
|
||||
{
|
||||
if (!array)
|
||||
{
|
||||
// Create an array that starts at index, and has len
|
||||
// elements
|
||||
array = SafeArrayCreateVector(VT_VARIANT, index, len - index);
|
||||
if (!array)
|
||||
{
|
||||
err = NS_ERROR_OUT_OF_MEMORY;
|
||||
return JS_FALSE;
|
||||
}
|
||||
if (FAILED(SafeArrayAccessData(array, NS_REINTERPRET_CAST(void**,&varArray))))
|
||||
{
|
||||
err = NS_ERROR_FAILURE;
|
||||
return JS_FALSE;
|
||||
}
|
||||
}
|
||||
if (!JSToCOM(ccx, val, *varArray, err))
|
||||
{
|
||||
SafeArrayUnaccessData(array);
|
||||
err = NS_ERROR_FAILURE;
|
||||
// This cleans up the elements as well
|
||||
SafeArrayDestroyData(array);
|
||||
return JS_FALSE;
|
||||
}
|
||||
}
|
||||
if (varArray)
|
||||
++varArray;
|
||||
}
|
||||
}
|
||||
SafeArrayUnaccessData(array);
|
||||
var.vt = VT_ARRAY | VT_VARIANT;
|
||||
var.parray = array;
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
#define XPC_ASSIGN(src, dest, data) *dest.p##data = src.data
|
||||
|
||||
/**
|
||||
* Copies a variant to a by ref variant
|
||||
* NOTE: This does not perform any reference counting. It simply does
|
||||
* a copy of the values, it's up to the caller to manage any ownership issues
|
||||
* @param src the variant to be copied
|
||||
* @param dest the destination for the copy
|
||||
* @return JS_TRUE if the copy was performed JS_FALSE if it failed
|
||||
*/
|
||||
inline
|
||||
JSBool xpc_CopyVariantByRef(VARIANT & src, VARIANT & dest)
|
||||
{
|
||||
VARIANT temp;
|
||||
VARTYPE vt = dest.vt & ~(VT_BYREF);
|
||||
if(vt != src.vt)
|
||||
{
|
||||
// TODO: This fails more than I had hoped, we may want to
|
||||
// add some logic to handle more conversions
|
||||
if(FAILED(VariantChangeType(&temp, &src, VARIANT_ALPHABOOL, vt)))
|
||||
{
|
||||
return JS_FALSE;
|
||||
}
|
||||
}
|
||||
else
|
||||
temp = src;
|
||||
switch (vt)
|
||||
{
|
||||
case VT_I2:
|
||||
{
|
||||
XPC_ASSIGN(temp, dest, iVal);
|
||||
}
|
||||
break;
|
||||
case VT_I4:
|
||||
{
|
||||
XPC_ASSIGN(temp, dest, lVal);
|
||||
}
|
||||
break;
|
||||
case VT_R4:
|
||||
{
|
||||
XPC_ASSIGN(temp, dest, fltVal);
|
||||
}
|
||||
break;
|
||||
case VT_R8:
|
||||
{
|
||||
XPC_ASSIGN(temp, dest, dblVal);
|
||||
}
|
||||
break;
|
||||
case VT_CY:
|
||||
{
|
||||
XPC_ASSIGN(temp, dest, cyVal);
|
||||
}
|
||||
break;
|
||||
case VT_DATE:
|
||||
{
|
||||
XPC_ASSIGN(temp, dest, date);
|
||||
}
|
||||
break;
|
||||
case VT_BSTR:
|
||||
{
|
||||
XPC_ASSIGN(temp, dest, bstrVal);
|
||||
}
|
||||
break;
|
||||
case VT_DISPATCH:
|
||||
{
|
||||
XPC_ASSIGN(temp, dest, pdispVal);
|
||||
}
|
||||
break;
|
||||
case VT_ERROR:
|
||||
{
|
||||
XPC_ASSIGN(temp, dest, scode);
|
||||
}
|
||||
break;
|
||||
case VT_BOOL:
|
||||
{
|
||||
XPC_ASSIGN(temp, dest, boolVal);
|
||||
}
|
||||
break;
|
||||
case VT_VARIANT:
|
||||
{
|
||||
// Not Supported right now
|
||||
return JS_FALSE;
|
||||
}
|
||||
break;
|
||||
case VT_I1:
|
||||
{
|
||||
XPC_ASSIGN(temp, dest, cVal);
|
||||
}
|
||||
break;
|
||||
case VT_UI1:
|
||||
{
|
||||
XPC_ASSIGN(temp, dest, bVal);
|
||||
}
|
||||
break;
|
||||
case VT_UI2:
|
||||
{
|
||||
XPC_ASSIGN(temp, dest, iVal);
|
||||
}
|
||||
break;
|
||||
case VT_UI4:
|
||||
{
|
||||
XPC_ASSIGN(temp, dest, uiVal);
|
||||
}
|
||||
break;
|
||||
case VT_INT:
|
||||
{
|
||||
XPC_ASSIGN(temp, dest, intVal);
|
||||
}
|
||||
break;
|
||||
case VT_UINT:
|
||||
{
|
||||
XPC_ASSIGN(temp, dest, uintVal);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
{
|
||||
return JS_FALSE;
|
||||
}
|
||||
}
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JSBool XPCDispConvert::JSToCOM(XPCCallContext& ccx,
|
||||
jsval src,
|
||||
VARIANT & dest,
|
||||
nsresult& err)
|
||||
jsval src,
|
||||
VARIANT & dest,
|
||||
nsresult& err,
|
||||
JSBool isByRef)
|
||||
{
|
||||
err = NS_OK;
|
||||
if(JSVAL_IS_STRING(src))
|
||||
VARIANT byRefVariant;
|
||||
VARIANT * varDest = isByRef ? &byRefVariant : &dest;
|
||||
varDest->vt = JSTypeToCOMType(ccx, src);
|
||||
switch (varDest->vt)
|
||||
{
|
||||
JSString* str = JSVAL_TO_STRING(src);
|
||||
if(!str)
|
||||
case VT_BSTR:
|
||||
{
|
||||
JSString* str = JSVAL_TO_STRING(src);
|
||||
jschar * chars = JS_GetStringChars(str);
|
||||
if(!chars)
|
||||
{
|
||||
err = NS_ERROR_XPC_BAD_CONVERT_NATIVE;
|
||||
// Avoid cleaning up garabage
|
||||
varDest->vt = VT_EMPTY;
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
CComBSTR val(JS_GetStringLength(str), chars);
|
||||
varDest->bstrVal = val.Detach();
|
||||
}
|
||||
break;
|
||||
case VT_I4:
|
||||
{
|
||||
varDest->vt = VT_I4;
|
||||
varDest->lVal = JSVAL_TO_INT(src);
|
||||
}
|
||||
break;
|
||||
case VT_R8:
|
||||
{
|
||||
varDest->vt = VT_R8;
|
||||
varDest->dblVal = *JSVAL_TO_DOUBLE(src);
|
||||
}
|
||||
break;
|
||||
case VT_EMPTY:
|
||||
case VT_NULL:
|
||||
break;
|
||||
case VT_ARRAY | VT_VARIANT:
|
||||
{
|
||||
JSObject * obj = JSVAL_TO_OBJECT(src);
|
||||
return JSArrayToCOMArray(ccx, obj, *varDest, err);
|
||||
}
|
||||
break;
|
||||
case VT_DISPATCH:
|
||||
{
|
||||
JSObject * obj = JSVAL_TO_OBJECT(src);
|
||||
// We only handle JS Objects that are IDispatch objects
|
||||
if(!XPCConvert::GetNativeInterfaceFromJSObject(
|
||||
ccx, (void**)&varDest->pdispVal, obj, &NSID_IDISPATCH,&err))
|
||||
{
|
||||
// Avoid cleaning up garabage
|
||||
varDest->vt = VT_EMPTY;
|
||||
return JS_FALSE;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case VT_BOOL:
|
||||
{
|
||||
varDest->boolVal = JSVAL_TO_BOOLEAN(src) ? VARIANT_TRUE : VARIANT_FALSE;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
{
|
||||
NS_ERROR("This is out of synce with XPCDispConvert::JSTypeToCOMType");
|
||||
err = NS_ERROR_XPC_BAD_CONVERT_NATIVE;
|
||||
// Avoid cleaning up garabage
|
||||
varDest->vt = VT_EMPTY;
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
jschar * chars = JS_GetStringChars(str);
|
||||
if(!chars)
|
||||
break;
|
||||
}
|
||||
if(isByRef)
|
||||
{
|
||||
if (!xpc_CopyVariantByRef(byRefVariant, dest))
|
||||
{
|
||||
err = NS_ERROR_XPC_BAD_CONVERT_NATIVE;
|
||||
return JS_FALSE;
|
||||
// Avoid cleaning up garabage
|
||||
dest.vt = VT_EMPTY;
|
||||
}
|
||||
|
||||
CComBSTR val(chars);
|
||||
dest.vt = VT_BSTR;
|
||||
dest.bstrVal = val.Detach();
|
||||
}
|
||||
else if(JSVAL_IS_INT(src))
|
||||
{
|
||||
dest.vt = VT_I4;
|
||||
dest.lVal = JSVAL_TO_INT(src);
|
||||
}
|
||||
else if(JSVAL_IS_DOUBLE(src))
|
||||
{
|
||||
dest.vt = VT_R8;
|
||||
dest.dblVal = *JSVAL_TO_DOUBLE(src);
|
||||
}
|
||||
else if(JSVAL_IS_VOID(src))
|
||||
{
|
||||
dest.vt = VT_EMPTY;
|
||||
}
|
||||
else if(JSVAL_IS_NULL(src))
|
||||
{
|
||||
dest.vt = VT_EMPTY;
|
||||
}
|
||||
else if(JSVAL_IS_OBJECT(src))
|
||||
{
|
||||
JSObject * obj = JSVAL_TO_OBJECT(src);
|
||||
if(JS_IsArrayObject(ccx, obj))
|
||||
{
|
||||
return JSArrayToCOMArray(ccx, obj, dest, err);
|
||||
}
|
||||
else
|
||||
{
|
||||
// only wrap JSObjects
|
||||
IUnknown * pUnknown;
|
||||
XPCConvert::JSObject2NativeInterface(
|
||||
ccx,
|
||||
(void**)&pUnknown,
|
||||
obj,
|
||||
&NSID_IDISPATCH,
|
||||
nsnull,
|
||||
&err);
|
||||
dest.vt = VT_DISPATCH;
|
||||
pUnknown->QueryInterface(IID_IDispatch,
|
||||
NS_REINTERPRET_CAST(void**,
|
||||
&dest.pdispVal));
|
||||
}
|
||||
}
|
||||
else if(JSVAL_IS_BOOLEAN(src))
|
||||
{
|
||||
dest.vt = VT_BOOL;
|
||||
dest.boolVal = JSVAL_TO_BOOLEAN(src);
|
||||
}
|
||||
else // Unknown type
|
||||
{
|
||||
err = NS_ERROR_XPC_BAD_CONVERT_NATIVE;
|
||||
return JS_FALSE;
|
||||
}
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JSBool XPCDispConvert::COMArrayToJSArray(XPCCallContext& ccx,
|
||||
const _variant_t & src,
|
||||
jsval & dest, nsresult& err)
|
||||
const VARIANT & src,
|
||||
jsval & dest, nsresult& err)
|
||||
{
|
||||
err = NS_OK;
|
||||
// We only support one dimensional arrays for now
|
||||
|
@ -206,33 +358,45 @@ JSBool XPCDispConvert::COMArrayToJSArray(XPCCallContext& ccx,
|
|||
err = NS_ERROR_FAILURE;
|
||||
return JS_FALSE;
|
||||
}
|
||||
long size;
|
||||
HRESULT hr = SafeArrayGetUBound(src.parray, 1, &size);
|
||||
if(FAILED(hr))
|
||||
// Get the upper bound;
|
||||
long ubound;
|
||||
if(FAILED(SafeArrayGetUBound(src.parray, 1, &ubound)))
|
||||
{
|
||||
err = NS_ERROR_FAILURE;
|
||||
return JS_FALSE;
|
||||
}
|
||||
JSObject * array = JS_NewArrayObject(ccx, size, nsnull);
|
||||
// Get the lower bound
|
||||
long lbound;
|
||||
if(FAILED(SafeArrayGetLBound(src.parray, 1, &lbound)))
|
||||
{
|
||||
err = NS_ERROR_FAILURE;
|
||||
return JS_FALSE;
|
||||
}
|
||||
// Create the JS Array
|
||||
JSObject * array = JS_NewArrayObject(ccx, ubound - lbound + 1, nsnull);
|
||||
if(!array)
|
||||
{
|
||||
err = NS_ERROR_OUT_OF_MEMORY;
|
||||
return JS_FALSE;
|
||||
}
|
||||
// Devine the type of our array
|
||||
_variant_t var;
|
||||
VARTYPE vartype;
|
||||
if((src.vt & VT_ARRAY) != 0)
|
||||
{
|
||||
var.vt = src.vt & ~VT_ARRAY;
|
||||
vartype = src.vt & ~VT_ARRAY;
|
||||
}
|
||||
else // This was maybe a VT_SAFEARRAY
|
||||
{
|
||||
SafeArrayGetVartype(src.parray, &var.vt);
|
||||
if(FAILED(SafeArrayGetVartype(src.parray, &vartype)))
|
||||
return JS_FALSE;
|
||||
}
|
||||
jsval val;
|
||||
for(long index = 0; index <= size; ++index)
|
||||
for(long index = lbound; index <= ubound; ++index)
|
||||
{
|
||||
hr = SafeArrayGetElement(src.parray, &index, &var.byref);
|
||||
if(FAILED(hr))
|
||||
// Devine the type of our array
|
||||
_variant_t var;
|
||||
var.vt = vartype;
|
||||
if(FAILED(SafeArrayGetElement(src.parray, &index, &var.byref)))
|
||||
{
|
||||
err = NS_ERROR_FAILURE;
|
||||
return JS_FALSE;
|
||||
|
@ -246,110 +410,101 @@ JSBool XPCDispConvert::COMArrayToJSArray(XPCCallContext& ccx,
|
|||
}
|
||||
|
||||
/**
|
||||
* Converts an integer number to a jsval
|
||||
* @param cx a JS context
|
||||
* @param value the integer to be converted
|
||||
* @return the converted jsval
|
||||
* Converts a string to a jsval
|
||||
* @param cx the JSContext
|
||||
* @param str the unicode string to be converted
|
||||
* @param len the length of the string being converted
|
||||
* @return the jsval representing the string
|
||||
*/
|
||||
inline
|
||||
jsval NumberToJSVal(JSContext* cx, int value)
|
||||
jsval StringToJSVal(JSContext* cx, const PRUnichar * str, PRUint32 len)
|
||||
{
|
||||
jsval val;
|
||||
if(INT_FITS_IN_JSVAL(value))
|
||||
val = INT_TO_JSVAL(value);
|
||||
else
|
||||
{
|
||||
if(!JS_NewDoubleValue(cx, NS_STATIC_CAST(jsdouble,value), &val))
|
||||
val = JSVAL_ZERO;
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts an floating point number to a jsval
|
||||
* @param cx a JS context
|
||||
* @param value the floating point number to be converted
|
||||
* @return the converted jsval
|
||||
*/
|
||||
inline
|
||||
jsval NumberToJSVal(JSContext* cx, double value)
|
||||
{
|
||||
jsval val;
|
||||
if(JS_NewDoubleValue(cx, NS_STATIC_CAST(jsdouble, value), &val))
|
||||
return val;
|
||||
else
|
||||
return JSVAL_ZERO;
|
||||
}
|
||||
|
||||
inline
|
||||
jsval StringToJSVal(JSContext* cx, const PRUnichar * str)
|
||||
{
|
||||
JSString * s = JS_NewUCStringCopyZ(cx, str);
|
||||
if (s)
|
||||
JSString * s = JS_NewUCStringCopyN(cx, str, len);
|
||||
if(s)
|
||||
return STRING_TO_JSVAL(s);
|
||||
else
|
||||
return JSVAL_NULL;
|
||||
}
|
||||
|
||||
JSBool XPCDispConvert::COMToJS(XPCCallContext& ccx, const _variant_t & src,
|
||||
jsval& dest, nsresult& err)
|
||||
|
||||
#define VALUE(val) (isPtr ? *src.p##val : src.val)
|
||||
JSBool XPCDispConvert::COMToJS(XPCCallContext& ccx, const VARIANT& src,
|
||||
jsval& dest, nsresult& err)
|
||||
{
|
||||
err = NS_OK;
|
||||
if(src.vt & VT_ARRAY || src.vt == VT_SAFEARRAY)
|
||||
{
|
||||
return COMArrayToJSArray(ccx, src, dest, err);
|
||||
}
|
||||
PRBool isPtr = src.vt & VT_BYREF;
|
||||
switch (src.vt & ~(VT_BYREF))
|
||||
{
|
||||
case VT_BSTR:
|
||||
case VT_UINT:
|
||||
{
|
||||
if(src.vt & VT_BYREF)
|
||||
dest = StringToJSVal(ccx, *src.pbstrVal);
|
||||
else
|
||||
dest = StringToJSVal(ccx, src.bstrVal);
|
||||
return JS_NewNumberValue(ccx, VALUE(uintVal), &dest);
|
||||
}
|
||||
break;
|
||||
case VT_UI4:
|
||||
{
|
||||
return JS_NewNumberValue(ccx, VALUE(ulVal), &dest);
|
||||
}
|
||||
break;
|
||||
case VT_INT:
|
||||
{
|
||||
return JS_NewNumberValue(ccx, VALUE(intVal), &dest);
|
||||
}
|
||||
break;
|
||||
case VT_I4:
|
||||
{
|
||||
dest = NumberToJSVal(ccx, src.lVal);
|
||||
return JS_NewNumberValue(ccx, VALUE(lVal), &dest);
|
||||
}
|
||||
break;
|
||||
case VT_UI1:
|
||||
{
|
||||
dest = INT_TO_JSVAL(src.bVal);
|
||||
dest = INT_TO_JSVAL(VALUE(bVal));
|
||||
}
|
||||
break;
|
||||
case VT_I1:
|
||||
{
|
||||
dest = INT_TO_JSVAL(VALUE(cVal));
|
||||
}
|
||||
break;
|
||||
case VT_UI2:
|
||||
{
|
||||
dest = INT_TO_JSVAL(VALUE(uiVal));
|
||||
}
|
||||
break;
|
||||
case VT_I2:
|
||||
{
|
||||
dest = INT_TO_JSVAL(src.iVal);
|
||||
dest = INT_TO_JSVAL(VALUE(iVal));
|
||||
}
|
||||
break;
|
||||
case VT_R4:
|
||||
{
|
||||
dest = NumberToJSVal(ccx, src.fltVal);
|
||||
return JS_NewNumberValue(ccx, VALUE(fltVal), &dest);
|
||||
}
|
||||
break;
|
||||
case VT_R8:
|
||||
{
|
||||
dest = NumberToJSVal(ccx, src.dblVal);
|
||||
return JS_NewNumberValue(ccx, VALUE(dblVal), &dest);
|
||||
}
|
||||
break;
|
||||
case VT_BOOL:
|
||||
{
|
||||
dest = BOOLEAN_TO_JSVAL(src.boolVal);
|
||||
dest = BOOLEAN_TO_JSVAL(VALUE(boolVal) != VARIANT_FALSE ? JS_TRUE : JS_FALSE);
|
||||
}
|
||||
break;
|
||||
case VT_DISPATCH:
|
||||
{
|
||||
XPCDispObject::WrapIDispatch(src.pdispVal, ccx,
|
||||
XPCDispObject::WrapIDispatch(VALUE(pdispVal), ccx,
|
||||
JS_GetGlobalObject(ccx), &dest);
|
||||
}
|
||||
break;
|
||||
case VT_DATE:
|
||||
{
|
||||
_variant_t var(src);
|
||||
_bstr_t bstr(var);
|
||||
dest = StringToJSVal(ccx, NS_STATIC_CAST(const PRUnichar*, bstr));
|
||||
// Convert date to string and frees it when we're done
|
||||
_bstr_t str(src);
|
||||
dest = StringToJSVal(ccx, str, str.length());
|
||||
}
|
||||
break;
|
||||
case VT_EMPTY:
|
||||
|
@ -357,22 +512,41 @@ JSBool XPCDispConvert::COMToJS(XPCCallContext& ccx, const _variant_t & src,
|
|||
dest = JSVAL_NULL;
|
||||
}
|
||||
break;
|
||||
case VT_ERROR:
|
||||
{
|
||||
return JS_NewNumberValue(ccx, VALUE(scode), &dest);
|
||||
}
|
||||
break;
|
||||
case VT_CY:
|
||||
{
|
||||
return JS_NewNumberValue(
|
||||
ccx,
|
||||
NS_STATIC_CAST(double,
|
||||
isPtr ? src.pcyVal->int64 :
|
||||
src.cyVal.int64) / 100.0,
|
||||
&dest);
|
||||
}
|
||||
break;
|
||||
/**
|
||||
* Currently unsupported conversion types
|
||||
*/
|
||||
case VT_ERROR:
|
||||
case VT_CY:
|
||||
case VT_UNKNOWN:
|
||||
case VT_I1:
|
||||
case VT_UI2:
|
||||
case VT_UI4:
|
||||
case VT_INT:
|
||||
case VT_UINT:
|
||||
default:
|
||||
{
|
||||
err = NS_ERROR_XPC_BAD_CONVERT_JS;
|
||||
return JS_FALSE;
|
||||
// Last ditch effort to convert to string
|
||||
if(FAILED(VariantChangeType(NS_CONST_CAST(VARIANT*,&src),
|
||||
NS_CONST_CAST(VARIANT*,&src),
|
||||
VARIANT_ALPHABOOL, VT_BSTR)))
|
||||
{
|
||||
err = NS_ERROR_XPC_BAD_CONVERT_JS;
|
||||
return JS_FALSE;
|
||||
}
|
||||
} // Fall through on success
|
||||
case VT_BSTR:
|
||||
{
|
||||
dest = StringToJSVal(ccx, VALUE(bstrVal), SysStringLen(VALUE(bstrVal)));
|
||||
}
|
||||
break;
|
||||
}
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
|
|
@ -334,7 +334,7 @@ void XPCDispNameArray::SetSize(PRUint32 size)
|
|||
{
|
||||
NS_ASSERTION(mCount == 0, "SetSize called more than once");
|
||||
mCount = size;
|
||||
mNames = (size ? new nsCString[size] : 0);
|
||||
mNames = (size ? new nsString[size] : 0);
|
||||
}
|
||||
|
||||
inline
|
||||
|
@ -344,27 +344,27 @@ PRUint32 XPCDispNameArray::GetSize() const
|
|||
}
|
||||
|
||||
inline
|
||||
void XPCDispNameArray::SetName(DISPID dispid, nsACString const & name)
|
||||
void XPCDispNameArray::SetName(DISPID dispid, nsAString const & name)
|
||||
{
|
||||
NS_ASSERTION(dispid <= mCount, "Array bounds error in XPCDispNameArray::SetName");
|
||||
mNames[dispid - 1] = name;
|
||||
}
|
||||
|
||||
inline
|
||||
nsCString XPCDispNameArray::GetName(DISPID dispid) const
|
||||
const nsAString & XPCDispNameArray::GetName(DISPID dispid) const
|
||||
{
|
||||
NS_ASSERTION(dispid <= mCount, "Array bounds error in XPCDispNameArray::Get");
|
||||
if(dispid > 0)
|
||||
return mNames[dispid - 1];
|
||||
return nsCString();
|
||||
return sEmpty;
|
||||
}
|
||||
|
||||
inline
|
||||
DISPID XPCDispNameArray::Find(const nsACString &target) const
|
||||
DISPID XPCDispNameArray::Find(const nsAString &target) const
|
||||
{
|
||||
for(PRUint32 index = 0; index < mCount; ++index)
|
||||
{
|
||||
if(mNames[index] == target)
|
||||
if(mNames[index].Equals(target))
|
||||
return NS_STATIC_CAST(DISPID, index + 1);
|
||||
}
|
||||
return 0;
|
||||
|
@ -429,7 +429,7 @@ PRUint32 XPCDispTypeInfo::FuncDescArray::Length() const
|
|||
}
|
||||
|
||||
inline
|
||||
nsCString XPCDispTypeInfo::GetNameForDispID(DISPID dispID)
|
||||
const nsAString & XPCDispTypeInfo::GetNameForDispID(DISPID dispID)
|
||||
{
|
||||
return mNameArray.GetName(dispID);
|
||||
}
|
||||
|
@ -486,7 +486,7 @@ void XPCDispJSPropertyInfo::SetSetter()
|
|||
}
|
||||
|
||||
inline
|
||||
nsACString const & XPCDispJSPropertyInfo::GetName() const
|
||||
const nsAString & XPCDispJSPropertyInfo::GetName() const
|
||||
{
|
||||
return mName;
|
||||
}
|
||||
|
@ -501,31 +501,31 @@ XPCDispJSPropertyInfo::property_type XPCDispJSPropertyInfo::PropertyType() const
|
|||
// GUID/nsIID/nsCID conversion functions
|
||||
|
||||
inline
|
||||
const nsIID & XPCDispGUID2nsIID(const struct _GUID & guid)
|
||||
const nsIID & XPCDispIID2nsIID(const IID & iid)
|
||||
{
|
||||
NS_ASSERTION(sizeof(struct _GUID) == sizeof(nsIID), "GUID is not the same as nsIID");
|
||||
return NS_REINTERPRET_CAST(const nsIID &,guid);
|
||||
NS_ASSERTION(sizeof(IID) == sizeof(nsIID), "IID is not the same size as nsIID");
|
||||
return NS_REINTERPRET_CAST(const nsIID &,iid);
|
||||
}
|
||||
|
||||
inline
|
||||
const GUID & XPCDispIID2GUID(const nsIID & iid)
|
||||
const IID & XPCDispIID2IID(const nsIID & iid)
|
||||
{
|
||||
NS_ASSERTION(sizeof(struct _GUID) == sizeof(nsIID), "GUID is not the same as IID");
|
||||
return NS_REINTERPRET_CAST(const struct _GUID &, iid);
|
||||
NS_ASSERTION(sizeof(IID) == sizeof(nsIID), "IID is not the same size as nsIID");
|
||||
return NS_REINTERPRET_CAST(const IID &, iid);
|
||||
}
|
||||
|
||||
inline
|
||||
const nsCID & XPCDispGUID2nsCID(const struct _GUID & guid)
|
||||
const nsCID & XPCDispCLSID2nsCID(const CLSID & clsid)
|
||||
{
|
||||
NS_ASSERTION(sizeof(struct _GUID) == sizeof(nsCID), "GUID is not the same as nsCID");
|
||||
return NS_REINTERPRET_CAST(const nsCID &,guid);
|
||||
NS_ASSERTION(sizeof(CLSID) == sizeof(nsCID), "CLSID is not the same size as nsCID");
|
||||
return NS_REINTERPRET_CAST(const nsCID &,clsid);
|
||||
}
|
||||
|
||||
inline
|
||||
const GUID & XPCDispCID2GUID(const nsCID & iid)
|
||||
const CLSID & XPCDispnsCID2CLSID(const nsCID & clsid)
|
||||
{
|
||||
NS_ASSERTION(sizeof(struct _GUID) == sizeof(nsCID), "GUID is not the same as IID");
|
||||
return NS_REINTERPRET_CAST(const struct _GUID &, iid);
|
||||
NS_ASSERTION(sizeof(CLSID) == sizeof(nsCID), "CLSID is not the same size as nsCID");
|
||||
return NS_REINTERPRET_CAST(const CLSID &, clsid);
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
|
@ -537,6 +537,14 @@ void XPCDispParams::SetNamedPropID()
|
|||
mDispParams.rgdispidNamedArgs = &mPropID;
|
||||
mDispParams.cNamedArgs = 1;
|
||||
}
|
||||
/*
|
||||
inline
|
||||
const VARIANT & XPCDispParams::GetParamRef(PRUint32 index) const
|
||||
{
|
||||
NS_ASSERTION(index < mDispParams.cArgs, "XPCDispParams::GetParam bounds error");
|
||||
return mDispParams.rgvarg[mDispParams.cArgs - index - 1];
|
||||
}
|
||||
*/
|
||||
|
||||
inline
|
||||
VARIANT & XPCDispParams::GetParamRef(PRUint32 index)
|
||||
|
@ -555,7 +563,7 @@ inline
|
|||
void * XPCDispParams::GetOutputBuffer(PRUint32 index)
|
||||
{
|
||||
NS_ASSERTION(index < mDispParams.cArgs, "XPCDispParams::GetParam bounds error");
|
||||
return mVarBuffer + VARIANT_UNION_SIZE * index;
|
||||
return mRefBuffer + sizeof(VARIANT) * index;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
|
@ -579,14 +587,19 @@ JSBool XPCDispParamPropJSClass::Invoke(XPCCallContext& ccx,
|
|||
* @return a C string (Does not need to be freed)
|
||||
*/
|
||||
inline
|
||||
const char * xpc_JSString2Char(JSContext * cx, jsval val)
|
||||
jschar * xpc_JSString2String(JSContext * cx, jsval val, PRUint32 * len = 0)
|
||||
{
|
||||
JSString* str = JS_ValueToString(cx, val);
|
||||
if(!str)
|
||||
return nsnull;
|
||||
|
||||
return JS_GetStringBytes(str);
|
||||
|
||||
JSString* str = JSVAL_IS_STRING(val) ? JSVAL_TO_STRING(val) :
|
||||
JS_ValueToString(cx, val);
|
||||
if(str)
|
||||
{
|
||||
if(len)
|
||||
*len = JS_GetStringLength(str);
|
||||
return JS_GetStringChars(str);
|
||||
}
|
||||
if(len)
|
||||
*len = 0;
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -41,7 +41,6 @@
|
|||
*/
|
||||
|
||||
#include "xpcprivate.h"
|
||||
#include <MBSTRING.H>
|
||||
|
||||
/**
|
||||
* Is this function reflectable
|
||||
|
@ -82,19 +81,16 @@ PRUint32 GetReflectableCount(ITypeInfo * pTypeInfo, PRUint32 members)
|
|||
|
||||
XPCDispInterface* XPCDispInterface::NewInstance(JSContext* cx, nsISupports * pIface)
|
||||
{
|
||||
IDispatch * pDispatch;
|
||||
HRESULT hr = NS_REINTERPRET_CAST(IUnknown*,pIface)->QueryInterface(IID_IDispatch, (PVOID*)&pDispatch);
|
||||
CComQIPtr<IDispatch> pDispatch(NS_REINTERPRET_CAST(IUnknown*,pIface));
|
||||
|
||||
if(SUCCEEDED(hr) && pDispatch)
|
||||
if(pDispatch)
|
||||
{
|
||||
unsigned int count;
|
||||
hr = pDispatch->GetTypeInfoCount(&count);
|
||||
HRESULT hr = pDispatch->GetTypeInfoCount(&count);
|
||||
if(SUCCEEDED(hr) && count > 0)
|
||||
{
|
||||
ITypeInfo* pPtr;
|
||||
hr = pDispatch->GetTypeInfo(0,LOCALE_SYSTEM_DEFAULT, &pPtr);
|
||||
CComPtr<ITypeInfo> pTypeInfo;
|
||||
pTypeInfo.Attach(pPtr);
|
||||
hr = pDispatch->GetTypeInfo(0,LOCALE_SYSTEM_DEFAULT, &pTypeInfo);
|
||||
if(SUCCEEDED(hr))
|
||||
{
|
||||
TYPEATTR * attr;
|
||||
|
@ -144,7 +140,7 @@ void ConvertInvokeKind(INVOKEKIND invokeKind, XPCDispInterface::Member & member)
|
|||
}
|
||||
}
|
||||
|
||||
void XPCDispInterface::InspectIDispatch(JSContext * cx, ITypeInfo * pTypeInfo, PRUint32 members)
|
||||
PRBool XPCDispInterface::InspectIDispatch(JSContext * cx, ITypeInfo * pTypeInfo, PRUint32 members)
|
||||
{
|
||||
HRESULT hResult;
|
||||
DISPID lastDispID = 0;
|
||||
|
@ -154,8 +150,8 @@ void XPCDispInterface::InspectIDispatch(JSContext * cx, ITypeInfo * pTypeInfo, P
|
|||
for(PRUint32 index = 0; index < members; index++ )
|
||||
{
|
||||
FUNCDESC* pFuncDesc;
|
||||
hResult = pTypeInfo->GetFuncDesc( index, &pFuncDesc );
|
||||
if(SUCCEEDED( hResult ))
|
||||
hResult = pTypeInfo->GetFuncDesc(index, &pFuncDesc );
|
||||
if(SUCCEEDED(hResult))
|
||||
{
|
||||
PRBool release = PR_TRUE;
|
||||
if(IsReflectable(pFuncDesc))
|
||||
|
@ -171,10 +167,14 @@ void XPCDispInterface::InspectIDispatch(JSContext * cx, ITypeInfo * pTypeInfo, P
|
|||
1,
|
||||
&nameCount)))
|
||||
{
|
||||
JSString* str = JS_InternUCString(cx, name);
|
||||
JSString* str = JS_InternUCStringN(cx, name, ::SysStringLen(name));
|
||||
::SysFreeString(name);
|
||||
if(!str)
|
||||
return PR_FALSE;
|
||||
// Initialize
|
||||
pInfo = new (pInfo) Member;
|
||||
if(!pInfo)
|
||||
return PR_FALSE;
|
||||
pInfo->SetName(STRING_TO_JSVAL(str));
|
||||
lastDispID = pFuncDesc->memid;
|
||||
pInfo->ResetType();
|
||||
|
@ -198,6 +198,7 @@ void XPCDispInterface::InspectIDispatch(JSContext * cx, ITypeInfo * pTypeInfo, P
|
|||
}
|
||||
}
|
||||
}
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -211,11 +212,13 @@ void XPCDispInterface::InspectIDispatch(JSContext * cx, ITypeInfo * pTypeInfo, P
|
|||
inline
|
||||
PRBool CaseInsensitiveCompare(XPCCallContext& ccx, const PRUnichar* lhs, size_t lhsLength, jsval rhs)
|
||||
{
|
||||
if(lhsLength == 0)
|
||||
return PR_FALSE;
|
||||
size_t rhsLength;
|
||||
PRUnichar* rhsString = xpc_JSString2PRUnichar(ccx, rhs, &rhsLength);
|
||||
return rhsString &&
|
||||
lhsLength == rhsLength &&
|
||||
_wcsnicmp(lhs, rhsString, lhsLength * sizeof(PRUnichar)) == 0;
|
||||
_wcsnicmp(lhs, rhsString, lhsLength) == 0;
|
||||
}
|
||||
|
||||
const XPCDispInterface::Member* XPCDispInterface::FindMemberCI(XPCCallContext& ccx, jsval name) const
|
||||
|
|
|
@ -45,17 +45,11 @@
|
|||
/**
|
||||
* This is COM's IDispatch IID, but in XPCOM's nsID type
|
||||
*/
|
||||
nsID NSID_IDISPATCH = { 0x00020400, 0x0000, 0x0000, { 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46 } };
|
||||
|
||||
/**
|
||||
* Need this for ATL stuff
|
||||
* We should look into the possiblity of removing this. It would be nice to
|
||||
* break the ties to ATL all together at some point
|
||||
*/
|
||||
CComModule _Module;
|
||||
const nsID NSID_IDISPATCH = { 0x00020400, 0x0000, 0x0000, { 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46 } };
|
||||
|
||||
PRBool
|
||||
XPCDispObject::WrapIDispatch(IDispatch *pDispatch, JSContext *cx, JSObject *obj, jsval *rval)
|
||||
XPCDispObject::WrapIDispatch(IDispatch *pDispatch, XPCCallContext &ccx,
|
||||
JSObject *obj, jsval *rval)
|
||||
{
|
||||
if(!pDispatch)
|
||||
{
|
||||
|
@ -64,10 +58,10 @@ XPCDispObject::WrapIDispatch(IDispatch *pDispatch, JSContext *cx, JSObject *obj,
|
|||
|
||||
// Wrap the desired COM object
|
||||
nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
|
||||
nsresult rv = nsXPConnect::GetXPConnect()->WrapNative(cx, obj,
|
||||
NS_REINTERPRET_CAST(nsISupports*, pDispatch),
|
||||
NSID_IDISPATCH, getter_AddRefs(holder));
|
||||
if(FAILED(rv) || !holder)
|
||||
nsresult rv = ccx.GetXPConnect()->WrapNative(
|
||||
ccx, obj, NS_REINTERPRET_CAST(nsISupports*, pDispatch), NSID_IDISPATCH,
|
||||
getter_AddRefs(holder));
|
||||
if(NS_FAILED(rv) || !holder)
|
||||
{
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
@ -84,14 +78,14 @@ XPCDispObject::WrapIDispatch(IDispatch *pDispatch, JSContext *cx, JSObject *obj,
|
|||
* @param the class ID of the COM object to be created
|
||||
* @return true if it has the category
|
||||
*/
|
||||
static PRBool HasSafeScriptingCategory(const GUID & classID)
|
||||
static PRBool HasSafeScriptingCategory(const CLSID & classID)
|
||||
{
|
||||
// TODO: probably should look into caching this if this becomes
|
||||
// a performance issue
|
||||
CComPtr<ICatInformation> catInfo;
|
||||
HRESULT hr = catInfo.CoCreateInstance(CLSID_StdComponentCategoriesMgr);
|
||||
// Must fail if we can't open the category manager
|
||||
if(catInfo == NULL)
|
||||
if(!catInfo)
|
||||
return PR_FALSE;
|
||||
|
||||
// See what categories the class implements
|
||||
|
@ -101,6 +95,7 @@ static PRBool HasSafeScriptingCategory(const GUID & classID)
|
|||
|
||||
// Search for matching categories
|
||||
CATID catidNext = GUID_NULL;
|
||||
// Get the next category, and no, I don't know what the 1 is
|
||||
while(enumCATID->Next(1, &catidNext, NULL) == S_OK)
|
||||
{
|
||||
if(::IsEqualCATID(CATID_SafeForScripting, catidNext))
|
||||
|
@ -122,22 +117,17 @@ PRBool ScriptOK(DWORD value)
|
|||
INTERFACESAFE_FOR_UNTRUSTED_DATA);
|
||||
}
|
||||
|
||||
HRESULT XPCDispObject::COMCreateInstance(const char * className, PRBool testScriptability, IDispatch ** result)
|
||||
HRESULT XPCDispObject::COMCreateInstance(BSTR className, PRBool testScriptability, IDispatch ** result)
|
||||
{
|
||||
_bstr_t bstrName(className);
|
||||
CLSID classID;
|
||||
HRESULT hr;
|
||||
// If this looks like a class ID
|
||||
if(className[0] == '{' && className[strlen(className) -1] == '}')
|
||||
if(FAILED(CLSIDFromString(className, &classID)))
|
||||
{
|
||||
hr = CLSIDFromString(bstrName, &classID);
|
||||
hr = CLSIDFromProgID(className, &classID);
|
||||
if(FAILED(hr))
|
||||
return hr;
|
||||
}
|
||||
else // it's probably a prog ID
|
||||
{
|
||||
hr = CLSIDFromProgID(bstrName, &classID);
|
||||
}
|
||||
if(FAILED(hr))
|
||||
return hr;
|
||||
PRBool scriptableOK = PR_TRUE;
|
||||
if(testScriptability)
|
||||
scriptableOK = HasSafeScriptingCategory(classID);
|
||||
|
@ -154,7 +144,7 @@ HRESULT XPCDispObject::COMCreateInstance(const char * className, PRBool testScri
|
|||
{
|
||||
CComQIPtr<IObjectSafety> objSafety(disp);
|
||||
// Didn't have IObjectSafety so we'll bail
|
||||
if(objSafety == 0)
|
||||
if(!objSafety)
|
||||
return E_FAIL;
|
||||
DWORD supported;
|
||||
DWORD state;
|
||||
|
@ -172,18 +162,15 @@ HRESULT XPCDispObject::COMCreateInstance(const char * className, PRBool testScri
|
|||
// static
|
||||
JSBool XPCDispObject::Dispatch(XPCCallContext& ccx, IDispatch * disp,
|
||||
DISPID dispID, CallMode mode,
|
||||
XPCDispParams & params,
|
||||
XPCDispParams * params,
|
||||
jsval* retval,
|
||||
XPCDispInterface::Member * member,
|
||||
XPCJSRuntime* rt)
|
||||
{
|
||||
// avoid deadlock in case the native method blocks somehow
|
||||
AutoJSSuspendRequest req(ccx); // scoped suspend of request
|
||||
|
||||
_variant_t dispResult;
|
||||
jsval val;
|
||||
uintN err;
|
||||
uintN argc = params.GetParamCount();
|
||||
uintN argc = params->GetParamCount();
|
||||
// Figure out what we're doing (getter/setter/method)
|
||||
WORD dispFlags;
|
||||
if(mode == CALL_SETTER)
|
||||
|
@ -198,16 +185,23 @@ JSBool XPCDispObject::Dispatch(XPCCallContext& ccx, IDispatch * disp,
|
|||
{
|
||||
dispFlags = DISPATCH_METHOD;
|
||||
}
|
||||
// call IDispatch's invoke
|
||||
HRESULT invokeResult= disp->Invoke(
|
||||
dispID, // IDispatch ID
|
||||
IID_NULL, // Reserved must be IID_NULL
|
||||
LOCALE_SYSTEM_DEFAULT, // The locale context, use the system's
|
||||
dispFlags, // Type of Invoke call
|
||||
params.GetDispParams(), // Parameters
|
||||
&dispResult, // Where the result is stored
|
||||
nsnull, // Exception information
|
||||
0); // Index of an argument error
|
||||
HRESULT invokeResult;
|
||||
EXCEPINFO exception;
|
||||
// Scope the lock
|
||||
{
|
||||
// avoid deadlock in case the native method blocks somehow
|
||||
AutoJSSuspendRequest req(ccx); // scoped suspend of request
|
||||
// call IDispatch's invoke
|
||||
invokeResult= disp->Invoke(
|
||||
dispID, // IDispatch ID
|
||||
IID_NULL, // Reserved must be IID_NULL
|
||||
LOCALE_SYSTEM_DEFAULT, // The locale context, use the system's
|
||||
dispFlags, // Type of Invoke call
|
||||
params->GetDispParams(), // Parameters
|
||||
&dispResult, // Where the result is stored
|
||||
&exception, // Exception information
|
||||
0); // Index of an argument error
|
||||
}
|
||||
if(SUCCEEDED(invokeResult))
|
||||
{
|
||||
if(mode == CALL_METHOD)
|
||||
|
@ -218,7 +212,7 @@ JSBool XPCDispObject::Dispatch(XPCCallContext& ccx, IDispatch * disp,
|
|||
const XPCDispInterface::Member::ParamInfo & paramInfo = member->GetParamInfo(index);
|
||||
if(paramInfo.IsOut())
|
||||
{
|
||||
if(!XPCDispConvert::COMToJS(ccx, params.GetParamRef(index), val, err))
|
||||
if(!XPCDispConvert::COMToJS(ccx, params->GetParamRef(index), val, err))
|
||||
return ThrowBadParam(err, index, ccx);
|
||||
|
||||
if(paramInfo.IsRetVal())
|
||||
|
@ -227,10 +221,11 @@ JSBool XPCDispObject::Dispatch(XPCCallContext& ccx, IDispatch * disp,
|
|||
}
|
||||
else
|
||||
{
|
||||
// we actually assured this before doing the invoke
|
||||
NS_ASSERTION(JSVAL_IS_OBJECT(val), "out var is not an object");
|
||||
if(!OBJ_SET_PROPERTY(ccx, JSVAL_TO_OBJECT(val),
|
||||
rt->GetStringID(XPCJSRuntime::IDX_VALUE), &val))
|
||||
jsval * argv = ccx.GetArgv();
|
||||
// Out, in/out parameters must be objects
|
||||
if(!JSVAL_IS_OBJECT(argv[index]) ||
|
||||
!OBJ_SET_PROPERTY(ccx, JSVAL_TO_OBJECT(argv[index]),
|
||||
rt->GetStringID(XPCJSRuntime::IDX_VALUE), &val))
|
||||
return ThrowBadParam(NS_ERROR_XPC_CANT_SET_OUT_VAL, index, ccx);
|
||||
}
|
||||
}
|
||||
|
@ -250,7 +245,9 @@ JSBool XPCDispObject::Dispatch(XPCCallContext& ccx, IDispatch * disp,
|
|||
|
||||
if(NS_FAILED(invokeResult))
|
||||
{
|
||||
XPCThrower::ThrowCOMError(ccx, invokeResult);
|
||||
XPCThrower::ThrowCOMError(ccx, invokeResult, NS_ERROR_XPC_COM_ERROR,
|
||||
invokeResult == DISP_E_EXCEPTION ?
|
||||
&exception : nsnull);
|
||||
return JS_FALSE;
|
||||
}
|
||||
return JS_TRUE;
|
||||
|
@ -308,18 +305,19 @@ JSBool XPCDispObject::Invoke(XPCCallContext & ccx, CallMode mode)
|
|||
jsval name = member->GetName();
|
||||
|
||||
nsIXPCSecurityManager* sm = xpcc->GetAppropriateSecurityManager(secFlag);
|
||||
XPCWrappedNative* wrapper = ccx.GetWrapper();
|
||||
if(sm && NS_FAILED(sm->CanAccess(secAction, &ccx, ccx,
|
||||
ccx.GetFlattenedJSObject(),
|
||||
ccx.GetWrapper()->GetIdentityObject(),
|
||||
ccx.GetWrapper()->GetClassInfo(), name,
|
||||
ccx.GetWrapper()->GetSecurityInfoAddr())))
|
||||
wrapper->GetIdentityObject(),
|
||||
wrapper->GetClassInfo(), name,
|
||||
wrapper->GetSecurityInfoAddr())))
|
||||
{
|
||||
// the security manager vetoed. It should have set an exception.
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
XPCWrappedNative* wrapper = ccx.GetWrapper();
|
||||
nsISupports * pObj = ccx.GetTearOff()->GetNative();
|
||||
IDispatch * pObj = NS_REINTERPRET_CAST(IDispatch*,
|
||||
ccx.GetTearOff()->GetNative());
|
||||
PRUint32 args = member->GetParamCount();
|
||||
uintN err;
|
||||
// Make sure setter has one argument
|
||||
|
@ -329,14 +327,17 @@ JSBool XPCDispObject::Invoke(XPCCallContext & ccx, CallMode mode)
|
|||
// are not enough parameters
|
||||
if(argc < args)
|
||||
args = argc;
|
||||
XPCDispParams params(args);
|
||||
XPCDispParams * params = new XPCDispParams(args);
|
||||
jsval val;
|
||||
// If this is a setter, we just need to convert the first parameter
|
||||
if(mode == CALL_SETTER)
|
||||
{
|
||||
params.SetNamedPropID();
|
||||
if(!XPCDispConvert::JSToCOM(ccx, argv[0],params.GetParamRef(0), err))
|
||||
params->SetNamedPropID();
|
||||
if(!XPCDispConvert::JSToCOM(ccx, argv[0], params->GetParamRef(0), err))
|
||||
{
|
||||
delete params;
|
||||
return ThrowBadParam(err, 0, ccx);
|
||||
}
|
||||
}
|
||||
else if(mode != CALL_GETTER) // This is a function
|
||||
{
|
||||
|
@ -354,17 +355,20 @@ JSBool XPCDispObject::Invoke(XPCCallContext & ccx, CallMode mode)
|
|||
rt->GetStringID(XPCJSRuntime::IDX_VALUE),
|
||||
&val))
|
||||
{
|
||||
ThrowBadParam(NS_ERROR_XPC_NEED_OUT_OBJECT, index, ccx);
|
||||
delete params;
|
||||
return ThrowBadParam(NS_ERROR_XPC_NEED_OUT_OBJECT, index, ccx);
|
||||
}
|
||||
paramInfo.InitializeOutputParam(params->GetOutputBuffer(index), params->GetParamRef(index));
|
||||
}
|
||||
if(!XPCDispConvert::JSToCOM(ccx, val,params.GetParamRef(index), err))
|
||||
if(!XPCDispConvert::JSToCOM(ccx, val, params->GetParamRef(index), err, paramInfo.IsOut()))
|
||||
{
|
||||
ThrowBadParam(err, index, ccx);
|
||||
delete params;
|
||||
return ThrowBadParam(err, index, ccx);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
paramInfo.InitializeOutputParam(params.GetOutputBuffer(index), params.GetParamRef(index));
|
||||
paramInfo.InitializeOutputParam(params->GetOutputBuffer(index), params->GetParamRef(index));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -372,35 +376,37 @@ JSBool XPCDispObject::Invoke(XPCCallContext & ccx, CallMode mode)
|
|||
if(member->IsParameterizedProperty())
|
||||
{
|
||||
// We need to get a parameterized property object to return to JS
|
||||
if(XPCDispParamPropJSClass::GetNewOrUsed(ccx, wrapper,
|
||||
member->GetDispID(),
|
||||
params, &val))
|
||||
// NewInstance takes ownership of params
|
||||
if(XPCDispParamPropJSClass::NewInstance(ccx, wrapper,
|
||||
member->GetDispID(),
|
||||
params, &val))
|
||||
{
|
||||
ccx.SetRetVal(val);
|
||||
if(!JS_IdToValue(ccx, 1, &val))
|
||||
{
|
||||
// This shouldn't fail
|
||||
NS_ERROR("JS_IdToValue failed in XPCDispParamPropJSClass::NewInstance");
|
||||
return JS_FALSE;
|
||||
}
|
||||
JS_SetCallReturnValue2(ccx, val);
|
||||
return JS_TRUE;
|
||||
}
|
||||
// NewInstance would only fail if there was an out of memory problem
|
||||
JS_ReportOutOfMemory(ccx);
|
||||
delete params;
|
||||
return JS_FALSE;
|
||||
}
|
||||
IDispatch * pDisp;
|
||||
// TODO: I'm not sure this QI is really needed
|
||||
nsresult result = pObj->QueryInterface(NSID_IDISPATCH, (void**)&pDisp);
|
||||
if(NS_SUCCEEDED(result))
|
||||
JSBool retval = Dispatch(ccx, pObj, member->GetDispID(), mode, params, &val, member, rt);
|
||||
if(retval && mode == CALL_SETTER)
|
||||
{
|
||||
JSBool retval = Dispatch(ccx, pDisp, member->GetDispID(), mode, params, &val, member, rt);
|
||||
if(retval && mode == CALL_SETTER)
|
||||
{
|
||||
ccx.SetRetVal(argv[0]);
|
||||
}
|
||||
else
|
||||
{
|
||||
ccx.SetRetVal(val);
|
||||
}
|
||||
return retval;
|
||||
ccx.SetRetVal(argv[0]);
|
||||
}
|
||||
return JS_FALSE;
|
||||
else
|
||||
{
|
||||
ccx.SetRetVal(val);
|
||||
}
|
||||
delete params;
|
||||
return retval;
|
||||
}
|
||||
|
||||
static
|
||||
|
@ -466,13 +472,14 @@ XPC_IDispatch_CallMethod(JSContext* cx, JSObject* obj, uintN argc,
|
|||
|
||||
XPCDispInterface::Member* member;
|
||||
XPCNativeInterface* iface;
|
||||
if(GetMember(ccx, funobj, iface, member))
|
||||
{
|
||||
ccx.SetIDispatchInfo(iface, member);
|
||||
#ifdef DEBUG
|
||||
PRBool ok =
|
||||
#endif
|
||||
GetMember(ccx, funobj, iface, member);
|
||||
NS_ASSERTION(ok, "GetMember faild in XPC_IDispatch_CallMethod");
|
||||
ccx.SetIDispatchInfo(iface, member);
|
||||
|
||||
return XPCDispObject::Invoke(ccx, XPCDispObject::CALL_METHOD);
|
||||
}
|
||||
return JS_FALSE;
|
||||
return XPCDispObject::Invoke(ccx, XPCDispObject::CALL_METHOD);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -500,10 +507,12 @@ XPC_IDispatch_GetterSetter(JSContext *cx, JSObject *obj, uintN argc,
|
|||
ccx.SetArgsAndResultPtr(argc, argv, vp);
|
||||
XPCDispInterface::Member* member;
|
||||
XPCNativeInterface* iface;
|
||||
if(GetMember(ccx, funobj, iface, member))
|
||||
{
|
||||
ccx.SetIDispatchInfo(iface, member);
|
||||
return XPCDispObject::Invoke(ccx, argc != 0 ? XPCDispObject::CALL_SETTER : XPCDispObject::CALL_GETTER);
|
||||
}
|
||||
return JS_FALSE;
|
||||
#ifdef DEBUG
|
||||
PRBool ok =
|
||||
#endif
|
||||
GetMember(ccx, funobj, iface, member);
|
||||
NS_ASSERTION(ok, "GetMember faild in XPC_IDispatch_CallMethod");
|
||||
|
||||
ccx.SetIDispatchInfo(iface, member);
|
||||
return XPCDispObject::Invoke(ccx, argc != 0 ? XPCDispObject::CALL_SETTER : XPCDispObject::CALL_GETTER);
|
||||
}
|
||||
|
|
|
@ -73,7 +73,7 @@ XPC_PP_GetProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
|
|||
XPCDispParamPropJSClass* paramProp = GetParamProp(cx, obj);
|
||||
JSObject* originalObj = paramProp->GetWrapper()->GetFlatJSObject();
|
||||
XPCCallContext ccx(JS_CALLER, cx, originalObj, nsnull, id,
|
||||
paramProp->GetParams().GetParamCount(), nsnull, vp);
|
||||
paramProp->GetParams()->GetParamCount(), nsnull, vp);
|
||||
return paramProp->Invoke(ccx, XPCDispObject::CALL_GETTER, vp);
|
||||
}
|
||||
|
||||
|
@ -94,15 +94,15 @@ XPC_PP_SetProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
|
|||
XPCDispParamPropJSClass* paramProp = GetParamProp(cx, obj);
|
||||
JSObject* originalObj = paramProp->GetWrapper()->GetFlatJSObject();
|
||||
XPCCallContext ccx(JS_CALLER, cx, originalObj, nsnull, id,
|
||||
paramProp->GetParams().GetParamCount(), nsnull, vp);
|
||||
paramProp->GetParams()->GetParamCount(), nsnull, vp);
|
||||
_variant_t var;
|
||||
uintN err;
|
||||
if(!XPCDispConvert::JSToCOM(ccx, *vp, var, err))
|
||||
return JS_FALSE;
|
||||
XPCDispParams& params = paramProp->GetParams();
|
||||
params.SetNamedPropID();
|
||||
XPCDispParams* params = paramProp->GetParams();
|
||||
params->SetNamedPropID();
|
||||
// params will own var
|
||||
params.InsertParam(var);
|
||||
params->InsertParam(var);
|
||||
return paramProp->Invoke(ccx, XPCDispObject::CALL_SETTER, vp);
|
||||
}
|
||||
|
||||
|
@ -173,10 +173,10 @@ static JSClass ParamPropClass = {
|
|||
};
|
||||
|
||||
// static
|
||||
JSBool XPCDispParamPropJSClass::GetNewOrUsed(XPCCallContext& ccx,
|
||||
JSBool XPCDispParamPropJSClass::NewInstance(XPCCallContext& ccx,
|
||||
XPCWrappedNative* wrapper,
|
||||
PRUint32 dispID,
|
||||
XPCDispParams& dispParams,
|
||||
XPCDispParams* dispParams,
|
||||
jsval* paramPropObj)
|
||||
{
|
||||
XPCDispParamPropJSClass* pDispParam =
|
||||
|
@ -196,22 +196,22 @@ JSBool XPCDispParamPropJSClass::GetNewOrUsed(XPCCallContext& ccx,
|
|||
XPCDispParamPropJSClass::XPCDispParamPropJSClass(XPCWrappedNative* wrapper,
|
||||
nsISupports * dispObj,
|
||||
PRUint32 dispID,
|
||||
XPCDispParams& dispParams) :
|
||||
XPCDispParams* dispParams) :
|
||||
mWrapper(wrapper),
|
||||
mDispID(dispID),
|
||||
mDispParams(dispParams)
|
||||
mDispParams(dispParams),
|
||||
mDispObj(nsnull)
|
||||
{
|
||||
NS_ADDREF(mWrapper);
|
||||
nsresult result = dispObj->QueryInterface(NSID_IDISPATCH,
|
||||
dispObj->QueryInterface(NSID_IDISPATCH,
|
||||
NS_REINTERPRET_CAST(void**,
|
||||
&mDispObj));
|
||||
if(NS_FAILED(result))
|
||||
mDispObj = nsnull;
|
||||
}
|
||||
|
||||
XPCDispParamPropJSClass::~XPCDispParamPropJSClass()
|
||||
{
|
||||
delete mDispParams;
|
||||
// release our members
|
||||
NS_RELEASE(mWrapper);
|
||||
NS_RELEASE(mDispObj);
|
||||
NS_IF_RELEASE(mWrapper);
|
||||
NS_IF_RELEASE(mDispObj);
|
||||
}
|
||||
|
|
|
@ -43,52 +43,32 @@
|
|||
#include "xpcprivate.h"
|
||||
|
||||
XPCDispParams::XPCDispParams(PRUint32 args) :
|
||||
mVarBuffer(args <= DEFAULT_ARG_ARRAY_SIZE ?
|
||||
mVarStackBuffer : new char[XPC_VARIANT_BUFFER_SIZE(args)]),
|
||||
mRefBuffer(mStackRefBuffer + sizeof(VARIANT)),
|
||||
mDispParamsAllocated(nsnull),
|
||||
mRefBufferAllocated(nsnull),
|
||||
mPropID(DISPID_PROPERTYPUT)
|
||||
#ifdef DEBUG
|
||||
,mInserted(PR_FALSE)
|
||||
#endif
|
||||
{
|
||||
memset(mVarBuffer, 0, XPC_VARIANT_BUFFER_SIZE(args));
|
||||
if(args >= DEFAULT_ARG_ARRAY_SIZE)
|
||||
{
|
||||
mRefBufferAllocated = new char[RefBufferSize(args)];
|
||||
mRefBuffer = mRefBufferAllocated + sizeof(VARIANT);
|
||||
}
|
||||
// Initialize the full buffer that was allocated
|
||||
memset(mRefBuffer - sizeof(VARIANT), 0, RefBufferSize(args));
|
||||
// Initialize the IDispatch parameters
|
||||
mDispParams.cArgs = args;
|
||||
mDispParams.rgvarg = args <= DEFAULT_ARG_ARRAY_SIZE ? mStackArgs : new VARIANT[args];
|
||||
mDispParams.rgdispidNamedArgs = nsnull;
|
||||
mDispParams.cNamedArgs = 0;
|
||||
}
|
||||
|
||||
XPCDispParams::XPCDispParams(XPCDispParams & other) :
|
||||
mPropID(DISPID_PROPERTYPUT)
|
||||
{
|
||||
// copy the simple values
|
||||
mDispParams.rgdispidNamedArgs = nsnull;
|
||||
mDispParams.cNamedArgs = 0;
|
||||
mDispParams.cArgs = other.mDispParams.cArgs;
|
||||
// move the variant buffer, used for reference types
|
||||
if(other.mVarBuffer == other.mVarStackBuffer)
|
||||
{
|
||||
mVarBuffer = mVarStackBuffer;
|
||||
memcpy(mVarBuffer, other.mVarBuffer,
|
||||
XPC_VARIANT_BUFFER_SIZE(other.mDispParams.cArgs));
|
||||
}
|
||||
if(args <= DEFAULT_ARG_ARRAY_SIZE)
|
||||
mDispParams.rgvarg = mStackArgs + 1;
|
||||
else
|
||||
{
|
||||
mVarBuffer = other.mVarBuffer;
|
||||
other.mVarBuffer = nsnull;
|
||||
mDispParamsAllocated = new VARIANT[args + 1];
|
||||
mDispParams.rgvarg = mDispParamsAllocated + 1;
|
||||
}
|
||||
// move the variants
|
||||
if(other.mDispParams.rgvarg == other.mStackArgs)
|
||||
{
|
||||
mDispParams.rgvarg = mStackArgs;
|
||||
memcpy(mDispParams.rgvarg, other.mStackArgs,
|
||||
sizeof(VARIANT) * other.mDispParams.cArgs);
|
||||
other.mDispParams.cArgs;
|
||||
}
|
||||
else
|
||||
{
|
||||
mDispParams.rgvarg = other.mDispParams.rgvarg;
|
||||
other.mDispParams.rgvarg = 0;
|
||||
}
|
||||
// The source no longer has arguments
|
||||
other.mDispParams.cArgs = 0;
|
||||
mDispParams.rgdispidNamedArgs = nsnull;
|
||||
mDispParams.cNamedArgs = 0;
|
||||
}
|
||||
|
||||
|
||||
|
@ -97,31 +77,25 @@ XPCDispParams::~XPCDispParams()
|
|||
// Cleanup the variants
|
||||
for(PRUint32 index = 0; index < mDispParams.cArgs; ++index)
|
||||
VariantClear(mDispParams.rgvarg + index);
|
||||
// Cleanup if we allocated the variant array
|
||||
if(mDispParams.rgvarg != mStackArgs)
|
||||
delete [] mDispParams.rgvarg;
|
||||
if(mVarBuffer != mVarStackBuffer)
|
||||
delete [] mVarBuffer;
|
||||
// Cleanup if we allocated the variant array. Remember that
|
||||
// our buffer may point one element into the allocate buffer
|
||||
delete [] mRefBufferAllocated;
|
||||
delete [] mDispParamsAllocated;
|
||||
}
|
||||
|
||||
void XPCDispParams::InsertParam(_variant_t & var)
|
||||
{
|
||||
// Save off the existing pointers
|
||||
VARIANT* oldArgs = mDispParams.rgvarg;
|
||||
char * oldVarBuffer = mVarBuffer;
|
||||
// If this will exceed our internal static buffers we need to create
|
||||
// dynamic ones
|
||||
if(mDispParams.cNamedArgs >= DEFAULT_ARG_ARRAY_SIZE)
|
||||
{
|
||||
if(mDispParams.rgvarg == mStackArgs)
|
||||
mDispParams.rgvarg = new VARIANT[mDispParams.cArgs + 1];
|
||||
if(mVarBuffer == mVarStackBuffer)
|
||||
mVarBuffer = new char [XPC_VARIANT_BUFFER_SIZE(mDispParams.cArgs + 1)];
|
||||
}
|
||||
// Move the data up, using position safe copy
|
||||
memmove(mDispParams.rgvarg + 1, oldArgs, sizeof(VARIANT) * mDispParams.cArgs);
|
||||
memmove(mVarBuffer + VARIANT_UNION_SIZE,oldVarBuffer, XPC_VARIANT_BUFFER_SIZE(mDispParams.cArgs));
|
||||
mDispParams.rgvarg[0] = var.Detach();
|
||||
memset(mVarBuffer, 0, VARIANT_UNION_SIZE);
|
||||
#ifdef DEBUG
|
||||
NS_ASSERTION(!mInserted,
|
||||
"XPCDispParams::InsertParam cannot be called more than once");
|
||||
mInserted = PR_TRUE;
|
||||
#endif
|
||||
// Bump the pointer back and increment the arg count
|
||||
--mDispParams.rgvarg;
|
||||
mRefBuffer -= sizeof(VARIANT);
|
||||
++mDispParams.cArgs;
|
||||
// Assign the value
|
||||
mDispParams.rgvarg[0] = var.Detach();
|
||||
// initialize the ref buffer
|
||||
memset(mRefBuffer, 0, sizeof(VARIANT));
|
||||
}
|
||||
|
|
|
@ -47,27 +47,46 @@
|
|||
#error "DispPrivate.h should not be included directly, please use XPCPrivate.h"
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Needed for CComPtr and friends
|
||||
*/
|
||||
#include <atlbase.h>
|
||||
/**
|
||||
* Needed for _variant_t and _bstr_t
|
||||
*/
|
||||
#include <comdef.h>
|
||||
/**
|
||||
* IObjectSafety interface and friends
|
||||
*/
|
||||
#include "objsafe.h"
|
||||
|
||||
// MS clutters the global namespace with so many macro names :-(
|
||||
// I tried to keep these includes in the CPP's but it became too
|
||||
// convoluted
|
||||
#undef GetClassInfo
|
||||
#undef GetClassName
|
||||
#undef GetMessage
|
||||
|
||||
// We need IDispatch
|
||||
#include "nsIDispatchSupport.h"
|
||||
|
||||
// The following are macro helpers pulled from XPCOM but tailored to COM
|
||||
#define NS_DECL_IUNKNOWN \
|
||||
public: \
|
||||
STDMETHOD(QueryInterface)(const struct _GUID& aIID, \
|
||||
STDMETHOD(QueryInterface)(REFIID aIID, \
|
||||
void** aInstancePtr); \
|
||||
STDMETHODIMP_(nsrefcnt) AddRef(void); \
|
||||
STDMETHODIMP_(nsrefcnt) Release(void); \
|
||||
STDMETHODIMP_(ULONG) AddRef(void); \
|
||||
STDMETHODIMP_(ULONG) Release(void); \
|
||||
protected: \
|
||||
nsAutoRefCnt mRefCnt; \
|
||||
NS_DECL_OWNINGTHREAD \
|
||||
ULONG mRefCnt;
|
||||
|
||||
#define NS_IMPL_COM_QUERY_HEAD(_class) \
|
||||
STDMETHODIMP _class::QueryInterface(const GUID& aIID, void** aInstancePtr) \
|
||||
STDMETHODIMP _class::QueryInterface(REFIID aIID, void** aInstancePtr) \
|
||||
{ \
|
||||
NS_ASSERTION(aInstancePtr, \
|
||||
"QueryInterface requires a non-NULL destination!"); \
|
||||
if( !aInstancePtr ) \
|
||||
return NS_ERROR_NULL_POINTER; \
|
||||
return E_POINTER; \
|
||||
IUnknown* foundInterface;
|
||||
|
||||
#define NS_IMPL_COM_QUERY_BODY(_interface) \
|
||||
|
@ -77,13 +96,13 @@ STDMETHODIMP _class::QueryInterface(const GUID& aIID, void** aInstancePtr) \
|
|||
|
||||
#define NS_IMPL_COM_QUERY_TAIL_GUTS \
|
||||
foundInterface = 0; \
|
||||
nsresult status; \
|
||||
HRESULT status; \
|
||||
if( !foundInterface ) \
|
||||
status = NS_NOINTERFACE; \
|
||||
status = E_NOINTERFACE; \
|
||||
else \
|
||||
{ \
|
||||
NS_ADDREF(foundInterface); \
|
||||
status = NS_OK; \
|
||||
status = S_OK; \
|
||||
} \
|
||||
*aInstancePtr = foundInterface; \
|
||||
return status; \
|
||||
|
@ -93,11 +112,36 @@ STDMETHODIMP _class::QueryInterface(const GUID& aIID, void** aInstancePtr) \
|
|||
#define NS_COM_MAP_ENTRY(_interface) NS_IMPL_COM_QUERY_BODY(_interface)
|
||||
#define NS_COM_MAP_END NS_IMPL_COM_QUERY_TAIL_GUTS
|
||||
|
||||
#define NS_COM_IMPL_ADDREF(_class) \
|
||||
STDMETHODIMP_(ULONG) _class::AddRef(void) \
|
||||
{ \
|
||||
NS_PRECONDITION(PRInt32(mRefCnt) >= 0, "illegal refcnt"); \
|
||||
NS_ASSERT_OWNINGTHREAD(_class); \
|
||||
++mRefCnt; \
|
||||
NS_LOG_ADDREF(this, mRefCnt, #_class, sizeof(*this)); \
|
||||
return mRefCnt; \
|
||||
}
|
||||
|
||||
#define NS_COM_IMPL_RELEASE(_class) \
|
||||
STDMETHODIMP_(ULONG) _class::Release(void) \
|
||||
{ \
|
||||
NS_PRECONDITION(0 != mRefCnt, "dup release"); \
|
||||
NS_ASSERT_OWNINGTHREAD(_class); \
|
||||
--mRefCnt; \
|
||||
NS_LOG_RELEASE(this, mRefCnt, #_class); \
|
||||
if(mRefCnt == 0) { \
|
||||
mRefCnt = 1; /* stabilize */ \
|
||||
delete this; \
|
||||
return 0; \
|
||||
} \
|
||||
return mRefCnt; \
|
||||
}
|
||||
|
||||
#ifndef NS_MT_SUPPORTED
|
||||
#error "We need MT support
|
||||
#endif
|
||||
|
||||
extern nsID NSID_IDISPATCH;
|
||||
extern const nsID NSID_IDISPATCH;
|
||||
|
||||
/**
|
||||
* JS<>COM Conversion functions. XPCDispConvert serves more as a namespace than
|
||||
|
@ -125,7 +169,8 @@ public:
|
|||
* @return True if the conversion succeeded
|
||||
*/
|
||||
static
|
||||
JSBool JSToCOM(XPCCallContext& ccx, jsval src, VARIANT & dest, nsresult& err);
|
||||
JSBool JSToCOM(XPCCallContext& ccx, jsval src, VARIANT & dest,
|
||||
nsresult& err, JSBool isByRef = JS_FALSE);
|
||||
|
||||
/**
|
||||
* Converts a COM variant to a jsval
|
||||
|
@ -136,7 +181,7 @@ public:
|
|||
* @return Returns true if the conversion succeeded
|
||||
*/
|
||||
static
|
||||
JSBool COMToJS(XPCCallContext& ccx, const _variant_t & src, jsval & dest,
|
||||
JSBool COMToJS(XPCCallContext& ccx, const VARIANT & src, jsval & dest,
|
||||
nsresult& err);
|
||||
private:
|
||||
/**
|
||||
|
@ -159,7 +204,7 @@ private:
|
|||
* @return True if the conversion succeeded
|
||||
*/
|
||||
static
|
||||
JSBool COMArrayToJSArray(XPCCallContext& ccx, const _variant_t & src,
|
||||
JSBool COMArrayToJSArray(XPCCallContext& ccx, const VARIANT & src,
|
||||
jsval & dest, nsresult& err);
|
||||
};
|
||||
|
||||
|
@ -220,22 +265,27 @@ public:
|
|||
* @param dispid IDispatch id for the name
|
||||
* @param name the name to assign
|
||||
*/
|
||||
void SetName(DISPID dispid, nsACString const & name);
|
||||
void SetName(DISPID dispid, nsAString const & name);
|
||||
/**
|
||||
* Retrieves a name/string for a dispid. This function
|
||||
* performs bounds checking in debug builds
|
||||
* @param dispid dispatch ID of the name to retrieve
|
||||
*/
|
||||
nsCString GetName(DISPID dispid) const;
|
||||
const nsAString& GetName(DISPID dispid) const;
|
||||
/**
|
||||
* Performs a search of the array for the target returning the
|
||||
* the id for the name
|
||||
* @param target the name to find
|
||||
*/
|
||||
DISPID Find(const nsACString &target) const;
|
||||
DISPID Find(const nsAString &target) const;
|
||||
private:
|
||||
/**
|
||||
* This is used by Find when it doesn't find something
|
||||
* @see XPCDispNameArray::Find
|
||||
*/
|
||||
static const nsString sEmpty;
|
||||
PRUint32 mCount;
|
||||
nsCString* mNames;
|
||||
nsString* mNames;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -436,7 +486,7 @@ public:
|
|||
* @param dispID the DISPID to look up
|
||||
* @return the name of the function
|
||||
*/
|
||||
nsCString GetNameForDispID(DISPID dispID);
|
||||
const nsAString& GetNameForDispID(DISPID dispID);
|
||||
private:
|
||||
/**
|
||||
* Initializes the object
|
||||
|
@ -524,7 +574,7 @@ public:
|
|||
* returns the name of the property/method
|
||||
* @return the name of the property/method
|
||||
*/
|
||||
nsACString const & GetName() const;
|
||||
nsAString const & GetName() const;
|
||||
private:
|
||||
enum property_type
|
||||
{
|
||||
|
@ -539,7 +589,7 @@ private:
|
|||
PRUint32 mParamCount;
|
||||
PRUint32 mMemID;
|
||||
jsval mProperty;
|
||||
nsCAutoString mName;
|
||||
nsString mName;
|
||||
|
||||
/**
|
||||
* Accessor for the property type mProperty
|
||||
|
@ -584,7 +634,7 @@ public:
|
|||
* interface pointer
|
||||
* @return HRESULT
|
||||
*/
|
||||
STDMETHOD(QueryInterface)(const struct _GUID & IID,void ** pPtr);
|
||||
STDMETHOD(QueryInterface)(REFIID IID,void ** pPtr);
|
||||
/**
|
||||
* Returns the number of type info's for this IDispatch instance.
|
||||
* See MSDN for form information
|
||||
|
@ -622,12 +672,14 @@ private:
|
|||
// The Type information for our instance
|
||||
XPCDispTypeInfo * mCOMTypeInfo;
|
||||
// Reference count
|
||||
nsrefcnt mRefCnt;
|
||||
ULONG mRefCnt;
|
||||
// Returns the type information
|
||||
XPCDispTypeInfo * GetCOMTypeInfo();
|
||||
// Returns the JS Object being used to wrap
|
||||
inline
|
||||
JSObject* GetJSObject();
|
||||
|
||||
NS_DECL_OWNINGTHREAD;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -909,8 +961,10 @@ private:
|
|||
* @param cx a JS context
|
||||
* @param pTypeInfo pointer to the type information for the object
|
||||
* @param members number of members in the interface
|
||||
* @return PR_TRUE if it worked, PR_FALSE if it didn't (usually out of
|
||||
* memory)
|
||||
*/
|
||||
void InspectIDispatch(JSContext * cx, ITypeInfo * pTypeInfo,
|
||||
PRBool InspectIDispatch(JSContext * cx, ITypeInfo * pTypeInfo,
|
||||
PRUint32 members);
|
||||
};
|
||||
|
||||
|
@ -937,7 +991,7 @@ public:
|
|||
*/
|
||||
static
|
||||
JSBool Dispatch(XPCCallContext& ccx, IDispatch * pDisp,
|
||||
DISPID dispID, CallMode mode, XPCDispParams & params,
|
||||
DISPID dispID, CallMode mode, XPCDispParams * params,
|
||||
jsval* retval, XPCDispInterface::Member* member = nsnull,
|
||||
XPCJSRuntime* rt = nsnull);
|
||||
/**
|
||||
|
@ -956,7 +1010,7 @@ public:
|
|||
* @param result pointer to the pointer to receive the interface pointer
|
||||
*/
|
||||
static
|
||||
HRESULT COMCreateInstance(const char * className,
|
||||
HRESULT COMCreateInstance(BSTR className,
|
||||
PRBool testScriptability, IDispatch ** result);
|
||||
/**
|
||||
* Wraps an IDispatch interface, returning the object as a jsval
|
||||
|
@ -966,7 +1020,7 @@ public:
|
|||
* @param rval is a pointer to a jsval to receive the JS object wrapper
|
||||
*/
|
||||
static
|
||||
PRBool WrapIDispatch(IDispatch *pDispatch, JSContext *cx,
|
||||
PRBool WrapIDispatch(IDispatch *pDispatch, XPCCallContext & ccx,
|
||||
JSObject *obj, jsval *rval);
|
||||
};
|
||||
|
||||
|
@ -1044,10 +1098,6 @@ public:
|
|||
* @param args the number of parameters this object will hold
|
||||
*/
|
||||
XPCDispParams(PRUint32 args);
|
||||
/**
|
||||
* Makes a copy and transfers ownership of buffers
|
||||
*/
|
||||
XPCDispParams(XPCDispParams & other);
|
||||
/**
|
||||
* Cleans up the parameters' data
|
||||
*/
|
||||
|
@ -1062,6 +1112,12 @@ public:
|
|||
* @param index index of the parameter
|
||||
* @return a reference to the parameter at index
|
||||
*/
|
||||
// const VARIANT & GetParamRef(PRUint32 index) const;
|
||||
/**
|
||||
* Returns a reference to a parameter
|
||||
* @param index index of the parameter
|
||||
* @return a reference to the parameter at index
|
||||
*/
|
||||
VARIANT & GetParamRef(PRUint32 index);
|
||||
/**
|
||||
* Returns the parameter by value
|
||||
|
@ -1079,7 +1135,7 @@ public:
|
|||
* Returns a DISPPARAMS structure pointer for the parameters
|
||||
* @return a DISPPARAMS structure pointer for the parameters
|
||||
*/
|
||||
DISPPARAMS* GetDispParams() { return &mDispParams; }
|
||||
DISPPARAMS* GetDispParams() const { return &NS_CONST_CAST(XPCDispParams*,this)->mDispParams; }
|
||||
/**
|
||||
* Returns the number of parameters
|
||||
* @return the number of parameters
|
||||
|
@ -1092,6 +1148,11 @@ public:
|
|||
*/
|
||||
void InsertParam(_variant_t & var);
|
||||
private:
|
||||
/**
|
||||
* Don't allow copying
|
||||
*/
|
||||
XPCDispParams(const XPCDispParams & other) {
|
||||
NS_ERROR("XPCDispParams can't be copied"); }
|
||||
/**
|
||||
* We don't allow assignments
|
||||
*/
|
||||
|
@ -1101,16 +1162,24 @@ private:
|
|||
enum
|
||||
{
|
||||
DEFAULT_ARG_ARRAY_SIZE = 8,
|
||||
// This is the size of the largest member in the union in VARIANT
|
||||
VARIANT_UNION_SIZE = sizeof(VARIANT) - sizeof(VARTYPE) - sizeof(unsigned short) * 3
|
||||
DEFAULT_REF_BUFFER_SIZE = 8 * sizeof(VARIANT)
|
||||
};
|
||||
#define XPC_VARIANT_BUFFER_SIZE(count) (VARIANT_UNION_SIZE * count)
|
||||
static
|
||||
PRUint32 RefBufferSize(PRUint32 args) { return (args + 1) * sizeof(VARIANT); }
|
||||
|
||||
DISPPARAMS mDispParams;
|
||||
char* mVarBuffer;
|
||||
char mVarStackBuffer[XPC_VARIANT_BUFFER_SIZE(DEFAULT_ARG_ARRAY_SIZE)];
|
||||
char* mRefBuffer;
|
||||
VARIANT* mDispParamsAllocated;
|
||||
char* mRefBufferAllocated;
|
||||
/**
|
||||
* Used by output/ref variant types
|
||||
*/
|
||||
char mStackRefBuffer[DEFAULT_REF_BUFFER_SIZE];
|
||||
VARIANT mStackArgs[DEFAULT_ARG_ARRAY_SIZE];
|
||||
DISPID mPropID;
|
||||
#ifdef DEBUG
|
||||
PRBool mInserted;
|
||||
#endif
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -1132,9 +1201,9 @@ public:
|
|||
* JS function object
|
||||
* @return true if the JS function object was created
|
||||
*/
|
||||
static JSBool GetNewOrUsed(XPCCallContext& ccx, XPCWrappedNative* wrapper,
|
||||
static JSBool NewInstance(XPCCallContext& ccx, XPCWrappedNative* wrapper,
|
||||
PRUint32 dispID,
|
||||
XPCDispParams& dispParams,
|
||||
XPCDispParams* dispParams,
|
||||
jsval* paramPropObj);
|
||||
/**
|
||||
* Cleans up the member, derefs the mDispObj, mWrapper and such
|
||||
|
@ -1158,7 +1227,7 @@ public:
|
|||
* Returns the parameters for the parameterized property
|
||||
* @return a reference to the parameters for the parameterized property
|
||||
*/
|
||||
XPCDispParams& GetParams() { return mDispParams; }
|
||||
XPCDispParams* GetParams() const { return mDispParams; }
|
||||
private:
|
||||
/**
|
||||
* Private constructor to initialize data members
|
||||
|
@ -1168,11 +1237,11 @@ private:
|
|||
* @param dispParams the parameters for the parameterized property
|
||||
*/
|
||||
XPCDispParamPropJSClass(XPCWrappedNative* wrapper, nsISupports* dispObj,
|
||||
PRUint32 dispID, XPCDispParams& dispParams);
|
||||
PRUint32 dispID, XPCDispParams* dispParams);
|
||||
|
||||
XPCWrappedNative* mWrapper;
|
||||
PRUint32 mDispID;
|
||||
XPCDispParams mDispParams;
|
||||
XPCDispParams* mDispParams;
|
||||
IDispatch* mDispObj;
|
||||
};
|
||||
|
||||
|
|
|
@ -50,46 +50,31 @@
|
|||
*/
|
||||
static HRESULT Error(HRESULT hResult, const CComBSTR & message)
|
||||
{
|
||||
ICreateErrorInfo * pCreateError;
|
||||
IErrorInfo * pError;
|
||||
CComPtr<ICreateErrorInfo> pCreateError;
|
||||
CComPtr<IErrorInfo> pError;
|
||||
HRESULT result = CreateErrorInfo(&pCreateError);
|
||||
if (FAILED(result))
|
||||
if(FAILED(result))
|
||||
return E_NOTIMPL;
|
||||
result = pCreateError->QueryInterface(&pError);
|
||||
if (FAILED(result))
|
||||
if(FAILED(result))
|
||||
return E_NOTIMPL;
|
||||
result = pCreateError->SetDescription(message);
|
||||
if (FAILED(result))
|
||||
if(FAILED(result))
|
||||
return E_NOTIMPL;
|
||||
result = pCreateError->SetGUID(IID_IDispatch);
|
||||
if (FAILED(result))
|
||||
if(FAILED(result))
|
||||
return E_NOTIMPL;
|
||||
CComBSTR source(L"@mozilla.XPCDispatchTearOff");
|
||||
result = pCreateError->SetSource(source);
|
||||
if (FAILED(result))
|
||||
if(FAILED(result))
|
||||
return E_NOTIMPL;
|
||||
result = SetErrorInfo(0, pError);
|
||||
if (FAILED(result))
|
||||
if(FAILED(result))
|
||||
return E_NOTIMPL;
|
||||
pError->Release();
|
||||
pCreateError->Release();
|
||||
return hResult;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets the COM error from a result code and text message
|
||||
* @param hResult the COM error code to be used
|
||||
* @param message the message to put in the error
|
||||
* @return the error code passed in via hResult
|
||||
*/
|
||||
inline
|
||||
HRESULT Error(HRESULT hResult, const nsCString & message)
|
||||
{
|
||||
CComBSTR someText(PromiseFlatCString(message).get());
|
||||
return Error(hResult, someText);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the COM error from a result code and text message
|
||||
* @param hResult the COM error code to be used
|
||||
|
@ -108,28 +93,22 @@ HRESULT Error(HRESULT hResult, const char * message)
|
|||
* @param exception
|
||||
* @return the description of the exception
|
||||
*/
|
||||
static nsCString BuildMessage(nsIException * exception)
|
||||
static void BuildMessage(nsIException * exception, nsCString & result)
|
||||
{
|
||||
nsCString result;
|
||||
char * msg;
|
||||
if(NS_FAILED(exception->GetMessage(&msg)))
|
||||
msg = "";
|
||||
char * filename;
|
||||
if(NS_FAILED(exception->GetFilename(&filename)))
|
||||
filename = "";
|
||||
nsXPIDLCString msg;
|
||||
exception->GetMessage(getter_Copies(msg));
|
||||
nsXPIDLCString filename;
|
||||
exception->GetFilename(getter_Copies(filename));
|
||||
|
||||
PRUint32 lineNumber;
|
||||
if(NS_FAILED(exception->GetLineNumber(&lineNumber)))
|
||||
lineNumber = 0;
|
||||
char lineNumberStr[32];
|
||||
sprintf(lineNumberStr, "%d", lineNumber);
|
||||
result = "Error in file ";
|
||||
result += filename;
|
||||
result += ",#";
|
||||
result += lineNumberStr;
|
||||
result.AppendInt(lineNumber);
|
||||
result += " : ";
|
||||
result += msg;
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -139,8 +118,9 @@ static nsCString BuildMessage(nsIException * exception)
|
|||
inline
|
||||
static void SetCOMError(nsIException * exception)
|
||||
{
|
||||
nsCString message = BuildMessage(exception);
|
||||
Error(E_FAIL, message);
|
||||
nsCString message;
|
||||
BuildMessage(exception, message);
|
||||
Error(E_FAIL, message.get());
|
||||
}
|
||||
|
||||
XPCDispatchTearOff::XPCDispatchTearOff(nsIXPConnectWrappedJS * wrappedJS) :
|
||||
|
@ -155,31 +135,8 @@ XPCDispatchTearOff::~XPCDispatchTearOff()
|
|||
NS_IF_RELEASE(mCOMTypeInfo);
|
||||
}
|
||||
|
||||
ULONG XPCDispatchTearOff::AddRef()
|
||||
{
|
||||
NS_PRECONDITION(PRInt32(mRefCnt) >= 0, "illegal refcnt");
|
||||
nsrefcnt count;
|
||||
count = PR_AtomicIncrement((PRInt32*)&mRefCnt);
|
||||
NS_LOG_ADDREF(this, count, "XPCDispatchTearOff", sizeof(*this));
|
||||
return count;
|
||||
}
|
||||
|
||||
ULONG XPCDispatchTearOff::Release()
|
||||
{
|
||||
nsrefcnt count;
|
||||
NS_PRECONDITION(0 != mRefCnt, "dup release");
|
||||
count = PR_AtomicDecrement((PRInt32 *)&mRefCnt);
|
||||
NS_LOG_RELEASE(this, count, "XPCDispatchTearOff");
|
||||
if(0 == count)
|
||||
{
|
||||
mRefCnt = 1; /* stabilize */
|
||||
/* enable this to find non-threadsafe destructors: */
|
||||
/* NS_ASSERT_OWNINGTHREAD(XPCDispatchTearOff); */
|
||||
NS_DELETEXPCOM(this);
|
||||
return 0;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
NS_COM_IMPL_ADDREF(XPCDispatchTearOff)
|
||||
NS_COM_IMPL_RELEASE(XPCDispatchTearOff)
|
||||
|
||||
STDMETHODIMP XPCDispatchTearOff::InterfaceSupportsErrorInfo(REFIID riid)
|
||||
{
|
||||
|
@ -201,19 +158,19 @@ STDMETHODIMP XPCDispatchTearOff::QueryInterface(const struct _GUID & guid,
|
|||
{
|
||||
if(IsEqualIID(guid, IID_IDispatch))
|
||||
{
|
||||
*pPtr = NS_STATIC_CAST(IDispatch*, this);
|
||||
NS_ADDREF(NS_REINTERPRET_CAST(IUnknown*, *pPtr));
|
||||
*pPtr = NS_STATIC_CAST(IDispatch*,this);
|
||||
NS_ADDREF_THIS();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if(IsEqualIID(guid, IID_ISupportErrorInfo))
|
||||
{
|
||||
*pPtr = NS_STATIC_CAST(ISupportErrorInfo*, this);
|
||||
NS_ADDREF(NS_REINTERPRET_CAST(IUnknown*, *pPtr));
|
||||
*pPtr = NS_STATIC_CAST(IDispatch*,this);
|
||||
NS_ADDREF_THIS();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
return mWrappedJS->QueryInterface(XPCDispGUID2nsIID(guid), pPtr);
|
||||
return mWrappedJS->QueryInterface(XPCDispIID2nsIID(guid), pPtr);
|
||||
}
|
||||
|
||||
STDMETHODIMP XPCDispatchTearOff::GetTypeInfoCount(unsigned int FAR * pctinfo)
|
||||
|
@ -265,11 +222,11 @@ xpcWrappedJSErrorReporter(JSContext *cx, const char *message,
|
|||
JSErrorReport *report);
|
||||
|
||||
STDMETHODIMP XPCDispatchTearOff::Invoke(DISPID dispIdMember, REFIID riid,
|
||||
LCID lcid, WORD wFlags,
|
||||
DISPPARAMS FAR* pDispParams,
|
||||
VARIANT FAR* pVarResult,
|
||||
EXCEPINFO FAR* pExcepInfo,
|
||||
unsigned int FAR* puArgErr)
|
||||
LCID lcid, WORD wFlags,
|
||||
DISPPARAMS FAR* pDispParams,
|
||||
VARIANT FAR* pVarResult,
|
||||
EXCEPINFO FAR* pExcepInfo,
|
||||
unsigned int FAR* puArgErr)
|
||||
{
|
||||
XPCDispTypeInfo* pTypeInfo = GetCOMTypeInfo();
|
||||
if(!pTypeInfo)
|
||||
|
@ -290,8 +247,9 @@ STDMETHODIMP XPCDispatchTearOff::Invoke(DISPID dispIdMember, REFIID riid,
|
|||
cx = nsnull;
|
||||
}
|
||||
// Get the name as a flat string
|
||||
const nsACString & xname = pTypeInfo->GetNameForDispID(dispIdMember);
|
||||
const nsPromiseFlatCString & name = PromiseFlatCString(xname);
|
||||
// This isn't that efficient, but we have to make the conversion somewhere
|
||||
const nsAString & xname = pTypeInfo->GetNameForDispID(dispIdMember);
|
||||
const nsPromiseFlatCString & name = PromiseFlatCString(NS_LossyConvertUCS2toASCII(xname));
|
||||
if(name.IsEmpty())
|
||||
return E_FAIL;
|
||||
// Decide if this is a getter or setter
|
||||
|
@ -309,17 +267,17 @@ STDMETHODIMP XPCDispatchTearOff::Invoke(DISPID dispIdMember, REFIID riid,
|
|||
obj = GetJSObject();
|
||||
if(!obj)
|
||||
return E_FAIL;
|
||||
if (!JS_GetProperty(cx, obj, name.get(), &val))
|
||||
if(!JS_GetProperty(cx, obj, name.get(), &val))
|
||||
{
|
||||
nsCString msg("Unable to retrieve property ");
|
||||
msg += xname;
|
||||
return Error(E_FAIL, msg);
|
||||
msg += name;
|
||||
return Error(E_FAIL, msg.get());
|
||||
}
|
||||
if(!XPCDispConvert::JSToCOM(ccx, val, *pVarResult, err))
|
||||
{
|
||||
nsCString msg("Failed to convert value from JS property ");
|
||||
msg += xname;
|
||||
return Error(E_FAIL, msg);
|
||||
msg += name;
|
||||
return Error(E_FAIL, msg.get());
|
||||
}
|
||||
}
|
||||
else if(pDispParams->cArgs > 0)
|
||||
|
@ -328,17 +286,17 @@ STDMETHODIMP XPCDispatchTearOff::Invoke(DISPID dispIdMember, REFIID riid,
|
|||
if(!XPCDispConvert::COMToJS(ccx, pDispParams->rgvarg[0], val, err))
|
||||
{
|
||||
nsCString msg("Failed to convert value for JS property ");
|
||||
msg += xname;
|
||||
return Error(E_FAIL, msg);
|
||||
msg += name;
|
||||
return Error(E_FAIL, msg.get());
|
||||
}
|
||||
obj = GetJSObject();
|
||||
if(!obj)
|
||||
return Error(E_FAIL, "The JS wrapper did not return a JS object");
|
||||
if (!JS_SetProperty(cx, obj, name.get(), &val))
|
||||
if(!JS_SetProperty(cx, obj, name.get(), &val))
|
||||
{
|
||||
nsCString msg("Unable to set property ");
|
||||
msg += xname;
|
||||
return Error(E_FAIL, msg);
|
||||
msg += name;
|
||||
return Error(E_FAIL, msg.get());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -347,7 +305,7 @@ STDMETHODIMP XPCDispatchTearOff::Invoke(DISPID dispIdMember, REFIID riid,
|
|||
jsval* stackbase;
|
||||
jsval* sp = nsnull;
|
||||
uint8 i;
|
||||
uint8 argc=pDispParams->cArgs;
|
||||
uint8 argc = pDispParams->cArgs;
|
||||
uint8 stack_size;
|
||||
jsval result;
|
||||
uint8 paramCount=0;
|
||||
|
@ -485,7 +443,7 @@ pre_call_clean_up:
|
|||
fp = oldfp = cx->fp;
|
||||
if(!fp)
|
||||
{
|
||||
memset(&frame, 0, sizeof frame);
|
||||
memset(&frame, 0, sizeof(frame));
|
||||
cx->fp = fp = &frame;
|
||||
}
|
||||
oldsp = fp->sp;
|
||||
|
@ -545,7 +503,7 @@ pre_call_clean_up:
|
|||
}
|
||||
JS_ClearPendingException(cx);
|
||||
}
|
||||
|
||||
// TODO: This exception logic needs to be refactored and shared with wrapped JS
|
||||
if(xpc_exception)
|
||||
{
|
||||
nsresult e_result;
|
||||
|
|
|
@ -49,6 +49,9 @@
|
|||
|
||||
#include "xpcprivate.h"
|
||||
|
||||
// There's no CPP for XPCDispNameArray so it's just plopped here
|
||||
const nsString XPCDispNameArray::sEmpty;
|
||||
|
||||
/**
|
||||
* Helper function that initializes the element description
|
||||
* @param vt The type of variant
|
||||
|
@ -96,7 +99,7 @@ ELEMDESC* XPCDispJSPropertyInfo::GetParamInfo()
|
|||
if(paramCount != 0)
|
||||
{
|
||||
elemDesc = new ELEMDESC[paramCount];
|
||||
if (elemDesc)
|
||||
if(elemDesc)
|
||||
{
|
||||
for(PRUint32 index = 0; index < paramCount; ++index)
|
||||
{
|
||||
|
@ -114,20 +117,21 @@ XPCDispJSPropertyInfo::XPCDispJSPropertyInfo(JSContext* cx, PRUint32 memid,
|
|||
JSObject* obj, jsval val) :
|
||||
mPropertyType(INVALID), mMemID(memid)
|
||||
{
|
||||
const char* chars = xpc_JSString2Char(cx, val);
|
||||
PRUint32 len;
|
||||
jschar * chars = xpc_JSString2String(cx, val, &len);
|
||||
if(!chars)
|
||||
return;
|
||||
|
||||
mName = chars;
|
||||
mName = nsString(chars, len);
|
||||
JSBool found;
|
||||
uintN attr;
|
||||
// Get the property's attributes, and make sure it's found and enumerable
|
||||
if(!JS_GetPropertyAttributes(cx, obj, chars, &attr, &found) ||
|
||||
if(!JS_GetUCPropertyAttributes(cx, obj, chars, len, &attr, &found) ||
|
||||
!found || (attr & JSPROP_ENUMERATE) == 0)
|
||||
return;
|
||||
|
||||
// Retrieve the property
|
||||
if(!chars || !JS_GetProperty(cx, obj, chars, &mProperty) ||
|
||||
if(!chars || !JS_GetUCProperty(cx, obj, chars, len, &mProperty) ||
|
||||
JSVAL_IS_NULL(mProperty))
|
||||
return;
|
||||
|
||||
|
@ -160,6 +164,7 @@ XPCDispJSPropertyInfo::XPCDispJSPropertyInfo(JSContext* cx, PRUint32 memid,
|
|||
PRBool XPCDispTypeInfo::FuncDescArray::BuildFuncDesc(XPCCallContext& ccx, JSObject* obj,
|
||||
XPCDispJSPropertyInfo & propInfo)
|
||||
{
|
||||
// While this memory is passed out, we're ultimately responsible to free it
|
||||
FUNCDESC* funcDesc = new FUNCDESC;
|
||||
if(!funcDesc)
|
||||
return PR_FALSE;
|
||||
|
@ -226,10 +231,6 @@ XPCDispTypeInfo::XPCDispTypeInfo(XPCCallContext& ccx, JSObject* obj,
|
|||
|
||||
XPCDispTypeInfo * XPCDispTypeInfo::New(XPCCallContext& ccx, JSObject* obj)
|
||||
{
|
||||
nsresult retval = NS_ERROR_FAILURE;
|
||||
// Saved state must be restored
|
||||
JSExceptionState* saved_exception = xpc_DoPreScriptEvaluated(ccx);
|
||||
JSErrorReporter older = JS_SetErrorReporter(ccx, nsnull);
|
||||
XPCDispTypeInfo * pTypeInfo = 0;
|
||||
JSIdArray * jsArray = JS_Enumerate(ccx, obj);
|
||||
if(!jsArray)
|
||||
|
@ -243,15 +244,13 @@ XPCDispTypeInfo * XPCDispTypeInfo::New(XPCCallContext& ccx, JSObject* obj)
|
|||
delete array;
|
||||
return nsnull;
|
||||
}
|
||||
JS_SetErrorReporter(ccx, older);
|
||||
xpc_DoPostScriptEvaluated(ccx, saved_exception);
|
||||
|
||||
NS_ADDREF(pTypeInfo);
|
||||
return pTypeInfo;
|
||||
}
|
||||
|
||||
NS_COM_MAP_BEGIN(XPCDispTypeInfo)
|
||||
NS_COM_MAP_ENTRY(ITypeInfo)
|
||||
NS_COM_MAP_ENTRY(IUnknown)
|
||||
NS_COM_MAP_ENTRY(ITypeInfo)
|
||||
NS_COM_MAP_ENTRY(IUnknown)
|
||||
NS_COM_MAP_END
|
||||
|
||||
NS_IMPL_THREADSAFE_ADDREF(XPCDispTypeInfo)
|
||||
|
@ -312,14 +311,12 @@ STDMETHODIMP XPCDispTypeInfo::GetIDsOfNames(
|
|||
/* [in] */ UINT cNames,
|
||||
/* [size_is][out] */ MEMBERID __RPC_FAR *pMemId)
|
||||
{
|
||||
_bstr_t name;
|
||||
// lookup each name
|
||||
for(UINT index = 0; index < cNames; ++index)
|
||||
{
|
||||
// This can probably be streamlined, I wasn't sure if
|
||||
// we could go safely from LPOLESTR to nsDependentString
|
||||
name = rgszNames[index];
|
||||
nsDependentCString buffer(NS_STATIC_CAST(const char *,name));
|
||||
nsDependentString buffer(NS_STATIC_CAST(const PRUnichar *,
|
||||
rgszNames[index]),
|
||||
SysStringLen(rgszNames[index]));
|
||||
pMemId[index] = mNameArray.Find(buffer);
|
||||
|
||||
}
|
||||
|
@ -335,16 +332,13 @@ STDMETHODIMP XPCDispTypeInfo::Invoke(
|
|||
/* [out] */ EXCEPINFO __RPC_FAR *pExcepInfo,
|
||||
/* [out] */ UINT __RPC_FAR *puArgErr)
|
||||
{
|
||||
IUnknown* ptr = NS_REINTERPRET_CAST(IUnknown*,pvInstance);
|
||||
IDispatch* pDisp;
|
||||
HRESULT result = ptr->QueryInterface(IID_IDispatch,
|
||||
NS_REINTERPRET_CAST(void**,&pDisp));
|
||||
if(SUCCEEDED(result))
|
||||
CComQIPtr<IDispatch> pDisp(NS_REINTERPRET_CAST(IUnknown*,pvInstance));
|
||||
if(pDisp)
|
||||
{
|
||||
result = pDisp->Invoke(memid, IID_NULL, LOCALE_SYSTEM_DEFAULT, wFlags,
|
||||
return pDisp->Invoke(memid, IID_NULL, LOCALE_SYSTEM_DEFAULT, wFlags,
|
||||
pDispParams, pVarResult, pExcepInfo, puArgErr);
|
||||
}
|
||||
return result;
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
|
||||
STDMETHODIMP XPCDispTypeInfo::GetDocumentation(
|
||||
|
|
|
@ -41,39 +41,45 @@ static const char* const IDISPATCH_NAME = "IDispatch";
|
|||
PRBool XPCIDispatchExtension::mIsEnabled = PR_TRUE;
|
||||
|
||||
static JSBool
|
||||
CommonConstructor(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
||||
jsval *rval, PRBool testScriptability)
|
||||
CommonConstructor(XPCCallContext &ccx, JSObject *obj, uintN argc, jsval *argv,
|
||||
jsval *rval, PRBool testScriptability)
|
||||
{
|
||||
// Check if IDispatch is enabled, fail if not
|
||||
if (!nsXPConnect::IsIDispatchEnabled())
|
||||
{
|
||||
XPCThrower::Throw(NS_ERROR_XPC_IDISPATCH_NOT_ENABLED, ccx);
|
||||
return JS_FALSE;
|
||||
}
|
||||
// Make sure we were called with one string parameter
|
||||
if(argc != 1 || (argc == 1 && !JSVAL_IS_STRING(argv[0])))
|
||||
{
|
||||
XPCThrower::Throw(NS_ERROR_XPC_COM_INVALID_CLASS_ID, cx);
|
||||
XPCThrower::Throw(NS_ERROR_XPC_COM_INVALID_CLASS_ID, ccx);
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
const char * bytes = xpc_JSString2Char(cx, argv[0]);
|
||||
if(!bytes)
|
||||
PRUint32 len;
|
||||
jschar * className = xpc_JSString2String(ccx, argv[0], &len);
|
||||
CComBSTR bstrClassName(len, className);
|
||||
if(!className)
|
||||
{
|
||||
XPCThrower::Throw(NS_ERROR_XPC_COM_INVALID_CLASS_ID, cx);
|
||||
XPCThrower::Throw(NS_ERROR_XPC_COM_INVALID_CLASS_ID, ccx);
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
// Instantiate the desired COM object
|
||||
IDispatch* pDispatch = nsnull;;
|
||||
HRESULT rv = XPCDispObject::COMCreateInstance(bytes, testScriptability, &pDispatch);
|
||||
CComPtr<IDispatch> pDispatch;
|
||||
HRESULT rv = XPCDispObject::COMCreateInstance(bstrClassName, testScriptability, &pDispatch);
|
||||
if(FAILED(rv))
|
||||
{
|
||||
XPCThrower::ThrowCOMError(cx, rv, NS_ERROR_XPC_COM_CREATE_FAILED);
|
||||
XPCThrower::ThrowCOMError(ccx, rv, NS_ERROR_XPC_COM_CREATE_FAILED);
|
||||
return JS_FALSE;
|
||||
}
|
||||
// Get a wrapper for our object
|
||||
nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
|
||||
nsresult nsrv = nsXPConnect::GetXPConnect()->WrapNative(cx, obj,
|
||||
NS_REINTERPRET_CAST(nsISupports*, pDispatch),
|
||||
NSID_IDISPATCH, getter_AddRefs(holder));
|
||||
nsresult nsrv = ccx.GetXPConnect()->WrapNative(
|
||||
ccx, obj, NS_REINTERPRET_CAST(nsISupports*, pDispatch.p), NSID_IDISPATCH,
|
||||
getter_AddRefs(holder));
|
||||
if(NS_FAILED(nsrv))
|
||||
{
|
||||
XPCThrower::Throw(nsrv, cx);
|
||||
XPCThrower::Throw(nsrv, ccx);
|
||||
return JS_FALSE;
|
||||
}
|
||||
// get and return the JS object wrapper
|
||||
|
@ -81,7 +87,7 @@ CommonConstructor(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
|||
nsrv = holder->GetJSObject(&jsobj);
|
||||
if(NS_FAILED(nsrv))
|
||||
{
|
||||
XPCThrower::Throw(nsrv, cx);
|
||||
XPCThrower::Throw(nsrv, ccx);
|
||||
return JS_FALSE;
|
||||
}
|
||||
*rval = OBJECT_TO_JSVAL(jsobj);
|
||||
|
@ -92,20 +98,21 @@ JS_STATIC_DLL_CALLBACK(JSBool)
|
|||
COMObjectConstructor(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
||||
jsval *rval)
|
||||
{
|
||||
return CommonConstructor(cx, obj, argc, argv, rval, PR_FALSE);
|
||||
XPCCallContext ccx(JS_CALLER, cx, obj);
|
||||
return CommonConstructor(ccx, obj, argc, argv, rval, PR_FALSE);
|
||||
}
|
||||
|
||||
JS_STATIC_DLL_CALLBACK(JSBool)
|
||||
ActiveXConstructor(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
||||
jsval *rval)
|
||||
jsval *rval)
|
||||
{
|
||||
return CommonConstructor(cx, obj, argc, argv, rval, PR_TRUE);
|
||||
XPCCallContext ccx(JS_CALLER, cx, obj);
|
||||
return CommonConstructor(ccx, obj, argc, argv, rval, PR_TRUE);
|
||||
}
|
||||
|
||||
JSBool XPCIDispatchExtension::Initialize(JSContext * aJSContext,
|
||||
JSObject * aGlobalJSObj)
|
||||
JSObject * aGlobalJSObj)
|
||||
{
|
||||
// TODO: Cleanup error code
|
||||
JSBool result = JS_DefineFunction(aJSContext, aGlobalJSObj, "ActiveXObject",
|
||||
ActiveXConstructor, 1, 0) != nsnull;
|
||||
#ifdef XPC_COMOBJECT
|
||||
|
@ -121,6 +128,8 @@ JSBool XPCIDispatchExtension::DefineProperty(XPCCallContext & ccx,
|
|||
XPCWrappedNative* wrapperToReflectInterfaceNames,
|
||||
uintN propFlags, JSBool* resolved)
|
||||
{
|
||||
if(!JSVAL_IS_STRING(idval))
|
||||
return JS_FALSE;
|
||||
// Look up the native interface for IDispatch and then find a tearoff
|
||||
XPCNativeInterface* iface = XPCNativeInterface::GetNewOrUsed(ccx,
|
||||
"IDispatch");
|
||||
|
@ -135,8 +144,6 @@ JSBool XPCIDispatchExtension::DefineProperty(XPCCallContext & ccx,
|
|||
if(jso == nsnull)
|
||||
return JS_FALSE;
|
||||
// Look up the member in the interface
|
||||
if(!JSVAL_IS_STRING(idval))
|
||||
return JS_FALSE;
|
||||
const XPCDispInterface::Member * member = to->GetIDispatchInfo()->FindMember(idval);
|
||||
if(!member)
|
||||
{
|
||||
|
@ -152,6 +159,9 @@ JSBool XPCIDispatchExtension::DefineProperty(XPCCallContext & ccx,
|
|||
jsval funval;
|
||||
if(!member->GetValue(ccx, iface, &funval))
|
||||
return JS_FALSE;
|
||||
// Protect the jsval
|
||||
AUTO_MARK_JSVAL(ccx, funval);
|
||||
// clone a function we can use for this object
|
||||
JSObject* funobj = JS_CloneFunctionObject(ccx, JSVAL_TO_OBJECT(funval), obj);
|
||||
if(!funobj)
|
||||
return JS_FALSE;
|
||||
|
@ -222,6 +232,11 @@ nsresult XPCIDispatchExtension::IDispatchQIWrappedJS(nsXPCWrappedJS * self,
|
|||
*aInstancePtr = nsnull;
|
||||
return NS_NOINTERFACE;
|
||||
}
|
||||
*aInstancePtr = NS_STATIC_CAST(XPCDispatchTearOff*, new XPCDispatchTearOff(root));
|
||||
XPCDispatchTearOff* tearOff = new XPCDispatchTearOff(root);
|
||||
if(!tearOff)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
tearOff->AddRef();
|
||||
*aInstancePtr = tearOff;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -96,11 +96,15 @@ NS_IMETHODIMP nsDispatchSupport::JSVal2COMVariant(jsval val, VARIANT * comvar)
|
|||
* @param result pointer to an IDispatch to receive the pointer to the instance
|
||||
* @return nsresult
|
||||
*/
|
||||
NS_IMETHODIMP nsDispatchSupport::CreateInstance(const char * className,
|
||||
NS_IMETHODIMP nsDispatchSupport::CreateInstance(const nsAString & className,
|
||||
PRBool testScriptability,
|
||||
IDispatch ** result)
|
||||
{
|
||||
return XPCDispObject::COMCreateInstance(className, testScriptability, result);
|
||||
if (!nsXPConnect::IsIDispatchEnabled())
|
||||
return NS_ERROR_XPC_IDISPATCH_NOT_ENABLED;
|
||||
const nsPromiseFlatString & flat = PromiseFlatString(className);
|
||||
CComBSTR name(flat.Length(), flat.get());
|
||||
return XPCDispObject::COMCreateInstance(name, testScriptability, result);
|
||||
}
|
||||
|
||||
nsDispatchSupport* nsDispatchSupport::GetSingleton()
|
||||
|
|
|
@ -162,4 +162,5 @@ XPC_MSG_DEF(NS_ERROR_XPC_COM_UNKNOWN , "Unknown COM error occured
|
|||
XPC_MSG_DEF(NS_ERROR_XPC_COM_ERROR , "COM Error")
|
||||
XPC_MSG_DEF(NS_ERROR_XPC_COM_INVALID_CLASS_ID , "Invalid class ID")
|
||||
XPC_MSG_DEF(NS_ERROR_XPC_COM_CREATE_FAILED , "Unable to create an instance of the desired COM class")
|
||||
XPC_MSG_DEF(NS_ERROR_XPC_IDISPATCH_NOT_ENABLED , "IDispatch support is not enabled")
|
||||
#endif
|
||||
|
|
|
@ -1069,6 +1069,47 @@ XPCConvert::NativeInterface2JSObject(XPCCallContext& ccx,
|
|||
return JS_FALSE;
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
// static
|
||||
JSBool XPCConvert::GetNativeInterfaceFromJSObject(XPCCallContext& ccx,
|
||||
void** dest, JSObject* src,
|
||||
const nsID* iid,
|
||||
nsresult* pErr)
|
||||
{
|
||||
nsISupports* identity;
|
||||
// Note that if we have a non-null aOuter then it means that we are
|
||||
// forcing the creation of a wrapper even if the object *is* a
|
||||
// wrappedNative or other wise has 'nsISupportness'.
|
||||
// This allows wrapJSAggregatedToNative to work.
|
||||
|
||||
// Is this really a native xpcom object with a wrapper?
|
||||
XPCWrappedNative* wrappedNative =
|
||||
XPCWrappedNative::GetWrappedNativeOfJSObject(ccx, src);
|
||||
if(wrappedNative)
|
||||
{
|
||||
identity = wrappedNative->GetIdentityObject();
|
||||
// is the underlying object the right interface?
|
||||
if(wrappedNative->GetIID().Equals(*iid))
|
||||
{
|
||||
NS_ADDREF(identity);
|
||||
*dest = identity;
|
||||
return JS_TRUE;
|
||||
}
|
||||
else
|
||||
return NS_SUCCEEDED(identity->QueryInterface(*iid, dest));
|
||||
}
|
||||
// else...
|
||||
|
||||
// Does the JSObject have 'nsISupportness'?
|
||||
// XXX hmm, I wonder if this matters anymore with no
|
||||
// oldstyle DOM objects around.
|
||||
if(GetISupportsFromJSObject(ccx, src, &identity) && identity)
|
||||
{
|
||||
return NS_SUCCEEDED(identity->QueryInterface(*iid, dest));
|
||||
}
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
// static
|
||||
|
@ -1089,46 +1130,14 @@ XPCConvert::JSObject2NativeInterface(XPCCallContext& ccx,
|
|||
if(pErr)
|
||||
*pErr = NS_ERROR_XPC_BAD_CONVERT_JS;
|
||||
|
||||
nsISupports* iface;
|
||||
|
||||
if(!aOuter)
|
||||
{
|
||||
// Note that if we have a non-null aOuter then it means that we are
|
||||
// forcing the creation of a wrapper even if the object *is* a
|
||||
// wrappedNative or other wise has 'nsISupportness'.
|
||||
// This allows wrapJSAggregatedToNative to work.
|
||||
|
||||
// Is this really a native xpcom object with a wrapper?
|
||||
XPCWrappedNative* wrappedNative =
|
||||
XPCWrappedNative::GetWrappedNativeOfJSObject(cx, src);
|
||||
if(wrappedNative)
|
||||
{
|
||||
iface = wrappedNative->GetIdentityObject();
|
||||
// is the underlying object the right interface?
|
||||
if(wrappedNative->GetIID().Equals(*iid))
|
||||
{
|
||||
NS_ADDREF(iface);
|
||||
*dest = iface;
|
||||
return JS_TRUE;
|
||||
}
|
||||
else
|
||||
return NS_SUCCEEDED(iface->QueryInterface(*iid, dest));
|
||||
}
|
||||
// else...
|
||||
|
||||
// Does the JSObject have 'nsISupportness'?
|
||||
// XXX hmm, I wonder if this matters anymore with no
|
||||
// oldstyle DOM objects around.
|
||||
if(GetISupportsFromJSObject(cx, src, &iface))
|
||||
{
|
||||
if(iface)
|
||||
return NS_SUCCEEDED(iface->QueryInterface(*iid, dest));
|
||||
return JS_FALSE;
|
||||
|
||||
}
|
||||
// See if this is really an wrapped XPCOM object
|
||||
if(GetNativeInterfaceFromJSObject(ccx, dest, src, iid, pErr))
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
// else...
|
||||
// else create a new wrapper
|
||||
|
||||
nsXPCWrappedJS* wrapper;
|
||||
nsresult rv = nsXPCWrappedJS::GetNewOrUsed(ccx, src, *iid, aOuter, &wrapper);
|
||||
|
|
|
@ -96,6 +96,7 @@ struct IDispatch;
|
|||
class XPCDispParams;
|
||||
class XPCDispJSPropertyInfo;
|
||||
class nsIXPConnectWrappedJS;
|
||||
class XPCIDispatchExtension;
|
||||
#endif
|
||||
|
||||
|
||||
|
|
|
@ -566,10 +566,13 @@ inline
|
|||
JSObject* XPCWrappedNativeTearOff::GetJSObject() const
|
||||
{
|
||||
#ifdef XPC_IDISPATCH_SUPPORT
|
||||
return IsIDispatch() ? GetIDispatchInfo()->GetJSObject() : mJSObject;
|
||||
#else
|
||||
return mJSObject;
|
||||
if(IsIDispatch())
|
||||
{
|
||||
XPCDispInterface * iface = GetIDispatchInfo();
|
||||
return iface ? iface->GetJSObject() : nsnull;
|
||||
}
|
||||
#endif
|
||||
return mJSObject;
|
||||
}
|
||||
|
||||
inline
|
||||
|
@ -577,7 +580,11 @@ void XPCWrappedNativeTearOff::SetJSObject(JSObject* JSObj)
|
|||
{
|
||||
#ifdef XPC_IDISPATCH_SUPPORT
|
||||
if(IsIDispatch())
|
||||
GetIDispatchInfo()->SetJSObject(JSObj);
|
||||
{
|
||||
XPCDispInterface* iface = GetIDispatchInfo();
|
||||
if (iface)
|
||||
iface->SetJSObject(JSObj);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
mJSObject = JSObj;
|
||||
|
@ -595,6 +602,8 @@ XPCWrappedNativeTearOff::SetIDispatch(JSContext* cx)
|
|||
inline XPCDispInterface*
|
||||
XPCWrappedNativeTearOff::GetIDispatchInfo() const
|
||||
{
|
||||
NS_ASSERTION((jsword)mJSObject & 2, "XPCWrappedNativeTearOff::GetIDispatchInfo "
|
||||
"called on a non IDispatch interface");
|
||||
return NS_REINTERPRET_CAST(XPCDispInterface*,
|
||||
(((jsword)mJSObject) & ~JSOBJECT_MASK));
|
||||
}
|
||||
|
|
|
@ -86,13 +86,13 @@ static const nsModuleComponentInfo components[] = {
|
|||
// jsloader stuff
|
||||
{ "JS component loader", MOZJSCOMPONENTLOADER_CID,
|
||||
mozJSComponentLoaderContractID, mozJSComponentLoaderConstructor,
|
||||
RegisterJSLoader, UnregisterJSLoader },
|
||||
RegisterJSLoader, UnregisterJSLoader }
|
||||
#ifndef NO_SUBSCRIPT_LOADER
|
||||
{ "JS subscript loader", MOZ_JSSUBSCRIPTLOADER_CID,
|
||||
mozJSSubScriptLoadContractID, mozJSSubScriptLoaderConstructor },
|
||||
,{ "JS subscript loader", MOZ_JSSUBSCRIPTLOADER_CID,
|
||||
mozJSSubScriptLoadContractID, mozJSSubScriptLoaderConstructor }
|
||||
#endif
|
||||
#ifdef XPC_IDISPATCH_SUPPORT
|
||||
{ nsnull, NS_IDISPATCH_SUPPORT_CID, NS_IDISPATCH_SUPPORT_CONTRACTID,
|
||||
,{ nsnull, NS_IDISPATCH_SUPPORT_CID, NS_IDISPATCH_SUPPORT_CONTRACTID,
|
||||
nsIDispatchSupportConstructor }
|
||||
#endif
|
||||
};
|
||||
|
|
|
@ -114,19 +114,13 @@
|
|||
#endif
|
||||
|
||||
#ifdef XPC_IDISPATCH_SUPPORT
|
||||
// This goop was added because of EXCEPINFO in ThrowCOMError
|
||||
// This include is here, because it needs to occur before the undefines below
|
||||
#include <atlbase.h>
|
||||
#include <comdef.h>
|
||||
|
||||
extern CComModule _Module;
|
||||
|
||||
#include <atlcom.h>
|
||||
#include <atlctl.h>
|
||||
// MS clutters the global namespace with so many macro names :-(
|
||||
// I tried to keep these includes in the CPP's but it became too
|
||||
// convoluted
|
||||
#include "oaidl.h"
|
||||
// Nasty MS defines
|
||||
#undef GetClassInfo
|
||||
#undef GetClassName
|
||||
#undef interface
|
||||
#undef GetMessage
|
||||
#endif
|
||||
|
||||
|
@ -381,10 +375,6 @@ private:
|
|||
static void operator delete(void* /*memory*/) {}
|
||||
};
|
||||
|
||||
#ifdef XPC_IDISPATCH_SUPPORT
|
||||
class XPCIDispatchExtension;
|
||||
#endif
|
||||
|
||||
/***************************************************************************
|
||||
****************************************************************************
|
||||
*
|
||||
|
@ -1704,7 +1694,6 @@ public:
|
|||
JSOBJECT_MASK = 3
|
||||
};
|
||||
void SetIDispatch(JSContext* cx);
|
||||
JSObject* Get() const;
|
||||
JSBool IsIDispatch() const;
|
||||
XPCDispInterface* GetIDispatchInfo() const;
|
||||
#endif
|
||||
|
@ -2265,13 +2254,10 @@ public:
|
|||
const nsID* iid,
|
||||
JSObject* scope, nsresult* pErr);
|
||||
|
||||
#ifdef XPC_IDISPATCH_SUPPORT
|
||||
static JSBool NativeInterface2JSObject(XPCCallContext& ccx,
|
||||
nsIXPConnectJSObjectHolder** dest,
|
||||
IDispatch* src,
|
||||
JSObject* scope, nsresult* pErr);
|
||||
#endif
|
||||
|
||||
static JSBool GetNativeInterfaceFromJSObject(XPCCallContext& ccx,
|
||||
void** dest, JSObject* src,
|
||||
const nsID* iid,
|
||||
nsresult* pErr);
|
||||
static JSBool JSObject2NativeInterface(XPCCallContext& ccx,
|
||||
void** dest, JSObject* src,
|
||||
const nsID* iid,
|
||||
|
@ -2462,7 +2448,9 @@ public:
|
|||
static void ThrowBadResult(nsresult rv, nsresult result, XPCCallContext& ccx);
|
||||
static void ThrowBadParam(nsresult rv, uintN paramNum, XPCCallContext& ccx);
|
||||
#ifdef XPC_IDISPATCH_SUPPORT
|
||||
static void ThrowCOMError(JSContext* cx, HRESULT COMErrorCode, nsresult rv = NS_ERROR_XPC_COM_ERROR);
|
||||
static void ThrowCOMError(JSContext* cx, unsigned long COMErrorCode,
|
||||
nsresult rv = NS_ERROR_XPC_COM_ERROR,
|
||||
const EXCEPINFO * exception = nsnull);
|
||||
#endif
|
||||
static JSBool SetVerbosity(JSBool state)
|
||||
{JSBool old = sVerbose; sVerbose = state; return old;}
|
||||
|
@ -3115,12 +3103,14 @@ class XPCMarkableJSVal
|
|||
public:
|
||||
XPCMarkableJSVal(jsval val) : mVal(val), mValPtr(&mVal) {}
|
||||
XPCMarkableJSVal(jsval *pval) : mVal(0), mValPtr(pval) {}
|
||||
~XPCMarkableJSVal() {}
|
||||
void Mark() {}
|
||||
void MarkBeforeJSFinalize(JSContext* cx)
|
||||
{if(JSVAL_IS_GCTHING(*mValPtr))
|
||||
JS_MarkGCThing(cx, JSVAL_TO_GCTHING(*mValPtr),
|
||||
"XPCMarkableJSVal", nsnull);}
|
||||
private:
|
||||
XPCMarkableJSVal(); // not implemented
|
||||
jsval mVal;
|
||||
jsval* mValPtr;
|
||||
};
|
||||
|
|
|
@ -155,11 +155,37 @@ XPCThrower::Verbosify(XPCCallContext& ccx,
|
|||
|
||||
if(ccx.HasInterfaceAndMember())
|
||||
{
|
||||
XPCNativeInterface* interface = ccx.GetInterface();
|
||||
XPCNativeInterface* iface = ccx.GetInterface();
|
||||
#ifdef XPC_IDISPATCH_SUPPORT
|
||||
NS_ASSERTION(ccx.GetIDispatchMember() == nsnull ||
|
||||
ccx.GetMember() == nsnull,
|
||||
"Both IDispatch member and regular XPCOM member "
|
||||
"were set in XPCCallContext");
|
||||
char const * name;
|
||||
if(ccx.GetIDispatchMember())
|
||||
{
|
||||
XPCDispInterface::Member * member =
|
||||
NS_REINTERPRET_CAST(XPCDispInterface::Member*,
|
||||
ccx.GetIDispatchMember());
|
||||
if(member && JSVAL_IS_STRING(member->GetName()))
|
||||
{
|
||||
name = JS_GetStringBytes(JSVAL_TO_STRING(member->GetName()));
|
||||
}
|
||||
else
|
||||
name = "Unknown";
|
||||
}
|
||||
else
|
||||
name = iface->GetMemberName(ccx, ccx.GetMember());
|
||||
sz = JS_smprintf("%s [%s.%s]",
|
||||
*psz,
|
||||
interface->GetNameString(),
|
||||
interface->GetMemberName(ccx, ccx.GetMember()));
|
||||
iface->GetNameString(),
|
||||
name);
|
||||
#else
|
||||
sz = JS_smprintf("%s [%s.%s]",
|
||||
*psz,
|
||||
iface->GetNameString(),
|
||||
iface->GetMemberName(ccx, ccx.GetMember()));
|
||||
#endif
|
||||
}
|
||||
|
||||
if(sz)
|
||||
|
@ -246,47 +272,57 @@ XPCThrower::ThrowExceptionObject(JSContext* cx, nsIException* e)
|
|||
#ifdef XPC_IDISPATCH_SUPPORT
|
||||
// static
|
||||
void
|
||||
XPCThrower::ThrowCOMError(JSContext* cx, HRESULT COMErrorCode, nsresult rv)
|
||||
XPCThrower::ThrowCOMError(JSContext* cx, unsigned long COMErrorCode,
|
||||
nsresult rv, const EXCEPINFO * exception)
|
||||
{
|
||||
nsCAutoString msg;
|
||||
IErrorInfo * pError;
|
||||
// Get the current COM error object
|
||||
HRESULT result = GetErrorInfo(0, &pError);
|
||||
if(SUCCEEDED(result) && pError)
|
||||
{
|
||||
// Build an error message from the COM error object
|
||||
BSTR bstrDesc = nsnull;
|
||||
BSTR bstrSource = nsnull;
|
||||
if(SUCCEEDED(pError->GetSource(&bstrSource)) && bstrSource)
|
||||
{
|
||||
msg = NS_STATIC_CAST(const char *,_bstr_t(bstrSource, FALSE));
|
||||
msg += " : ";
|
||||
}
|
||||
char buffer[9];
|
||||
sprintf(buffer, "%0X", COMErrorCode);
|
||||
msg += buffer;
|
||||
if(SUCCEEDED(pError->GetDescription(&bstrDesc)) && bstrDesc)
|
||||
{
|
||||
msg += " - ";
|
||||
msg += NS_STATIC_CAST(const char *,_bstr_t(bstrDesc, FALSE));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// No error object, so just report the result
|
||||
const char* format;
|
||||
if(!nsXPCException::NameAndFormatForNSResult(rv, nsnull, &format))
|
||||
format = "";
|
||||
char buffer[48];
|
||||
sprintf(buffer, "COM Error Result = %0X", COMErrorCode);
|
||||
msg = buffer;
|
||||
}
|
||||
const char * format;
|
||||
if(!nsXPCException::NameAndFormatForNSResult(rv, nsnull, &format))
|
||||
format = "";
|
||||
char * finalMsg = JS_smprintf("%s - %s", format, PromiseFlatCString(msg).get());
|
||||
XPCThrower::BuildAndThrowException(cx, rv, finalMsg);
|
||||
JS_smprintf_free(finalMsg);
|
||||
msg = format;
|
||||
if(exception)
|
||||
{
|
||||
msg += NS_STATIC_CAST(const char *,
|
||||
_bstr_t(exception->bstrSource, false));
|
||||
msg += " : ";
|
||||
msg.AppendInt(COMErrorCode);
|
||||
msg += " - ";
|
||||
msg += NS_STATIC_CAST(const char *,
|
||||
_bstr_t(exception->bstrDescription, false));
|
||||
}
|
||||
else
|
||||
{
|
||||
// Get the current COM error object
|
||||
unsigned long result = GetErrorInfo(0, &pError);
|
||||
if(SUCCEEDED(result) && pError)
|
||||
{
|
||||
// Build an error message from the COM error object
|
||||
BSTR bstrSource = NULL;
|
||||
if(SUCCEEDED(pError->GetSource(&bstrSource)) && bstrSource)
|
||||
{
|
||||
_bstr_t src(bstrSource, false);
|
||||
msg += NS_STATIC_CAST(const char *,src);
|
||||
msg += " : ";
|
||||
}
|
||||
msg.AppendInt(COMErrorCode, 16);
|
||||
BSTR bstrDesc = NULL;
|
||||
if(SUCCEEDED(pError->GetDescription(&bstrDesc)) && bstrDesc)
|
||||
{
|
||||
msg += " - ";
|
||||
_bstr_t desc(bstrDesc, false);
|
||||
msg += NS_STATIC_CAST(const char *,desc);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// No error object, so just report the result
|
||||
msg += "COM Error Result = ";
|
||||
msg.AppendInt(COMErrorCode, 16);
|
||||
}
|
||||
}
|
||||
|
||||
XPCThrower::BuildAndThrowException(cx, rv, msg.get());
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -216,7 +216,7 @@ XPCWrappedNative::GetNewOrUsed(XPCCallContext& ccx,
|
|||
// in a pointer that hasn't been QI'd to IDispatch properly this could
|
||||
// create multiple wrappers for the same object, creating a fair bit of
|
||||
// confusion.
|
||||
if(nsXPConnect::IsIDispatchEnabled() && Interface->GetIID()->Equals(NSID_IDISPATCH))
|
||||
if(Interface->GetIID()->Equals(NSID_IDISPATCH))
|
||||
identity = Object;
|
||||
else
|
||||
#endif
|
||||
|
@ -435,7 +435,7 @@ XPCWrappedNative::GetUsedOnly(XPCCallContext& ccx,
|
|||
nsCOMPtr<nsISupports> identity;
|
||||
#ifdef XPC_IDISPATCH_SUPPORT
|
||||
// XXX See GetNewOrUsed for more info on this
|
||||
if(!nsXPConnect::IsIDispatchEnabled() && Interface->GetIID()->Equals(NSID_IDISPATCH))
|
||||
if(Interface->GetIID()->Equals(NSID_IDISPATCH))
|
||||
identity = Object;
|
||||
else
|
||||
#endif
|
||||
|
@ -1443,7 +1443,7 @@ XPCWrappedNative::InitTearOff(XPCCallContext& ccx,
|
|||
aTearOff->SetNative(obj);
|
||||
#ifdef XPC_IDISPATCH_SUPPORT
|
||||
// Are we building a tearoff for IDispatch?
|
||||
if(ccx.GetXPConnect()->IsIDispatchEnabled() && iid->Equals(NSID_IDISPATCH))
|
||||
if(iid->Equals(NSID_IDISPATCH))
|
||||
{
|
||||
aTearOff->SetIDispatch(ccx);
|
||||
}
|
||||
|
@ -2477,7 +2477,7 @@ XPCWrappedNative::HandlePossibleNameCaseError(XPCCallContext& ccx,
|
|||
PRUnichar* oldStr;
|
||||
PRUnichar* newStr;
|
||||
XPCNativeMember* member;
|
||||
XPCNativeInterface* interface;
|
||||
XPCNativeInterface* localIface;
|
||||
|
||||
/* PRUnichar->char->PRUnichar hack is to avoid pulling in i18n code. */
|
||||
if(JSVAL_IS_STRING(name) &&
|
||||
|
@ -2492,11 +2492,11 @@ XPCWrappedNative::HandlePossibleNameCaseError(XPCCallContext& ccx,
|
|||
newJSStr = JS_NewUCStringCopyZ(ccx, (const jschar*)newStr);
|
||||
nsCRT::free(newStr);
|
||||
if(newJSStr && (set ?
|
||||
set->FindMember(STRING_TO_JSVAL(newJSStr), &member, &interface) :
|
||||
set->FindMember(STRING_TO_JSVAL(newJSStr), &member, &localIface) :
|
||||
(JSBool)NS_PTR_TO_INT32(iface->FindMember(STRING_TO_JSVAL(newJSStr)))))
|
||||
{
|
||||
// found it!
|
||||
const char* ifaceName = interface->GetNameString();
|
||||
const char* ifaceName = localIface->GetNameString();
|
||||
const char* goodName = JS_GetStringBytes(newJSStr);
|
||||
const char* badName = JS_GetStringBytes(oldJSStr);
|
||||
char* locationStr = nsnull;
|
||||
|
|
|
@ -376,7 +376,6 @@ DefinePropertyIfFound(XPCCallContext& ccx,
|
|||
#ifdef XPC_IDISPATCH_SUPPORT
|
||||
// Check to see if there's an IDispatch tearoff
|
||||
if(wrapperToReflectInterfaceNames &&
|
||||
nsXPConnect::IsIDispatchEnabled() &&
|
||||
XPCIDispatchExtension::DefineProperty(ccx, obj,
|
||||
idval, wrapperToReflectInterfaceNames, propFlags, resolved))
|
||||
return JS_TRUE;
|
||||
|
@ -604,19 +603,18 @@ XPC_WN_Shared_Enumerate(JSContext *cx, JSObject *obj)
|
|||
XPCNativeInterface** interfaceArray = set->GetInterfaceArray();
|
||||
for(PRUint16 i = 0; i < interface_count; i++)
|
||||
{
|
||||
XPCNativeInterface* interface = interfaceArray[i];
|
||||
XPCNativeInterface* iface = interfaceArray[i];
|
||||
#ifdef XPC_IDISPATCH_SUPPORT
|
||||
if (nsXPConnect::GetXPConnect()->IsIDispatchEnabled() &&
|
||||
interface->GetIID()->Equals(NSID_IDISPATCH))
|
||||
if(iface->GetIID()->Equals(NSID_IDISPATCH))
|
||||
{
|
||||
XPCIDispatchExtension::Enumerate(ccx, obj, wrapper);
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
PRUint16 member_count = interface->GetMemberCount();
|
||||
PRUint16 member_count = iface->GetMemberCount();
|
||||
for(PRUint16 k = 0; k < member_count; k++)
|
||||
{
|
||||
XPCNativeMember* member = interface->GetMemberAt(k);
|
||||
XPCNativeMember* member = iface->GetMemberAt(k);
|
||||
jsval name = member->GetName();
|
||||
|
||||
// Skip if this member is going to come from the proto.
|
||||
|
|
Загрузка…
Ссылка в новой задаче