Fix for bug 554432 (Allow non-scriptable types for QS arguments). r=mrbkap.

--HG--
extra : rebase_source : ee8983f5578c658e9a3ecf1a8f0e5b0b0861e03c
This commit is contained in:
Peter Van der Beken 2010-01-27 10:53:51 +01:00
parent b4a6d86739
commit e882d412ac
4 changed files with 167 additions and 104 deletions

View File

@ -554,11 +554,11 @@ CUSTOM_QS_TN = {
customMethodCalls = {
'nsIDOMNode_GetNextSibling': {
'thisType': 'nsINode',
'code': ' nsINode* result = self->GetSibling(1);'
'code': ' nsINode *result = self->GetSibling(1);'
},
'nsIDOMNode_GetFirstChild': {
'thisType': 'nsINode',
'code': ' nsINode* result = self->GetChildAt(0);'
'code': ' nsINode *result = self->GetChildAt(0);'
},
'nsIDOMNode_GetChildNodes': {
'thisType': 'nsINode',
@ -567,23 +567,56 @@ customMethodCalls = {
},
'nsIDOMNode_GetPreviousSibling': {
'thisType': 'nsINode',
'code': ' nsINode* result = self->GetSibling(-1);'
'code': ' nsINode *result = self->GetSibling(-1);'
},
'nsIDOMNode_GetLastChild': {
'thisType': 'nsINode',
'code': ' nsINode* result = self->GetLastChild();'
'code': ' nsINode *result = self->GetLastChild();'
},
'nsIDOMNode_GetOwnerDocument': {
'thisType': 'nsINode',
'code': ' nsIDocument* result = self->GetOwnerDocument();'
'code': ' nsIDocument *result = self->GetOwnerDocument();'
},
'nsIDOMNode_GetParentNode': {
'thisType': 'nsINode',
'code': ' nsINode* result = self->GetNodeParent();'
'code': ' nsINode *result = self->GetNodeParent();'
},
'nsIDOMNode_InsertBefore': {
'thisType': 'nsINode',
'arg0Type': 'nsINode',
'arg1Type': 'nsINode',
'code': ' nsINode *result = self->InsertBefore(arg0, arg1, &rv);\n'
' if(NS_FAILED(rv))\n'
' result = nsnull;',
'canFail': True
},
'nsIDOMNode_ReplaceChild': {
'thisType': 'nsINode',
'arg0Type': 'nsINode',
'arg1Type': 'nsINode',
'code': ' nsINode *result = self->ReplaceChild(arg0, arg1, &rv);\n'
' if(NS_FAILED(rv))\n'
' result = nsnull;',
'canFail': True
},
'nsIDOMNode_RemoveChild': {
'thisType': 'nsINode',
'arg0Type': 'nsINode',
'code': ' rv = self->RemoveChild(arg0);\n'
' nsINode *result = NS_SUCCEEDED(rv) ? arg0 : nsnull;',
'canFail': True
},
'nsIDOMNode_AppendChild': {
'thisType': 'nsINode',
'arg0Type': 'nsINode',
'code': ' nsINode *result = self->AppendChild(arg0, &rv);\n'
' if(NS_FAILED(rv))\n'
' result = nsnull;',
'canFail': True
},
'nsIDOMNodeList_Item': {
'thisType': 'nsINodeList',
'code': ' nsINode* result = self->GetNodeAt(arg0);'
'code': ' nsINode *result = self->GetNodeAt(arg0);'
},
'nsIDOMHTMLDocument_Write': {
'code': nsIDOMHTMLDocument_Write_customMethodCallCode % 'Write',

View File

@ -865,10 +865,17 @@ def writeQuickStub(f, customMethodCalls, member, stubName, isSetter=False):
if len(member.params) > 0:
f.write(" jsval *argv = JS_ARGV(cx, vp);\n")
for i, param in enumerate(member.params):
validateParam(member, param)
argName = 'arg%d' % i
argTypeKey = argName + 'Type'
if customMethodCall is None or not argTypeKey in customMethodCall:
validateParam(member, param)
realtype = param.realtype
else:
realtype = xpidl.Forward(name=customMethodCall[argTypeKey],
location='', doccomments='')
# Emit code to convert this argument from jsval.
rvdeclared = writeArgumentUnboxing(
f, i, 'arg%d' % i, param.realtype,
f, i, argName, realtype,
haveCcx=haveCcx,
optional=param.optional,
rvdeclared=rvdeclared,
@ -1255,12 +1262,17 @@ def writeTraceableQuickStub(f, customMethodCalls, member, stubName):
# Convert in-parameters.
rvdeclared = False
for i, param in enumerate(member.params):
validateParam(member, param)
type = unaliasType(param.realtype)
argName = "arg%d" % i
argTypeKey = argName + 'Type'
if customMethodCall is None or not argTypeKey in customMethodCall:
validateParam(member, param)
realtype = unaliasType(param.realtype)
else:
realtype = xpidl.Forward(name=customMethodCall[argTypeKey],
location='', doccomments='')
rvdeclared = writeTraceableArgumentConversion(f, member, i, argName,
param.realtype,
haveCcx, rvdeclared)
realtype, haveCcx,
rvdeclared)
argNames.append(argName)
if customMethodCall is not None:

View File

@ -797,7 +797,7 @@ getNative(nsISupports *idobj,
return rv;
}
static nsresult
inline nsresult
getNativeFromWrapper(XPCWrappedNative *wrapper,
const nsIID &iid,
void **ppThis,
@ -809,40 +809,50 @@ getNativeFromWrapper(XPCWrappedNative *wrapper,
}
JSBool
xpc_qsUnwrapThisImpl(JSContext *cx,
JSObject *obj,
JSObject *callee,
const nsIID &iid,
void **ppThis,
nsISupports **pThisRef,
jsval *vp,
XPCLazyCallContext *lccx)
nsresult
getWrapper(JSContext *cx,
JSObject *obj,
JSObject *callee,
XPCWrappedNative **wrapper,
JSObject **cur,
XPCWrappedNativeTearOff **tearoff)
{
if(XPCWrapper::IsSecurityWrapper(obj))
if(XPCWrapper::IsSecurityWrapper(obj) &&
!(obj = XPCWrapper::Unwrap(cx, obj)))
{
obj = XPCWrapper::Unwrap(cx, obj);
if(!obj)
return xpc_qsThrow(cx, NS_ERROR_XPC_SECURITY_MANAGER_VETO);
return NS_ERROR_XPC_SECURITY_MANAGER_VETO;
}
JSObject *cur = obj;
XPCWrappedNativeTearOff *tearoff = nsnull;
XPCWrappedNative *wrapper =
XPCWrappedNative::GetWrappedNativeOfJSObject(cx, obj, callee, &cur,
&tearoff);
*cur = obj;
*tearoff = nsnull;
*wrapper =
XPCWrappedNative::GetWrappedNativeOfJSObject(cx, obj, callee, cur,
tearoff);
return NS_OK;
}
nsresult
castNative(JSContext *cx,
XPCWrappedNative *wrapper,
JSObject *cur,
XPCWrappedNativeTearOff *tearoff,
const nsIID &iid,
void **ppThis,
nsISupports **pThisRef,
jsval *vp,
XPCLazyCallContext *lccx)
{
if(wrapper)
{
nsresult rv = getNativeFromWrapper(wrapper, iid, ppThis, pThisRef, vp);
if(NS_SUCCEEDED(rv))
{
if(lccx)
lccx->SetWrapper(wrapper, tearoff);
return JS_TRUE;
}
if(lccx && NS_SUCCEEDED(rv))
lccx->SetWrapper(wrapper, tearoff);
if(rv != NS_ERROR_NO_INTERFACE)
return xpc_qsThrow(cx, rv);
return rv;
}
else if(cur)
{
@ -853,12 +863,12 @@ xpc_qsUnwrapThisImpl(JSContext *cx,
if(lccx)
lccx->SetWrapper(cur);
return JS_TRUE;
return NS_OK;
}
}
*pThisRef = nsnull;
return xpc_qsThrow(cx, NS_ERROR_XPC_BAD_OP_ON_WN_PROTO);
return NS_ERROR_XPC_BAD_OP_ON_WN_PROTO;
}
JSBool
@ -880,6 +890,29 @@ xpc_qsUnwrapThisFromCcxImpl(XPCCallContext &ccx,
return JS_TRUE;
}
JSObject*
xpc_qsUnwrapObj(jsval v, nsISupports **ppArgRef, nsresult *rv)
{
if(JSVAL_IS_VOID(v) || JSVAL_IS_NULL(v))
{
*ppArgRef = nsnull;
*rv = NS_OK;
return nsnull;
}
if(!JSVAL_IS_OBJECT(v))
{
*ppArgRef = nsnull;
*rv = ((JSVAL_IS_INT(v) && JSVAL_TO_INT(v) == 0)
? NS_ERROR_XPC_BAD_CONVERT_JS_ZERO_ISNOT_NULL
: NS_ERROR_XPC_BAD_CONVERT_JS);
return nsnull;
}
*rv = NS_OK;
return JSVAL_TO_OBJECT(v);
}
nsresult
xpc_qsUnwrapArgImpl(JSContext *cx,
jsval v,
@ -888,50 +921,25 @@ xpc_qsUnwrapArgImpl(JSContext *cx,
nsISupports **ppArgRef,
jsval *vp)
{
// From XPCConvert::JSData2Native
if(JSVAL_IS_VOID(v) || JSVAL_IS_NULL(v))
nsresult rv;
JSObject *src = xpc_qsUnwrapObj(v, ppArgRef, &rv);
if(!src)
{
*ppArg = nsnull;
*ppArgRef = nsnull;
return NS_OK;
return rv;
}
if(!JSVAL_IS_OBJECT(v))
{
*ppArgRef = nsnull;
return ((JSVAL_IS_INT(v) && JSVAL_TO_INT(v) == 0)
? NS_ERROR_XPC_BAD_CONVERT_JS_ZERO_ISNOT_NULL
: NS_ERROR_XPC_BAD_CONVERT_JS);
}
JSObject *src = JSVAL_TO_OBJECT(v);
XPCWrappedNative *wrapper;
XPCWrappedNativeTearOff *tearoff;
JSObject *obj2;
rv = getWrapper(cx, src, nsnull, &wrapper, &obj2, &tearoff);
NS_ENSURE_SUCCESS(rv, rv);
JSObject *inner = nsnull;
if(XPCWrapper::IsSecurityWrapper(src))
if(wrapper || obj2)
{
inner = XPCWrapper::Unwrap(cx, src);
if(!inner)
return NS_ERROR_XPC_SECURITY_MANAGER_VETO;
}
// From XPCConvert::JSObject2NativeInterface
JSObject* obj2;
XPCWrappedNative* wrappedNative =
XPCWrappedNative::GetWrappedNativeOfJSObject(cx, inner ? inner : src,
nsnull, &obj2);
nsISupports *iface;
if(wrappedNative)
{
iface = wrappedNative->GetIdentityObject();
if(NS_FAILED(getNativeFromWrapper(wrappedNative, iid, ppArg, ppArgRef,
vp)))
return NS_ERROR_XPC_BAD_CONVERT_JS;
return NS_OK;
}
if(obj2)
{
iface = static_cast<nsISupports*>(xpc_GetJSPrivate(obj2));
if(NS_FAILED(getNative(iface, GetOffsetsFromSlimWrapper(obj2),
obj2, iid, ppArg, ppArgRef, vp)))
if(NS_FAILED(castNative(cx, wrapper, obj2, tearoff, iid, ppArg,
ppArgRef, vp, nsnull)))
return NS_ERROR_XPC_BAD_CONVERT_JS;
return NS_OK;
}
@ -948,6 +956,7 @@ xpc_qsUnwrapArgImpl(JSContext *cx,
}
// Try to unwrap a slim wrapper.
nsISupports *iface;
if(XPCConvert::GetISupportsFromJSObject(src, &iface))
{
if(!iface || NS_FAILED(iface->QueryInterface(iid, ppArg)))
@ -968,10 +977,10 @@ xpc_qsUnwrapArgImpl(JSContext *cx,
return NS_ERROR_XPC_BAD_CONVERT_JS;
}
nsXPCWrappedJS *wrapper;
nsresult rv =
nsXPCWrappedJS::GetNewOrUsed(ccx, src, iid, nsnull, &wrapper);
if(NS_FAILED(rv) || !wrapper)
nsRefPtr<nsXPCWrappedJS> wrappedJS;
rv = nsXPCWrappedJS::GetNewOrUsed(ccx, src, iid, nsnull,
getter_AddRefs(wrappedJS));
if(NS_FAILED(rv) || !wrappedJS)
{
*ppArgRef = nsnull;
return rv;
@ -981,13 +990,12 @@ xpc_qsUnwrapArgImpl(JSContext *cx,
// the right thing for the various 'special' interfaces; e.g.
// nsIPropertyBag. We must use AggregatedQueryInterface in cases where
// there is an outer to avoid nasty recursion.
rv = wrapper->QueryInterface(iid, ppArg);
rv = wrappedJS->QueryInterface(iid, ppArg);
if(NS_SUCCEEDED(rv))
{
*ppArgRef = static_cast<nsISupports*>(*ppArg);
*vp = OBJECT_TO_JSVAL(wrapper->GetJSObject());
*vp = OBJECT_TO_JSVAL(wrappedJS->GetJSObject());
}
NS_RELEASE(wrapper);
return rv;
}

View File

@ -348,15 +348,24 @@ xpc_qsJsvalToWcharStr(JSContext *cx, jsval v, jsval *pval, PRUnichar **pstr);
JSBool
xpc_qsStringToJsval(JSContext *cx, const nsAString &str, jsval *rval);
JSBool
xpc_qsUnwrapThisImpl(JSContext *cx,
JSObject *obj,
JSObject *callee,
const nsIID &iid,
void **ppThis,
nsISupports **ppThisRef,
jsval *vp,
XPCLazyCallContext *lccx);
nsresult
getWrapper(JSContext *cx,
JSObject *obj,
JSObject *callee,
XPCWrappedNative **wrapper,
JSObject **cur,
XPCWrappedNativeTearOff **tearoff);
nsresult
castNative(JSContext *cx,
XPCWrappedNative *wrapper,
JSObject *cur,
XPCWrappedNativeTearOff *tearoff,
const nsIID &iid,
void **ppThis,
nsISupports **ppThisRef,
jsval *vp,
XPCLazyCallContext *lccx);
/**
* Search @a obj and its prototype chain for an XPCOM object that implements
@ -384,14 +393,15 @@ xpc_qsUnwrapThis(JSContext *cx,
jsval *pThisVal,
XPCLazyCallContext *lccx)
{
return xpc_qsUnwrapThisImpl(cx,
obj,
callee,
NS_GET_TEMPLATE_IID(T),
reinterpret_cast<void **>(ppThis),
pThisRef,
pThisVal,
lccx);
XPCWrappedNative *wrapper;
XPCWrappedNativeTearOff *tearoff;
nsresult rv = getWrapper(cx, obj, callee, &wrapper, &obj, &tearoff);
if(NS_SUCCEEDED(rv))
rv = castNative(cx, wrapper, obj, tearoff, NS_GET_TEMPLATE_IID(T),
reinterpret_cast<void **>(ppThis), pThisRef, pThisVal,
lccx);
return NS_SUCCEEDED(rv) || xpc_qsThrow(cx, rv);
}
JSBool