Bug 627954, part 2: ensure nsXPCConvert::VariantData2JS et al are in the correct compartment (r=mrbkap)

--HG--
extra : rebase_source : c924f5e87e2f5a6339f4c83c78db1c7f05b600f7
This commit is contained in:
Luke Wagner 2011-02-05 04:56:05 -08:00
parent 3cfb03a5ab
commit bbfde362e9
13 changed files with 186 additions and 263 deletions

View File

@ -25,7 +25,7 @@ load 348049-1.xhtml
load 344882-1.html
load 345837-1.xhtml
load 349355-1.html
asserts(1) load 354645-1.xul # bug 512815
load 354645-1.xul
load 360599-1.html
load 366200-1.xhtml
load 369216-1.html

View File

@ -1093,6 +1093,7 @@ nsXPConnect::InitClassesWithNewWrappedGlobal(JSContext * aJSContext,
JSAutoEnterCompartment ac;
if(!ac.enter(ccx, tempGlobal))
return UnexpectedFailure(NS_ERROR_FAILURE);
ccx.SetScopeForNewJSObjects(tempGlobal);
PRBool system = (aFlags & nsIXPConnect::FLAG_SYSTEM_GLOBAL_OBJECT) != 0;
if(system && !JS_MakeSystemObject(aJSContext, tempGlobal))
@ -1113,8 +1114,7 @@ nsXPConnect::InitClassesWithNewWrappedGlobal(JSContext * aJSContext,
if(!XPCConvert::NativeInterface2JSObject(ccx, &v,
getter_AddRefs(holder),
helper, &aIID, nsnull,
tempGlobal, PR_FALSE,
OBJ_IS_GLOBAL, &rv))
PR_FALSE, OBJ_IS_GLOBAL, &rv))
return UnexpectedFailure(rv);
NS_ASSERTION(NS_SUCCEEDED(rv) && holder, "Didn't wrap properly");
@ -1207,10 +1207,16 @@ NativeInterface2JSObject(XPCLazyCallContext & lccx,
jsval *aVal,
nsIXPConnectJSObjectHolder **aHolder)
{
JSAutoEnterCompartment ac;
if (!ac.enter(lccx.GetJSContext(), aScope))
return NS_ERROR_OUT_OF_MEMORY;
lccx.SetScopeForNewJSObjects(aScope);
nsresult rv;
xpcObjectHelper helper(aCOMObj, aCache);
if(!XPCConvert::NativeInterface2JSObject(lccx, aVal, aHolder, helper, aIID,
nsnull, aScope, aAllowWrapping,
nsnull, aAllowWrapping,
OBJ_IS_NOT_GLOBAL, &rv))
return rv;
@ -2273,8 +2279,10 @@ nsXPConnect::VariantToJS(JSContext* ctx, JSObject* scope, nsIVariant* value, jsv
return NS_ERROR_FAILURE;
XPCLazyCallContext lccx(ccx);
ccx.SetScopeForNewJSObjects(scope);
nsresult rv = NS_OK;
if(!XPCVariant::VariantDataToJS(lccx, value, scope, &rv, _retval))
if(!XPCVariant::VariantDataToJS(lccx, value, &rv, _retval))
{
if(NS_FAILED(rv))
return rv;

View File

@ -57,18 +57,17 @@ XPCCallContext::XPCCallContext(XPCContext::LangType callerLanguage,
mJSContext(cx),
mContextPopRequired(JS_FALSE),
mDestroyJSContextInDestructor(JS_FALSE),
mCallerLanguage(callerLanguage),
mCallee(nsnull)
mCallerLanguage(callerLanguage)
{
Init(callerLanguage, callerLanguage == NATIVE_CALLER, obj, funobj, JS_TRUE,
name, argc, argv, rval);
Init(callerLanguage, callerLanguage == NATIVE_CALLER, obj, funobj,
INIT_SHOULD_LOOKUP_WRAPPER, name, argc, argv, rval);
}
XPCCallContext::XPCCallContext(XPCContext::LangType callerLanguage,
JSContext* cx,
JSBool callBeginRequest,
JSObject* obj,
JSObject* currentJSObject,
JSObject* flattenedJSObject,
XPCWrappedNative* wrapper,
XPCWrappedNativeTearOff* tearOff)
: mState(INIT_FAILED),
@ -79,12 +78,12 @@ XPCCallContext::XPCCallContext(XPCContext::LangType callerLanguage,
mContextPopRequired(JS_FALSE),
mDestroyJSContextInDestructor(JS_FALSE),
mCallerLanguage(callerLanguage),
mCurrentJSObject(currentJSObject),
mFlattenedJSObject(flattenedJSObject),
mWrapper(wrapper),
mTearOff(tearOff),
mCallee(nsnull)
mTearOff(tearOff)
{
Init(callerLanguage, callBeginRequest, obj, nsnull, JS_FALSE, JSID_VOID, NO_ARGS,
Init(callerLanguage, callBeginRequest, obj, nsnull,
WRAPPER_PASSED_TO_CONSTRUCTOR, JSID_VOID, NO_ARGS,
nsnull, nsnull);
}
@ -93,7 +92,7 @@ XPCCallContext::Init(XPCContext::LangType callerLanguage,
JSBool callBeginRequest,
JSObject* obj,
JSObject* funobj,
JSBool getWrappedNative,
WrapperInitOptions wrapperInitOptions,
jsid name,
uintN argc,
jsval *argv,
@ -180,45 +179,38 @@ XPCCallContext::Init(XPCContext::LangType callerLanguage,
if(!obj)
return;
mScopeForNewJSObjects = obj;
mState = HAVE_SCOPE;
mMethodIndex = 0xDEAD;
mOperandJSObject = obj;
mState = HAVE_OBJECT;
mTearOff = nsnull;
if(getWrappedNative)
if(wrapperInitOptions == INIT_SHOULD_LOOKUP_WRAPPER)
{
mWrapper = XPCWrappedNative::GetWrappedNativeOfJSObject(mJSContext, obj,
funobj,
&mCurrentJSObject,
&mFlattenedJSObject,
&mTearOff);
if(mWrapper)
{
DEBUG_CheckWrapperThreadSafety(mWrapper);
mFlattenedJSObject = mWrapper->GetFlatJSObjectAndMark();
if(mTearOff)
if(mWrapper)
{
mCurrentJSObject = mTearOff->GetJSObject();
mScriptableInfo = nsnull;
DEBUG_CheckWrapperThreadSafety(mWrapper);
mFlattenedJSObject = mWrapper->GetFlatJSObjectAndMark();
if(mTearOff)
mScriptableInfo = nsnull;
else
mScriptableInfo = mWrapper->GetScriptableInfo();
}
else
{
mWrapper->GetJSObject(&mCurrentJSObject);
mScriptableInfo = mWrapper->GetScriptableInfo();
NS_ABORT_IF_FALSE(!mFlattenedJSObject || IS_SLIM_WRAPPER(mFlattenedJSObject),
"should have a slim wrapper");
}
}
else
{
if(!mCurrentJSObject)
return;
NS_ASSERTION(IS_SLIM_WRAPPER(mCurrentJSObject),
"What kind of wrapper is this?");
mFlattenedJSObject = mCurrentJSObject;
}
if(!JSID_IS_VOID(name))
SetName(name);

View File

@ -239,13 +239,18 @@ INT64_TO_DOUBLE(const int64 &v)
// static
JSBool
XPCConvert::NativeData2JS(XPCLazyCallContext& lccx, jsval* d, const void* s,
const nsXPTType& type, const nsID* iid,
JSObject* scope, nsresult* pErr)
const nsXPTType& type, const nsID* iid, nsresult* pErr)
{
NS_PRECONDITION(s, "bad param");
NS_PRECONDITION(d, "bad param");
JSContext* cx = lccx.GetJSContext();
JSContext* cx = lccx.GetJSContext();
// Allow wrong compartment or unset ScopeForNewObject when the caller knows
// the value is primitive (viz., XPCNativeMember::GetConstantValue).
NS_ABORT_IF_FALSE(type.IsArithmetic() ||
cx->compartment == lccx.GetScopeForNewJSObjects()->compartment(),
"bad scope for new JSObjects");
if(pErr)
*pErr = NS_ERROR_XPC_BAD_CONVERT_NATIVE;
@ -294,18 +299,6 @@ XPCConvert::NativeData2JS(XPCLazyCallContext& lccx, jsval* d, const void* s,
case nsXPTType::T_JSVAL :
{
*d = *((jsval*)s);
JSAutoEnterCompartment ac;
XPCCallContext &ccx = lccx.GetXPCCallContext();
if(ccx.GetXPCContext()->CallerTypeIsNative())
{
JSObject *jsscope = ccx.GetCallee();
if(!jsscope || !JS_ObjectIsFunction(ccx, jsscope))
jsscope = JS_GetGlobalForObject(ccx, scope);
if(!ac.enter(ccx, jsscope))
return JS_FALSE;
}
if(!JS_WrapValue(cx, d))
return JS_FALSE;
break;
@ -333,7 +326,7 @@ XPCConvert::NativeData2JS(XPCLazyCallContext& lccx, jsval* d, const void* s,
if(!iid2)
break;
JSObject* obj;
if(!(obj = xpc_NewIDObject(cx, scope, *iid2)))
if(!(obj = xpc_NewIDObject(cx, lccx.GetScopeForNewJSObjects(), *iid2)))
return JS_FALSE;
*d = OBJECT_TO_JSVAL(obj);
break;
@ -479,7 +472,7 @@ XPCConvert::NativeData2JS(XPCLazyCallContext& lccx, jsval* d, const void* s,
return JS_FALSE;
return XPCVariant::VariantDataToJS(lccx, variant,
scope, pErr, d);
pErr, d);
}
// else...
@ -490,7 +483,7 @@ XPCConvert::NativeData2JS(XPCLazyCallContext& lccx, jsval* d, const void* s,
// creating a new XPCNativeScriptableShared.
xpcObjectHelper helper(iface);
if(!NativeInterface2JSObject(lccx, d, nsnull, helper, iid,
nsnull, scope, PR_TRUE,
nsnull, PR_TRUE,
OBJ_IS_NOT_GLOBAL, pErr))
return JS_FALSE;
@ -1113,34 +1106,6 @@ CreateHolderIfNeeded(XPCCallContext& ccx, JSObject* obj, jsval* d,
return JS_TRUE;
}
static PRBool
ComputeWrapperInfo(const XPCCallContext &ccx, XPCWrappedNativeScope *scope,
JSObject **callee)
{
if(ccx.GetXPCContext()->CallerTypeIsJavaScript())
{
// Called from JS. We're going to hand the resulting JSObject
// to said JS. The correct compartment must already be pushed
// on cx, so return true and don't give back a callee.
*callee = nsnull;
return PR_TRUE;
}
if(ccx.GetXPCContext()->CallerTypeIsNative())
{
// Calling from JS -> C++, return false to indicate that we need
// to push a compartment and return the callee.
*callee = ccx.GetCallee();
if(!*callee || !JS_ObjectIsFunction(ccx, *callee))
{
*callee = scope->GetGlobalJSObject();
OBJ_TO_INNER_OBJECT(ccx, *callee);
}
}
return PR_FALSE;
}
/***************************************************************************/
// static
JSBool
@ -1150,12 +1115,10 @@ XPCConvert::NativeInterface2JSObject(XPCLazyCallContext& lccx,
xpcObjectHelper& aHelper,
const nsID* iid,
XPCNativeInterface** Interface,
JSObject* scope,
PRBool allowNativeWrapper,
PRBool isGlobal,
nsresult* pErr)
{
NS_ASSERTION(scope, "bad param");
NS_ASSERTION(!Interface || iid,
"Need the iid if you pass in an XPCNativeInterface cache.");
@ -1176,9 +1139,12 @@ XPCConvert::NativeInterface2JSObject(XPCLazyCallContext& lccx,
// optimal -- we could detect this and roll the functionality into a
// single wrapper, but the current solution is good enough for now.
JSContext* cx = lccx.GetJSContext();
NS_ABORT_IF_FALSE(lccx.GetScopeForNewJSObjects()->compartment() == cx->compartment,
"bad scope for new JSObjects");
JSObject *jsscope = lccx.GetScopeForNewJSObjects();
XPCWrappedNativeScope* xpcscope =
XPCWrappedNativeScope::FindInJSObjectScope(cx, scope);
XPCWrappedNativeScope::FindInJSObjectScope(cx, jsscope);
if(!xpcscope)
return JS_FALSE;
@ -1190,8 +1156,6 @@ XPCConvert::NativeInterface2JSObject(XPCLazyCallContext& lccx,
// object will create (and fill the cache) from its PreCreate call.
nsWrapperCache *cache = aHelper.GetWrapperCache();
JSObject *callee;
PRBool tryConstructSlimWrapper = PR_FALSE;
JSObject *flat;
if(cache)
@ -1206,13 +1170,6 @@ XPCConvert::NativeInterface2JSObject(XPCLazyCallContext& lccx,
if(!flat)
flat = ConstructProxyObject(ccx, aHelper, xpcscope);
JSAutoEnterCompartment ac;
if(!ComputeWrapperInfo(ccx, xpcscope, &callee) &&
!ac.enter(ccx, callee))
{
return JS_FALSE;
}
if(!JS_WrapObject(ccx, &flat))
return JS_FALSE;
@ -1368,13 +1325,6 @@ XPCConvert::NativeInterface2JSObject(XPCLazyCallContext& lccx,
if(!ccx.IsValid())
return JS_FALSE;
JSAutoEnterCompartment ac;
if(!ComputeWrapperInfo(ccx, xpcscope, &callee) &&
!ac.enter(ccx, callee))
{
return JS_FALSE;
}
JSObject *original = flat;
if(!JS_WrapObject(ccx, &flat))
return JS_FALSE;
@ -1959,8 +1909,8 @@ XPC_JSArgumentFormatter(JSContext *cx, const char *format,
// NOTE: MUST be retrieved *after* the iid in the 'p' case above.
p = va_arg(ap, void *);
if(!XPCConvert::NativeData2JS(ccx, &vp[0], &p, type, iid,
JS_GetGlobalObject(cx), nsnull))
ccx.SetScopeForNewJSObjects(JS_GetGlobalForScopeChain(cx));
if(!XPCConvert::NativeData2JS(ccx, &vp[0], &p, type, iid, nsnull))
return JS_FALSE;
}
*vpp = vp + 1;
@ -1981,8 +1931,7 @@ JSBool
XPCConvert::NativeArray2JS(XPCLazyCallContext& lccx,
jsval* d, const void** s,
const nsXPTType& type, const nsID* iid,
JSUint32 count, JSObject* scope,
nsresult* pErr)
JSUint32 count, nsresult* pErr)
{
NS_PRECONDITION(s, "bad param");
NS_PRECONDITION(d, "bad param");
@ -1992,6 +1941,8 @@ XPCConvert::NativeArray2JS(XPCLazyCallContext& lccx,
return JS_FALSE;
JSContext* cx = ccx.GetJSContext();
NS_ABORT_IF_FALSE(lccx.GetScopeForNewJSObjects()->compartment() == cx->compartment,
"bad scope for new JSObjects");
// XXX add support for putting chars in a string rather than an array
@ -2017,8 +1968,7 @@ XPCConvert::NativeArray2JS(XPCLazyCallContext& lccx,
PR_BEGIN_MACRO \
for(i = 0; i < count; i++) \
{ \
if(!NativeData2JS(ccx, &current, ((_t*)*s)+i, type, iid, \
scope, pErr) || \
if(!NativeData2JS(ccx, &current, ((_t*)*s)+i, type, iid, pErr) ||\
!JS_SetElement(cx, array, i, &current)) \
goto failure; \
} \

View File

@ -157,17 +157,19 @@ XPCCallContext::GetPrevCallContext() const
}
inline JSObject*
XPCCallContext::GetOperandJSObject() const
XPCCallContext::GetScopeForNewJSObjects() const
{
CHECK_STATE(HAVE_OBJECT);
return mOperandJSObject;
CHECK_STATE(HAVE_SCOPE);
return mScopeForNewJSObjects;
}
inline JSObject*
XPCCallContext::GetCurrentJSObject() const
inline void
XPCCallContext::SetScopeForNewJSObjects(JSObject *scope)
{
CHECK_STATE(HAVE_OBJECT);
return mCurrentJSObject;
NS_ABORT_IF_FALSE(mState == HAVE_CONTEXT, "wrong call context state");
NS_ABORT_IF_FALSE(scope->compartment() == mJSContext->compartment, "wrong compartment");
mScopeForNewJSObjects = scope;
mState = HAVE_SCOPE;
}
inline JSObject*
@ -183,8 +185,8 @@ XPCCallContext::GetIdentityObject() const
CHECK_STATE(HAVE_OBJECT);
if(mWrapper)
return mWrapper->GetIdentityObject();
return mCurrentJSObject ?
static_cast<nsISupports*>(xpc_GetJSPrivate(mCurrentJSObject)) :
return mFlattenedJSObject ?
static_cast<nsISupports*>(xpc_GetJSPrivate(mFlattenedJSObject)) :
nsnull;
}
@ -204,7 +206,7 @@ XPCCallContext::GetProto() const
CHECK_STATE(HAVE_OBJECT);
if(mWrapper)
return mWrapper->GetProto();
return mCurrentJSObject ? GetSlimWrapperProto(mCurrentJSObject) : nsnull;
return mFlattenedJSObject ? GetSlimWrapperProto(mFlattenedJSObject) : nsnull;
}
inline JSBool
@ -348,22 +350,6 @@ XPCCallContext::SetResolvingWrapper(XPCWrappedNative* w)
return mThreadData->SetResolvingWrapper(w);
}
inline JSObject*
XPCCallContext::GetCallee() const
{
NS_ASSERTION(mCallerLanguage == NATIVE_CALLER,
"GetCallee() doesn't make sense");
return mCallee;
}
inline void
XPCCallContext::SetCallee(JSObject* callee)
{
NS_ASSERTION(mCallerLanguage == NATIVE_CALLER,
"SetCallee() doesn't make sense");
mCallee = callee;
}
inline PRUint16
XPCCallContext::GetMethodIndex() const
{
@ -803,18 +789,18 @@ XPCLazyCallContext::SetWrapper(XPCWrappedNative* wrapper,
mWrapper = wrapper;
mTearOff = tearoff;
if(mTearOff)
mCurrentJSObject = mTearOff->GetJSObject();
mFlattenedJSObject = mTearOff->GetJSObject();
else
mWrapper->GetJSObject(&mCurrentJSObject);
mFlattenedJSObject = mWrapper->GetFlatJSObjectAndMark();
}
inline void
XPCLazyCallContext::SetWrapper(JSObject* currentJSObject)
XPCLazyCallContext::SetWrapper(JSObject* flattenedJSObject)
{
NS_ASSERTION(IS_SLIM_WRAPPER_OBJECT(currentJSObject),
NS_ASSERTION(IS_SLIM_WRAPPER_OBJECT(flattenedJSObject),
"What kind of object is this?");
mWrapper = nsnull;
mTearOff = nsnull;
mCurrentJSObject = currentJSObject;
mFlattenedJSObject = flattenedJSObject;
}
/***************************************************************************/

View File

@ -66,6 +66,7 @@
#include "nsAutoPtr.h"
#include "nsCycleCollectionParticipant.h"
#include "nsCycleCollector.h"
#include "nsDebug.h"
#include "nsISupports.h"
#include "nsIServiceManager.h"
#include "nsIClassInfoImpl.h"
@ -1095,10 +1096,18 @@ public:
inline XPCContext::LangType GetPrevCallerLanguage() const ;
inline XPCCallContext* GetPrevCallContext() const ;
inline JSObject* GetOperandJSObject() const ;
inline JSObject* GetCurrentJSObject() const ;
inline JSObject* GetFlattenedJSObject() const ;
/*
* The 'scope for new JSObjects' will be the scope for objects created when
* carrying out a JS/C++ call. This member is only available if HAVE_SCOPE.
* The object passed to the ccx constructor is used as the scope for new
* JSObjects. However, this object is also queried for a wrapper, so
* clients that don't want a wrapper (and thus pass NULL to the ccx
* constructor) need to manually call SetScopeForNewJSObjects.
*/
inline JSObject* GetScopeForNewJSObjects() const ;
inline void SetScopeForNewJSObjects(JSObject *obj) ;
inline JSObject* GetFlattenedJSObject() const ;
inline nsISupports* GetIdentityObject() const ;
inline XPCWrappedNative* GetWrapper() const ;
inline XPCWrappedNativeProto* GetProto() const ;
@ -1134,9 +1143,6 @@ public:
inline void SetRetVal(jsval val);
inline JSObject* GetCallee() const;
inline void SetCallee(JSObject* callee);
void SetName(jsid name);
void SetArgsAndResultPtr(uintN argc, jsval *argv, jsval *rval);
void SetCallInfo(XPCNativeInterface* iface, XPCNativeMember* member,
@ -1171,15 +1177,20 @@ private:
JSContext* cx,
JSBool callBeginRequest,
JSObject* obj,
JSObject* currentJSObject,
JSObject* flattenedJSObject,
XPCWrappedNative* wn,
XPCWrappedNativeTearOff* tearoff);
enum WrapperInitOptions {
WRAPPER_PASSED_TO_CONSTRUCTOR,
INIT_SHOULD_LOOKUP_WRAPPER
};
void Init(XPCContext::LangType callerLanguage,
JSBool callBeginRequest,
JSObject* obj,
JSObject* funobj,
JSBool getWrappedNative,
WrapperInitOptions wrapperInitOptions,
jsid name,
uintN argc,
jsval *argv,
@ -1191,6 +1202,7 @@ private:
INIT_FAILED,
SYSTEM_SHUTDOWN,
HAVE_CONTEXT,
HAVE_SCOPE,
HAVE_OBJECT,
HAVE_NAME,
HAVE_ARGS,
@ -1223,8 +1235,7 @@ private:
XPCCallContext* mPrevCallContext;
JSObject* mOperandJSObject;
JSObject* mCurrentJSObject;
JSObject* mScopeForNewJSObjects;
JSObject* mFlattenedJSObject;
XPCWrappedNative* mWrapper;
XPCWrappedNativeTearOff* mTearOff;
@ -1248,12 +1259,6 @@ private:
#endif
PRUint16 mMethodIndex;
// If not null, this is the function object of the function we're going to
// call. This member only makes sense when CallerTypeIsNative() on our
// XPCContext returns true. We're not responsible for rooting this object;
// whoever sets it on us needs to deal with that.
JSObject* mCallee;
#define XPCCCX_STRING_CACHE_SIZE 2
// String wrapper entry, holds a string, and a boolean that tells
@ -1288,7 +1293,7 @@ public:
, mCx(nsnull)
, mCallerLanguage(JS_CALLER)
, mObj(nsnull)
, mCurrentJSObject(nsnull)
, mFlattenedJSObject(nsnull)
, mWrapper(nsnull)
, mTearOff(nsnull)
#endif
@ -1296,7 +1301,7 @@ public:
}
XPCLazyCallContext(XPCContext::LangType callerLanguage, JSContext* cx,
JSObject* obj = nsnull,
JSObject* currentJSObject = nsnull,
JSObject* flattenedJSObject = nsnull,
XPCWrappedNative* wrapper = nsnull,
XPCWrappedNativeTearOff* tearoff = nsnull)
: mCallBeginRequest(callerLanguage == NATIVE_CALLER ?
@ -1306,7 +1311,7 @@ public:
mCx(cx),
mCallerLanguage(callerLanguage),
mObj(obj),
mCurrentJSObject(currentJSObject),
mFlattenedJSObject(flattenedJSObject),
mWrapper(wrapper),
mTearOff(tearoff)
{
@ -1327,7 +1332,7 @@ public:
}
void SetWrapper(XPCWrappedNative* wrapper,
XPCWrappedNativeTearOff* tearoff);
void SetWrapper(JSObject* currentJSObject);
void SetWrapper(JSObject* flattenedJSObject);
JSContext *GetJSContext()
{
@ -1341,12 +1346,28 @@ public:
return mCx;
}
JSObject *GetCurrentJSObject() const
JSObject *GetScopeForNewJSObjects() const
{
if(mCcx)
return mCcx->GetCurrentJSObject();
return mCcx->GetScopeForNewJSObjects();
return mCurrentJSObject;
return mObj;
}
void SetScopeForNewJSObjects(JSObject *obj)
{
if(mCcx) {
mCcx->SetScopeForNewJSObjects(obj);
return;
}
NS_ABORT_IF_FALSE(!mObj, "already set!");
mObj = obj;
}
JSObject *GetFlattenedJSObject() const
{
if(mCcx)
return mCcx->GetFlattenedJSObject();
return mFlattenedJSObject;
}
XPCCallContext &GetXPCCallContext()
{
@ -1356,7 +1377,7 @@ public:
new (mData) XPCCallContext(mCallerLanguage, mCx,
mCallBeginRequest == CALL_BEGINREQUEST,
mObj,
mCurrentJSObject, mWrapper,
mFlattenedJSObject, mWrapper,
mTearOff);
if(!mCcx->IsValid())
{
@ -1383,7 +1404,7 @@ private:
JSContext *mCx;
XPCContext::LangType mCallerLanguage;
JSObject *mObj;
JSObject *mCurrentJSObject;
JSObject *mFlattenedJSObject;
XPCWrappedNative *mWrapper;
XPCWrappedNativeTearOff *mTearOff;
char mData[sizeof(XPCCallContext)];
@ -3205,15 +3226,14 @@ public:
*/
static JSBool NativeData2JS(XPCCallContext& ccx, jsval* d, const void* s,
const nsXPTType& type, const nsID* iid,
JSObject* scope, nsresult* pErr)
nsresult* pErr)
{
XPCLazyCallContext lccx(ccx);
return NativeData2JS(lccx, d, s, type, iid, scope, pErr);
return NativeData2JS(lccx, d, s, type, iid, pErr);
}
static JSBool NativeData2JS(XPCLazyCallContext& lccx, jsval* d,
const void* s, const nsXPTType& type,
const nsID* iid, JSObject* scope,
nsresult* pErr);
const nsID* iid, nsresult* pErr);
static JSBool JSData2Native(XPCCallContext& ccx, void* d, jsval s,
const nsXPTType& type,
@ -3230,7 +3250,6 @@ public:
* @param Interface the interface of src that we want
* @param cache the wrapper cache for src (may be null, in which case src
* will be QI'ed to get the cache)
* @param scope the default scope to put on the new JSObject's parent chain
* @param allowNativeWrapper if true, this method may wrap the resulting
* JSObject in an XPCNativeWrapper and return that, as needed.
* @param isGlobal
@ -3244,15 +3263,13 @@ public:
xpcObjectHelper& aHelper,
const nsID* iid,
XPCNativeInterface** Interface,
JSObject* scope,
PRBool allowNativeWrapper,
PRBool isGlobal,
nsresult* pErr)
{
XPCLazyCallContext lccx(ccx);
return NativeInterface2JSObject(lccx, d, dest, aHelper, iid, Interface,
scope, allowNativeWrapper, isGlobal,
pErr);
allowNativeWrapper, isGlobal, pErr);
}
static JSBool NativeInterface2JSObject(XPCLazyCallContext& lccx,
jsval* d,
@ -3260,7 +3277,6 @@ public:
xpcObjectHelper& aHelper,
const nsID* iid,
XPCNativeInterface** Interface,
JSObject* scope,
PRBool allowNativeWrapper,
PRBool isGlobal,
nsresult* pErr);
@ -3291,8 +3307,7 @@ public:
static JSBool NativeArray2JS(XPCLazyCallContext& ccx,
jsval* d, const void** s,
const nsXPTType& type, const nsID* iid,
JSUint32 count, JSObject* scope,
nsresult* pErr);
JSUint32 count, nsresult* pErr);
static JSBool JSArray2Native(XPCCallContext& ccx, void** d, jsval s,
JSUint32 count, JSUint32 capacity,
@ -4324,8 +4339,7 @@ public:
*/
static JSBool VariantDataToJS(XPCLazyCallContext& lccx,
nsIVariant* variant,
JSObject* scope, nsresult* pErr,
jsval* pJSVal);
nsresult* pErr, jsval* pJSVal);
protected:
virtual ~XPCVariant() { }

View File

@ -869,6 +869,7 @@ castNative(JSContext *cx,
}
else if(cur)
{
NS_ABORT_IF_FALSE(IS_SLIM_WRAPPER(cur), "should be a slim wrapper");
nsISupports *native = static_cast<nsISupports*>(xpc_GetJSPrivate(cur));
if(NS_SUCCEEDED(getNative(native, GetOffsetsFromSlimWrapper(cur),
cur, iid, ppThis, pThisRef, vp)))
@ -1133,8 +1134,7 @@ xpc_qsXPCOMObjectToJsval(XPCLazyCallContext &lccx, qsObjectHelper &aHelper,
nsresult rv;
if(!XPCConvert::NativeInterface2JSObject(lccx, rval, nsnull,
aHelper, iid, iface,
lccx.GetCurrentJSObject(), PR_TRUE,
OBJ_IS_NOT_GLOBAL, &rv))
PR_TRUE, OBJ_IS_NOT_GLOBAL, &rv))
{
// I can't tell if NativeInterface2JSObject throws JS exceptions
// or not. This is a sloppy stab at the right semantics; the
@ -1164,9 +1164,7 @@ xpc_qsVariantToJsval(XPCLazyCallContext &lccx,
if(p)
{
nsresult rv;
JSBool ok = XPCVariant::VariantDataToJS(lccx, p,
lccx.GetCurrentJSObject(),
&rv, rval);
JSBool ok = XPCVariant::VariantDataToJS(lccx, p, &rv, rval);
if (!ok)
xpc_qsThrow(lccx.GetJSContext(), rv);
return ok;

View File

@ -412,8 +412,7 @@ XPCVariant::GetAsJSVal(jsval* result)
JSBool
XPCVariant::VariantDataToJS(XPCLazyCallContext& lccx,
nsIVariant* variant,
JSObject* scope, nsresult* pErr,
jsval* pJSVal)
nsresult* pErr, jsval* pJSVal)
{
// Get the type early because we might need to spoof it below.
PRUint16 type;
@ -429,11 +428,8 @@ XPCVariant::VariantDataToJS(XPCLazyCallContext& lccx,
type == nsIDataType::VTYPE_EMPTY_ARRAY ||
type == nsIDataType::VTYPE_ID))
{
// It's not a JSObject (or it's a JSArray or a JSObject representing an
// nsID). Just pass through the underlying data.
JSAutoEnterCompartment ac;
JSContext *cx = lccx.GetJSContext();
if(!ac.enter(cx, scope) || !JS_WrapValue(cx, &realVal))
if(!JS_WrapValue(cx, &realVal))
return JS_FALSE;
*pJSVal = realVal;
return JS_TRUE;
@ -446,9 +442,8 @@ XPCVariant::VariantDataToJS(XPCLazyCallContext& lccx,
type == nsIDataType::VTYPE_INTERFACE_IS,
"Weird variant");
JSAutoEnterCompartment ac;
JSContext *cx = lccx.GetJSContext();
if(!ac.enter(cx, scope) || !JS_WrapValue(cx, &realVal))
if(!JS_WrapValue(cx, &realVal))
return JS_FALSE;
*pJSVal = realVal;
return JS_TRUE;
@ -474,6 +469,9 @@ XPCVariant::VariantDataToJS(XPCLazyCallContext& lccx,
JSBool success;
JSContext* cx = lccx.GetJSContext();
NS_ABORT_IF_FALSE(lccx.GetScopeForNewJSObjects()->compartment() == cx->compartment,
"bad scope for new JSObjects");
switch(type)
{
case nsIDataType::VTYPE_INT8:
@ -656,8 +654,7 @@ XPCVariant::VariantDataToJS(XPCLazyCallContext& lccx,
XPCConvert::NativeArray2JS(lccx, pJSVal,
(const void**)&du.u.array.mArrayValue,
conversionType, pid,
du.u.array.mArrayCount,
scope, pErr);
du.u.array.mArrayCount, pErr);
VARIANT_DONE:
nsVariant::Cleanup(&du);
@ -697,7 +694,7 @@ VARIANT_DONE:
success = XPCConvert::NativeData2JS(lccx, pJSVal,
(const void*)&xpctvar.val,
xpctvar.type,
&iid, scope, pErr);
&iid, pErr);
}
if(xpctvar.IsValAllocated())

View File

@ -1309,20 +1309,26 @@ nsXPCWrappedJSClass::CallMethod(nsXPCWrappedJS* wrapper, uint16 methodIndex,
cx = nsnull;
}
if(!cx || !xpcc || !IsReflectable(methodIndex))
return NS_ERROR_FAILURE;
obj = thisObj = wrapper->GetJSObject();
JSAutoEnterCompartment ac;
if (!ac.enter(cx, obj))
return NS_ERROR_FAILURE;
ccx.SetScopeForNewJSObjects(obj);
js::AutoValueVector args(cx);
AutoScriptEvaluate scriptEval(cx);
ContextPrincipalGuard principalGuard(ccx);
obj = thisObj = wrapper->GetJSObject();
// XXX ASSUMES that retval is last arg. The xpidl compiler ensures this.
paramCount = info->num_args;
argc = paramCount -
(paramCount && XPT_PD_IS_RETVAL(info->params[paramCount-1].flags) ? 1 : 0);
if(!cx || !xpcc || !IsReflectable(methodIndex))
goto pre_call_clean_up;
if (!scriptEval.StartEvaluating(obj, xpcWrappedJSErrorReporter))
goto pre_call_clean_up;
@ -1440,7 +1446,7 @@ nsXPCWrappedJSClass::CallMethod(nsXPCWrappedJS* wrapper, uint16 methodIndex,
JSBool ok =
XPCConvert::NativeInterface2JSObject(ccx,
&v, nsnull, helper, newWrapperIID,
nsnull, obj, PR_FALSE, PR_FALSE,
nsnull, PR_FALSE, PR_FALSE,
nsnull);
if(newWrapperIID)
nsMemory::Free(newWrapperIID);
@ -1477,41 +1483,6 @@ nsXPCWrappedJSClass::CallMethod(nsXPCWrappedJS* wrapper, uint16 methodIndex,
argv = args.jsval_begin();
sp = argv;
// Figure out what our callee is
if(XPT_MD_IS_GETTER(info->flags) || XPT_MD_IS_SETTER(info->flags))
{
// Pull the getter or setter off of |obj|
uintN attrs;
JSBool found;
JSPropertyOp getter;
JSStrictPropertyOp setter;
if(!JS_GetPropertyAttrsGetterAndSetter(cx, obj, name,
&attrs, &found,
&getter, &setter))
{
// XXX Do we want to report this exception?
JS_ClearPendingException(cx);
goto pre_call_clean_up;
}
if(XPT_MD_IS_GETTER(info->flags) && (attrs & JSPROP_GETTER))
{
// JSPROP_GETTER means the getter is actually a
// function object.
ccx.SetCallee(JS_FUNC_TO_DATA_PTR(JSObject*, getter));
}
else if(XPT_MD_IS_SETTER(info->flags) && (attrs & JSPROP_SETTER))
{
// JSPROP_SETTER means the setter is actually a
// function object.
ccx.SetCallee(JS_FUNC_TO_DATA_PTR(JSObject*, setter));
}
}
else if(JSVAL_IS_OBJECT(fval))
{
ccx.SetCallee(JSVAL_TO_OBJECT(fval));
}
// build the args
// NB: This assignment *looks* wrong because we haven't yet called our
// function. However, we *have* already entered the compartmen that we're
@ -1578,7 +1549,7 @@ nsXPCWrappedJSClass::CallMethod(nsXPCWrappedJS* wrapper, uint16 methodIndex,
if(!XPCConvert::NativeArray2JS(lccx, &val,
(const void**)&pv->val,
datum_type, &param_iid,
array_count, obj, nsnull))
array_count, nsnull))
goto pre_call_clean_up;
}
else if(isSizedString)
@ -1592,7 +1563,7 @@ nsXPCWrappedJSClass::CallMethod(nsXPCWrappedJS* wrapper, uint16 methodIndex,
else
{
if(!XPCConvert::NativeData2JS(ccx, &val, &pv->val, type,
&param_iid, obj, nsnull))
&param_iid, nsnull))
goto pre_call_clean_up;
}
}

View File

@ -2595,8 +2595,7 @@ CallMethodHelper::GatherAndConvertResults()
XPCLazyCallContext lccx(mCallContext);
if(!XPCConvert::NativeArray2JS(lccx, &v, (const void**)&dp->val,
datum_type, &param_iid,
array_count, mCallContext.GetCurrentJSObject(),
&err))
array_count, &err))
{
// XXX need exception scheme for arrays to indicate bad element
ThrowBadParam(err, i, mCallContext);
@ -2617,8 +2616,7 @@ CallMethodHelper::GatherAndConvertResults()
else
{
if(!XPCConvert::NativeData2JS(mCallContext, &v, &dp->val, datum_type,
&param_iid,
mCallContext.GetCurrentJSObject(), &err))
&param_iid, &err))
{
ThrowBadParam(err, i, mCallContext);
return JS_FALSE;
@ -2703,7 +2701,7 @@ CallMethodHelper::QueryInterfaceFastPath() const
JSBool success =
XPCConvert::NativeData2JS(mCallContext, &v, &qiresult,
nsXPTType::T_INTERFACE_IS | XPT_TDP_POINTER,
iid, mCallContext.GetCurrentJSObject(), &err);
iid, &err);
NS_IF_RELEASE(qiresult);
if(!success)

View File

@ -135,7 +135,7 @@ XPCNativeMember::Resolve(XPCCallContext& ccx, XPCNativeInterface* iface,
jsval resultVal;
if(!XPCConvert::NativeData2JS(ccx, &resultVal, &v.val, v.type,
nsnull, nsnull, nsnull))
nsnull, nsnull))
return JS_FALSE;
*vp = resultVal;

View File

@ -1690,6 +1690,7 @@ XPC_WN_Shared_Proto_Enumerate(JSContext *cx, JSObject *obj)
XPCCallContext ccx(JS_CALLER, cx);
if(!ccx.IsValid())
return JS_FALSE;
ccx.SetScopeForNewJSObjects(obj);
PRUint16 interface_count = set->GetInterfaceCount();
XPCNativeInterface** interfaceArray = set->GetInterfaceArray();
@ -1752,6 +1753,7 @@ XPC_WN_ModsAllowed_Proto_Resolve(JSContext *cx, JSObject *obj, jsid id)
XPCCallContext ccx(JS_CALLER, cx);
if(!ccx.IsValid())
return JS_FALSE;
ccx.SetScopeForNewJSObjects(obj);
XPCNativeScriptableInfo* si = self->GetScriptableInfo();
uintN enumFlag = (si && si->GetFlags().DontEnumStaticProps()) ?
@ -1835,6 +1837,7 @@ XPC_WN_OnlyIWrite_Proto_AddPropertyStub(JSContext *cx, JSObject *obj, jsid id, j
XPCCallContext ccx(JS_CALLER, cx);
if(!ccx.IsValid())
return JS_FALSE;
ccx.SetScopeForNewJSObjects(obj);
// Allow XPConnect to add the property only
if(ccx.GetResolveName() == id)
@ -1865,6 +1868,7 @@ XPC_WN_NoMods_Proto_Resolve(JSContext *cx, JSObject *obj, jsid id)
XPCCallContext ccx(JS_CALLER, cx);
if(!ccx.IsValid())
return JS_FALSE;
ccx.SetScopeForNewJSObjects(obj);
XPCNativeScriptableInfo* si = self->GetScriptableInfo();
uintN enumFlag = (si && si->GetFlags().DontEnumStaticProps()) ?

View File

@ -184,26 +184,31 @@ WrapperFactory::PrepareForWrapping(JSContext *cx, JSObject *scope, JSObject *obj
if (!wn->GetClassInfo())
return DoubleWrap(cx, obj, flags);
XPCCallContext ccx(JS_CALLER, cx, obj);
if (NATIVE_HAS_FLAG(&ccx, WantPreCreate)) {
// We have a precreate hook. This object might enforce that we only
// ever create JS object for it.
JSObject *originalScope = scope;
nsresult rv = wn->GetScriptableInfo()->GetCallback()->
PreCreate(wn->Native(), cx, scope, &scope);
NS_ENSURE_SUCCESS(rv, DoubleWrap(cx, obj, flags));
{
JSAutoEnterCompartment ac;
if (!ac.enter(cx, obj))
return nsnull;
XPCCallContext ccx(JS_CALLER, cx, obj);
if (NATIVE_HAS_FLAG(&ccx, WantPreCreate)) {
// We have a precreate hook. This object might enforce that we only
// ever create JS object for it.
JSObject *originalScope = scope;
nsresult rv = wn->GetScriptableInfo()->GetCallback()->
PreCreate(wn->Native(), cx, scope, &scope);
NS_ENSURE_SUCCESS(rv, DoubleWrap(cx, obj, flags));
// If the handed back scope differs from the passed-in scope and is in
// a separate compartment, then this object is explicitly requesting
// that we don't create a second JS object for it: create a security
// wrapper.
if (originalScope->compartment() != scope->getCompartment())
return DoubleWrap(cx, obj, flags);
// If the handed back scope differs from the passed-in scope and is in
// a separate compartment, then this object is explicitly requesting
// that we don't create a second JS object for it: create a security
// wrapper.
if (originalScope->compartment() != scope->getCompartment())
return DoubleWrap(cx, obj, flags);
// Note: this penalizes objects that only have one wrapper, but are
// being accessed across compartments. We would really prefer to
// replace the above code with a test that says "do you only have one
// wrapper?"
// Note: this penalizes objects that only have one wrapper, but are
// being accessed across compartments. We would really prefer to
// replace the above code with a test that says "do you only have one
// wrapper?"
}
}
// The object we're looking at might allow us to create a new wrapped