mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-24 21:31:04 +00:00
Bug 522621 - Use namespaces in the wrapper code and generally clean up the internal interfaces between the wrappers. r=jst
This commit is contained in:
parent
44e1ce7702
commit
2e37e51b5b
@ -244,7 +244,11 @@ XPC_COW_Iterator(JSContext *cx, JSObject *obj, JSBool keysonly);
|
||||
static JSObject *
|
||||
XPC_COW_WrappedObject(JSContext *cx, JSObject *obj);
|
||||
|
||||
JSExtendedClass sXPC_COW_JSClass = {
|
||||
using namespace XPCWrapper;
|
||||
|
||||
namespace ChromeObjectWrapper {
|
||||
|
||||
JSExtendedClass COWClass = {
|
||||
// JSClass (JSExtendedClass.base) initialization
|
||||
{ "ChromeObjectWrapper",
|
||||
JSCLASS_NEW_RESOLVE | JSCLASS_IS_EXTENDED |
|
||||
@ -268,11 +272,43 @@ JSExtendedClass sXPC_COW_JSClass = {
|
||||
JSCLASS_NO_RESERVED_MEMBERS
|
||||
};
|
||||
|
||||
JSBool
|
||||
WrapObject(JSContext *cx, JSObject *parent, jsval v, jsval *vp)
|
||||
{
|
||||
JSObject *wrapperObj =
|
||||
JS_NewObjectWithGivenProto(cx, &COWClass.base, NULL, parent);
|
||||
if (!wrapperObj) {
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
*vp = OBJECT_TO_JSVAL(wrapperObj);
|
||||
|
||||
jsval exposedProps = JSVAL_VOID;
|
||||
JSAutoTempValueRooter tvr(cx, 1, &exposedProps);
|
||||
|
||||
if (!GetExposedProperties(cx, JSVAL_TO_OBJECT(v), &exposedProps)) {
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
if (!JS_SetReservedSlot(cx, wrapperObj, XPCWrapper::sWrappedObjSlot, v) ||
|
||||
!JS_SetReservedSlot(cx, wrapperObj, XPCWrapper::sFlagsSlot,
|
||||
JSVAL_ZERO) ||
|
||||
!JS_SetReservedSlot(cx, wrapperObj, sExposedPropsSlot, exposedProps)) {
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
} // namespace ChromeObjectWrapper
|
||||
|
||||
using namespace ChromeObjectWrapper;
|
||||
|
||||
// Throws an exception on context |cx|.
|
||||
static inline JSBool
|
||||
ThrowException(nsresult rv, JSContext *cx)
|
||||
{
|
||||
return XPCWrapper::ThrowException(rv, cx);
|
||||
return XPCWrapper::DoThrowException(rv, cx);
|
||||
}
|
||||
|
||||
// Like GetWrappedObject, but works on other types of wrappers, too.
|
||||
@ -305,7 +341,7 @@ static inline
|
||||
JSObject *
|
||||
GetWrapper(JSObject *obj)
|
||||
{
|
||||
while (STOBJ_GET_CLASS(obj) != &sXPC_COW_JSClass.base) {
|
||||
while (STOBJ_GET_CLASS(obj) != &COWClass.base) {
|
||||
obj = STOBJ_GET_PROTO(obj);
|
||||
if (!obj) {
|
||||
break;
|
||||
@ -320,7 +356,7 @@ static inline
|
||||
JSObject *
|
||||
GetWrappedObject(JSContext *cx, JSObject *wrapper)
|
||||
{
|
||||
return XPCWrapper::UnwrapGeneric(cx, &sXPC_COW_JSClass, wrapper);
|
||||
return XPCWrapper::UnwrapGeneric(cx, &COWClass, wrapper);
|
||||
}
|
||||
|
||||
// Forward declaration for the function wrapper.
|
||||
@ -423,7 +459,7 @@ XPC_COW_RewrapForChrome(JSContext *cx, JSObject *wrapperObj, jsval *vp)
|
||||
return XPCNativeWrapper::CreateExplicitWrapper(cx, wn, JS_TRUE, vp);
|
||||
}
|
||||
|
||||
return XPC_SJOW_Construct(cx, obj, 1, vp, vp);
|
||||
return XPCSafeJSObjectWrapper::WrapObject(cx, obj, *vp, vp);
|
||||
}
|
||||
|
||||
JSBool
|
||||
@ -444,8 +480,7 @@ XPC_COW_RewrapForContent(JSContext *cx, JSObject *wrapperObj, jsval *vp)
|
||||
return XPC_COW_WrapFunction(cx, wrapperObj, obj, vp);
|
||||
}
|
||||
|
||||
return XPC_COW_WrapObject(cx, JS_GetScopeChain(cx), OBJECT_TO_JSVAL(obj),
|
||||
vp);
|
||||
return WrapObject(cx, JS_GetScopeChain(cx), OBJECT_TO_JSVAL(obj), vp);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
@ -482,7 +517,7 @@ XPC_COW_AddProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
|
||||
|
||||
if (desc.attrs & (JSPROP_GETTER | JSPROP_SETTER)) {
|
||||
// Only chrome is allowed to add getters or setters to our object.
|
||||
if (!AllowedToAct(cx, id)) {
|
||||
if (!SystemOnlyWrapper::AllowedToAct(cx, id)) {
|
||||
return JS_FALSE;
|
||||
}
|
||||
}
|
||||
@ -714,7 +749,7 @@ XPC_COW_Iterator(JSContext *cx, JSObject *obj, JSBool keysonly)
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
JSObject *wrapperIter = JS_NewObject(cx, &sXPC_COW_JSClass.base, nsnull,
|
||||
JSObject *wrapperIter = JS_NewObject(cx, &COWClass.base, nsnull,
|
||||
JS_GetGlobalForObject(cx, obj));
|
||||
if (!wrapperIter) {
|
||||
return nsnull;
|
||||
@ -739,31 +774,3 @@ XPC_COW_WrappedObject(JSContext *cx, JSObject *obj)
|
||||
{
|
||||
return GetWrappedObject(cx, obj);
|
||||
}
|
||||
|
||||
JSBool
|
||||
XPC_COW_WrapObject(JSContext *cx, JSObject *parent, jsval v, jsval *vp)
|
||||
{
|
||||
JSObject *wrapperObj =
|
||||
JS_NewObjectWithGivenProto(cx, &sXPC_COW_JSClass.base, NULL, parent);
|
||||
if (!wrapperObj) {
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
*vp = OBJECT_TO_JSVAL(wrapperObj);
|
||||
|
||||
jsval exposedProps = JSVAL_VOID;
|
||||
JSAutoTempValueRooter tvr(cx, 1, &exposedProps);
|
||||
|
||||
if (!GetExposedProperties(cx, JSVAL_TO_OBJECT(v), &exposedProps)) {
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
if (!JS_SetReservedSlot(cx, wrapperObj, XPCWrapper::sWrappedObjSlot, v) ||
|
||||
!JS_SetReservedSlot(cx, wrapperObj, XPCWrapper::sFlagsSlot,
|
||||
JSVAL_ZERO) ||
|
||||
!JS_SetReservedSlot(cx, wrapperObj, sExposedPropsSlot, exposedProps)) {
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
@ -96,7 +96,63 @@ XPC_XOW_Iterator(JSContext *cx, JSObject *obj, JSBool keysonly);
|
||||
static JSObject *
|
||||
XPC_XOW_WrappedObject(JSContext *cx, JSObject *obj);
|
||||
|
||||
JSExtendedClass sXPC_XOW_JSClass = {
|
||||
// The slot that we stick our scope into.
|
||||
// This is used in the finalizer to see if we actually need to remove
|
||||
// ourselves from our scope's map. Because we cannot outlive our scope
|
||||
// (the parent link ensures this), we know that, when we're being
|
||||
// finalized, either our scope is still alive (i.e. we became garbage
|
||||
// due to no more references) or it is being garbage collected right now.
|
||||
// Therefore, we can look in gDyingScopes, and if our scope is there,
|
||||
// then the map is about to be destroyed anyway, so we don't need to
|
||||
// do anything.
|
||||
static const int XPC_XOW_ScopeSlot = XPCWrapper::sNumSlots;
|
||||
static const int sUXPCObjectSlot = XPCWrapper::sNumSlots + 1;
|
||||
|
||||
using namespace XPCWrapper;
|
||||
|
||||
// Throws an exception on context |cx|.
|
||||
static inline
|
||||
JSBool
|
||||
ThrowException(nsresult ex, JSContext *cx)
|
||||
{
|
||||
XPCWrapper::DoThrowException(ex, cx);
|
||||
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
// Get the (possibly non-existant) XOW off of an object
|
||||
static inline
|
||||
JSObject *
|
||||
GetWrapper(JSObject *obj)
|
||||
{
|
||||
while (STOBJ_GET_CLASS(obj) != &XPCCrossOriginWrapper::XOWClass.base) {
|
||||
obj = STOBJ_GET_PROTO(obj);
|
||||
if (!obj) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
static inline
|
||||
JSObject *
|
||||
GetWrappedObject(JSContext *cx, JSObject *wrapper)
|
||||
{
|
||||
return XPCWrapper::UnwrapGeneric(cx, &XPCCrossOriginWrapper::XOWClass, wrapper);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
XPC_XOW_FunctionWrapper(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
||||
jsval *rval);
|
||||
|
||||
// This flag is set on objects that were created for UniversalXPConnect-
|
||||
// enabled code.
|
||||
static const PRUint32 FLAG_IS_UXPC_OBJECT = XPCWrapper::LAST_FLAG << 1;
|
||||
|
||||
namespace XPCCrossOriginWrapper {
|
||||
|
||||
JSExtendedClass XOWClass = {
|
||||
// JSClass (JSExtendedClass.base) initialization
|
||||
{ "XPCCrossOriginWrapper",
|
||||
JSCLASS_NEW_RESOLVE | JSCLASS_IS_EXTENDED |
|
||||
@ -120,56 +176,8 @@ JSExtendedClass sXPC_XOW_JSClass = {
|
||||
JSCLASS_NO_RESERVED_MEMBERS
|
||||
};
|
||||
|
||||
// The slot that we stick our scope into.
|
||||
// This is used in the finalizer to see if we actually need to remove
|
||||
// ourselves from our scope's map. Because we cannot outlive our scope
|
||||
// (the parent link ensures this), we know that, when we're being
|
||||
// finalized, either our scope is still alive (i.e. we became garbage
|
||||
// due to no more references) or it is being garbage collected right now.
|
||||
// Therefore, we can look in gDyingScopes, and if our scope is there,
|
||||
// then the map is about to be destroyed anyway, so we don't need to
|
||||
// do anything.
|
||||
static const int XPC_XOW_ScopeSlot = XPCWrapper::sNumSlots;
|
||||
static const int sUXPCObjectSlot = XPCWrapper::sNumSlots + 1;
|
||||
|
||||
static JSBool
|
||||
XPC_XOW_toString(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
||||
jsval *rval);
|
||||
|
||||
// Throws an exception on context |cx|.
|
||||
static inline
|
||||
JSBool
|
||||
ThrowException(nsresult ex, JSContext *cx)
|
||||
{
|
||||
XPCThrower::Throw(ex, cx);
|
||||
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
// Get the (possibly non-existant) XOW off of an object
|
||||
static inline
|
||||
JSObject *
|
||||
GetWrapper(JSObject *obj)
|
||||
{
|
||||
while (STOBJ_GET_CLASS(obj) != &sXPC_XOW_JSClass.base) {
|
||||
obj = STOBJ_GET_PROTO(obj);
|
||||
if (!obj) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
static inline
|
||||
JSObject *
|
||||
GetWrappedObject(JSContext *cx, JSObject *wrapper)
|
||||
{
|
||||
return XPCWrapper::UnwrapGeneric(cx, &sXPC_XOW_JSClass, wrapper);
|
||||
}
|
||||
|
||||
JSBool
|
||||
XPC_XOW_WrapperMoved(JSContext *cx, XPCWrappedNative *innerObj,
|
||||
WrapperMoved(JSContext *cx, XPCWrappedNative *innerObj,
|
||||
XPCWrappedNativeScope *newScope)
|
||||
{
|
||||
typedef WrappedNative2WrapperMap::Link Link;
|
||||
@ -206,36 +214,6 @@ XPC_XOW_WrapperMoved(JSContext *cx, XPCWrappedNative *innerObj,
|
||||
JS_SetParent(cx, xow, newScope->GetGlobalJSObject());
|
||||
}
|
||||
|
||||
static JSBool
|
||||
IsValFrame(JSObject *obj, jsval v, XPCWrappedNative *wn)
|
||||
{
|
||||
// Fast path for the common case.
|
||||
if (STOBJ_GET_CLASS(obj)->name[0] != 'W') {
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDOMWindow> domwin(do_QueryWrappedNative(wn));
|
||||
if (!domwin) {
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDOMWindowCollection> col;
|
||||
domwin->GetFrames(getter_AddRefs(col));
|
||||
if (!col) {
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
if (JSVAL_IS_INT(v)) {
|
||||
col->Item(JSVAL_TO_INT(v), getter_AddRefs(domwin));
|
||||
} else {
|
||||
nsAutoString str(reinterpret_cast<PRUnichar *>
|
||||
(JS_GetStringChars(JSVAL_TO_STRING(v))));
|
||||
col->NamedItem(str, getter_AddRefs(domwin));
|
||||
}
|
||||
|
||||
return domwin != nsnull;
|
||||
}
|
||||
|
||||
// Returns whether the currently executing code is allowed to access
|
||||
// the wrapper. Uses nsIPrincipal::Subsumes.
|
||||
// |cx| must be the top context on the context stack.
|
||||
@ -308,96 +286,8 @@ CanAccessWrapper(JSContext *cx, JSObject *wrappedObj, JSBool *privilegeEnabled)
|
||||
return rv;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
WrapSameOriginProp(JSContext *cx, JSObject *outerObj, jsval *vp);
|
||||
|
||||
static JSBool
|
||||
XPC_XOW_FunctionWrapper(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
||||
jsval *rval)
|
||||
{
|
||||
JSObject *wrappedObj, *outerObj = obj;
|
||||
|
||||
// Allow 'this' to be either an XOW, in which case we unwrap it.
|
||||
// We disallow invalid XOWs that have no wrapped object. Otherwise,
|
||||
// if it isn't an XOW, then pass it through as-is.
|
||||
|
||||
wrappedObj = GetWrapper(obj);
|
||||
if (wrappedObj) {
|
||||
wrappedObj = GetWrappedObject(cx, wrappedObj);
|
||||
if (!wrappedObj) {
|
||||
return ThrowException(NS_ERROR_ILLEGAL_VALUE, cx);
|
||||
}
|
||||
} else {
|
||||
wrappedObj = obj;
|
||||
}
|
||||
|
||||
JSObject *funObj = JSVAL_TO_OBJECT(argv[-2]);
|
||||
jsval funToCall;
|
||||
if (!JS_GetReservedSlot(cx, funObj, XPCWrapper::eWrappedFunctionSlot,
|
||||
&funToCall)) {
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
JSFunction *fun = JS_ValueToFunction(cx, funToCall);
|
||||
if (!fun) {
|
||||
return ThrowException(NS_ERROR_ILLEGAL_VALUE, cx);
|
||||
}
|
||||
|
||||
XPCCallContext ccx(JS_CALLER, cx);
|
||||
if (!ccx.IsValid()) {
|
||||
return ThrowException(NS_ERROR_FAILURE, cx);
|
||||
}
|
||||
|
||||
nsresult rv = CanAccessWrapper(cx, JSVAL_TO_OBJECT(funToCall), nsnull);
|
||||
if (NS_FAILED(rv) && rv != NS_ERROR_DOM_PROP_ACCESS_DENIED) {
|
||||
return ThrowException(rv, cx);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
JSNative native = JS_GetFunctionNative(cx, fun);
|
||||
NS_ASSERTION(native, "How'd we get here with a scripted function?");
|
||||
#endif
|
||||
|
||||
if (!JS_CallFunctionValue(cx, wrappedObj, funToCall, argc, argv, rval)) {
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
return WrapSameOriginProp(cx, outerObj, rval);
|
||||
}
|
||||
|
||||
return XPC_XOW_RewrapIfNeeded(cx, obj, rval);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
WrapSameOriginProp(JSContext *cx, JSObject *outerObj, jsval *vp)
|
||||
{
|
||||
// Don't call XPC_XOW_RewrapIfNeeded for same origin properties. We only
|
||||
// need to wrap window, document and location.
|
||||
if (JSVAL_IS_PRIMITIVE(*vp)) {
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JSObject *wrappedObj = JSVAL_TO_OBJECT(*vp);
|
||||
JSClass *clasp = STOBJ_GET_CLASS(wrappedObj);
|
||||
if (XPC_XOW_ClassNeedsXOW(clasp->name)) {
|
||||
return XPC_XOW_WrapObject(cx, JS_GetGlobalForObject(cx, outerObj), vp);
|
||||
}
|
||||
|
||||
// Check if wrappedObj is an XOW. If so, verify that it's from the
|
||||
// right scope.
|
||||
if (clasp == &sXPC_XOW_JSClass.base &&
|
||||
STOBJ_GET_PARENT(wrappedObj) != STOBJ_GET_PARENT(outerObj)) {
|
||||
*vp = OBJECT_TO_JSVAL(GetWrappedObject(cx, wrappedObj));
|
||||
return XPC_XOW_WrapObject(cx, STOBJ_GET_PARENT(outerObj), vp);
|
||||
}
|
||||
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JSBool
|
||||
XPC_XOW_WrapFunction(JSContext *cx, JSObject *outerObj, JSObject *funobj,
|
||||
jsval *rval)
|
||||
WrapFunction(JSContext *cx, JSObject *outerObj, JSObject *funobj, jsval *rval)
|
||||
{
|
||||
jsval funobjVal = OBJECT_TO_JSVAL(funobj);
|
||||
JSFunction *wrappedFun =
|
||||
@ -420,10 +310,8 @@ XPC_XOW_WrapFunction(JSContext *cx, JSObject *outerObj, JSObject *funobj,
|
||||
JSObject *funWrapperObj = JS_GetFunctionObject(funWrapper);
|
||||
*rval = OBJECT_TO_JSVAL(funWrapperObj);
|
||||
|
||||
if (!JS_SetReservedSlot(cx, funWrapperObj, XPCWrapper::eWrappedFunctionSlot,
|
||||
funobjVal) ||
|
||||
!JS_SetReservedSlot(cx, funWrapperObj, XPCWrapper::eAllAccessSlot,
|
||||
JSVAL_FALSE)) {
|
||||
if (!JS_SetReservedSlot(cx, funWrapperObj, eWrappedFunctionSlot, funobjVal) ||
|
||||
!JS_SetReservedSlot(cx, funWrapperObj, eAllAccessSlot, JSVAL_FALSE)) {
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
@ -431,7 +319,7 @@ XPC_XOW_WrapFunction(JSContext *cx, JSObject *outerObj, JSObject *funobj,
|
||||
}
|
||||
|
||||
JSBool
|
||||
XPC_XOW_RewrapIfNeeded(JSContext *cx, JSObject *outerObj, jsval *vp)
|
||||
RewrapIfNeeded(JSContext *cx, JSObject *outerObj, jsval *vp)
|
||||
{
|
||||
// Don't need to wrap primitive values.
|
||||
if (JSVAL_IS_PRIMITIVE(*vp)) {
|
||||
@ -441,23 +329,22 @@ XPC_XOW_RewrapIfNeeded(JSContext *cx, JSObject *outerObj, jsval *vp)
|
||||
JSObject *obj = JSVAL_TO_OBJECT(*vp);
|
||||
|
||||
if (JS_ObjectIsFunction(cx, obj)) {
|
||||
return XPC_XOW_WrapFunction(cx, outerObj, obj, vp);
|
||||
return WrapFunction(cx, outerObj, obj, vp);
|
||||
}
|
||||
|
||||
XPCWrappedNative *wn = nsnull;
|
||||
if (STOBJ_GET_CLASS(obj) == &sXPC_XOW_JSClass.base &&
|
||||
if (STOBJ_GET_CLASS(obj) == &XOWClass.base &&
|
||||
STOBJ_GET_PARENT(outerObj) != STOBJ_GET_PARENT(obj)) {
|
||||
*vp = OBJECT_TO_JSVAL(GetWrappedObject(cx, obj));
|
||||
} else if (!(wn = XPCWrappedNative::GetAndMorphWrappedNativeOfJSObject(cx, obj))) {
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
return XPC_XOW_WrapObject(cx, JS_GetGlobalForObject(cx, outerObj), vp, wn);
|
||||
return WrapObject(cx, JS_GetGlobalForObject(cx, outerObj), vp, wn);
|
||||
}
|
||||
|
||||
JSBool
|
||||
XPC_XOW_WrapObject(JSContext *cx, JSObject *parent, jsval *vp,
|
||||
XPCWrappedNative* wn)
|
||||
WrapObject(JSContext *cx, JSObject *parent, jsval *vp, XPCWrappedNative* wn)
|
||||
{
|
||||
NS_ASSERTION(XPCPerThreadData::IsMainThread(cx),
|
||||
"Can't do this off the main thread!");
|
||||
@ -467,7 +354,7 @@ XPC_XOW_WrapObject(JSContext *cx, JSObject *parent, jsval *vp,
|
||||
JSObject *wrappedObj;
|
||||
if (!JSVAL_IS_OBJECT(*vp) ||
|
||||
!(wrappedObj = JSVAL_TO_OBJECT(*vp)) ||
|
||||
STOBJ_GET_CLASS(wrappedObj) == &sXPC_XOW_JSClass.base) {
|
||||
STOBJ_GET_CLASS(wrappedObj) == &XOWClass.base) {
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
@ -506,7 +393,7 @@ XPC_XOW_WrapObject(JSContext *cx, JSObject *parent, jsval *vp,
|
||||
|
||||
outerObj = map->Find(wrappedObj);
|
||||
if (outerObj) {
|
||||
NS_ASSERTION(STOBJ_GET_CLASS(outerObj) == &sXPC_XOW_JSClass.base,
|
||||
NS_ASSERTION(STOBJ_GET_CLASS(outerObj) == &XOWClass.base,
|
||||
"What crazy object are we getting here?");
|
||||
#ifdef DEBUG_mrbkap_off
|
||||
printf("But found a wrapper in the map %p!\n", (void *)outerObj);
|
||||
@ -515,15 +402,14 @@ XPC_XOW_WrapObject(JSContext *cx, JSObject *parent, jsval *vp,
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
outerObj = JS_NewObjectWithGivenProto(cx, &sXPC_XOW_JSClass.base, nsnull,
|
||||
outerObj = JS_NewObjectWithGivenProto(cx, &XOWClass.base, nsnull,
|
||||
parent);
|
||||
if (!outerObj) {
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
if (!JS_SetReservedSlot(cx, outerObj, XPCWrapper::sWrappedObjSlot, *vp) ||
|
||||
!JS_SetReservedSlot(cx, outerObj, XPCWrapper::sFlagsSlot,
|
||||
JSVAL_ZERO) ||
|
||||
if (!JS_SetReservedSlot(cx, outerObj, sWrappedObjSlot, *vp) ||
|
||||
!JS_SetReservedSlot(cx, outerObj, sFlagsSlot, JSVAL_ZERO) ||
|
||||
!JS_SetReservedSlot(cx, outerObj, XPC_XOW_ScopeSlot,
|
||||
PRIVATE_TO_JSVAL(parentScope))) {
|
||||
return JS_FALSE;
|
||||
@ -536,6 +422,130 @@ XPC_XOW_WrapObject(JSContext *cx, JSObject *parent, jsval *vp,
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
} // namespace XPCCrossOriginWrapper
|
||||
|
||||
using namespace XPCCrossOriginWrapper;
|
||||
|
||||
static JSBool
|
||||
XPC_XOW_toString(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
||||
jsval *rval);
|
||||
|
||||
static JSBool
|
||||
IsValFrame(JSObject *obj, jsval v, XPCWrappedNative *wn)
|
||||
{
|
||||
// Fast path for the common case.
|
||||
if (STOBJ_GET_CLASS(obj)->name[0] != 'W') {
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDOMWindow> domwin(do_QueryWrappedNative(wn));
|
||||
if (!domwin) {
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDOMWindowCollection> col;
|
||||
domwin->GetFrames(getter_AddRefs(col));
|
||||
if (!col) {
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
if (JSVAL_IS_INT(v)) {
|
||||
col->Item(JSVAL_TO_INT(v), getter_AddRefs(domwin));
|
||||
} else {
|
||||
nsAutoString str(reinterpret_cast<PRUnichar *>
|
||||
(JS_GetStringChars(JSVAL_TO_STRING(v))));
|
||||
col->NamedItem(str, getter_AddRefs(domwin));
|
||||
}
|
||||
|
||||
return domwin != nsnull;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
WrapSameOriginProp(JSContext *cx, JSObject *outerObj, jsval *vp);
|
||||
|
||||
static JSBool
|
||||
XPC_XOW_FunctionWrapper(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
||||
jsval *rval)
|
||||
{
|
||||
JSObject *wrappedObj, *outerObj = obj;
|
||||
|
||||
// Allow 'this' to be either an XOW, in which case we unwrap it.
|
||||
// We disallow invalid XOWs that have no wrapped object. Otherwise,
|
||||
// if it isn't an XOW, then pass it through as-is.
|
||||
|
||||
wrappedObj = GetWrapper(obj);
|
||||
if (wrappedObj) {
|
||||
wrappedObj = GetWrappedObject(cx, wrappedObj);
|
||||
if (!wrappedObj) {
|
||||
return ThrowException(NS_ERROR_ILLEGAL_VALUE, cx);
|
||||
}
|
||||
} else {
|
||||
wrappedObj = obj;
|
||||
}
|
||||
|
||||
JSObject *funObj = JSVAL_TO_OBJECT(argv[-2]);
|
||||
jsval funToCall;
|
||||
if (!JS_GetReservedSlot(cx, funObj, eWrappedFunctionSlot, &funToCall)) {
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
JSFunction *fun = JS_ValueToFunction(cx, funToCall);
|
||||
if (!fun) {
|
||||
return ThrowException(NS_ERROR_ILLEGAL_VALUE, cx);
|
||||
}
|
||||
|
||||
XPCCallContext ccx(JS_CALLER, cx);
|
||||
if (!ccx.IsValid()) {
|
||||
return ThrowException(NS_ERROR_FAILURE, cx);
|
||||
}
|
||||
|
||||
nsresult rv = CanAccessWrapper(cx, JSVAL_TO_OBJECT(funToCall), nsnull);
|
||||
if (NS_FAILED(rv) && rv != NS_ERROR_DOM_PROP_ACCESS_DENIED) {
|
||||
return ThrowException(rv, cx);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
JSNative native = JS_GetFunctionNative(cx, fun);
|
||||
NS_ASSERTION(native, "How'd we get here with a scripted function?");
|
||||
#endif
|
||||
|
||||
if (!JS_CallFunctionValue(cx, wrappedObj, funToCall, argc, argv, rval)) {
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
return WrapSameOriginProp(cx, outerObj, rval);
|
||||
}
|
||||
|
||||
return RewrapIfNeeded(cx, obj, rval);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
WrapSameOriginProp(JSContext *cx, JSObject *outerObj, jsval *vp)
|
||||
{
|
||||
// Don't call RewrapIfNeeded for same origin properties. We only
|
||||
// need to wrap window, document and location.
|
||||
if (JSVAL_IS_PRIMITIVE(*vp)) {
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JSObject *wrappedObj = JSVAL_TO_OBJECT(*vp);
|
||||
JSClass *clasp = STOBJ_GET_CLASS(wrappedObj);
|
||||
if (ClassNeedsXOW(clasp->name)) {
|
||||
return WrapObject(cx, JS_GetGlobalForObject(cx, outerObj), vp);
|
||||
}
|
||||
|
||||
// Check if wrappedObj is an XOW. If so, verify that it's from the
|
||||
// right scope.
|
||||
if (clasp == &XOWClass.base &&
|
||||
STOBJ_GET_PARENT(wrappedObj) != STOBJ_GET_PARENT(outerObj)) {
|
||||
*vp = OBJECT_TO_JSVAL(GetWrappedObject(cx, wrappedObj));
|
||||
return WrapObject(cx, STOBJ_GET_PARENT(outerObj), vp);
|
||||
}
|
||||
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
XPC_XOW_AddProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
|
||||
{
|
||||
@ -544,7 +554,7 @@ XPC_XOW_AddProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
|
||||
|
||||
obj = GetWrapper(obj);
|
||||
jsval resolving;
|
||||
if (!JS_GetReservedSlot(cx, obj, XPCWrapper::sFlagsSlot, &resolving)) {
|
||||
if (!JS_GetReservedSlot(cx, obj, sFlagsSlot, &resolving)) {
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
@ -574,7 +584,7 @@ XPC_XOW_AddProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
|
||||
}
|
||||
|
||||
// Same origin, pass this request along.
|
||||
return XPCWrapper::AddProperty(cx, obj, JS_TRUE, wrappedObj, id, vp);
|
||||
return AddProperty(cx, obj, JS_TRUE, wrappedObj, id, vp);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
@ -600,7 +610,7 @@ XPC_XOW_DelProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
|
||||
}
|
||||
|
||||
// Same origin, pass this request along.
|
||||
return XPCWrapper::DelProperty(cx, wrappedObj, id, vp);
|
||||
return DelProperty(cx, wrappedObj, id, vp);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
@ -656,22 +666,21 @@ XPC_XOW_GetOrSetProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp,
|
||||
XPCWrappedNative::GetWrappedNativeOfJSObject(cx, wrappedObj);
|
||||
NS_ASSERTION(wn, "How did we wrap a non-WrappedNative?");
|
||||
if (!IsValFrame(wrappedObj, id, wn)) {
|
||||
nsIScriptSecurityManager *ssm = XPCWrapper::GetSecurityManager();
|
||||
nsIScriptSecurityManager *ssm = GetSecurityManager();
|
||||
if (!ssm) {
|
||||
return ThrowException(NS_ERROR_NOT_INITIALIZED, cx);
|
||||
}
|
||||
rv = ssm->CheckPropertyAccess(cx, wrappedObj,
|
||||
STOBJ_GET_CLASS(wrappedObj)->name,
|
||||
id, isSet ? XPCWrapper::sSecMgrSetProp
|
||||
: XPCWrapper::sSecMgrGetProp);
|
||||
id, isSet ? sSecMgrSetProp
|
||||
: sSecMgrGetProp);
|
||||
if (NS_FAILED(rv)) {
|
||||
// The security manager threw an exception for us.
|
||||
return JS_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
return XPCWrapper::GetOrSetNativeProperty(cx, obj, wn, id, vp, isSet,
|
||||
JS_FALSE);
|
||||
return GetOrSetNativeProperty(cx, obj, wn, id, vp, isSet, JS_FALSE);
|
||||
}
|
||||
|
||||
JSObject *proto = nsnull; // Initialize this to quiet GCC.
|
||||
@ -764,7 +773,7 @@ XPC_XOW_Enumerate(JSContext *cx, JSObject *obj)
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
return XPCWrapper::Enumerate(cx, obj, wrappedObj);
|
||||
return Enumerate(cx, obj, wrappedObj);
|
||||
}
|
||||
|
||||
// Because of the drastically different ways that same- and cross-origin XOWs
|
||||
@ -785,10 +794,10 @@ XPC_XOW_Enumerate(JSContext *cx, JSObject *obj)
|
||||
static JSObject *
|
||||
GetUXPCObject(JSContext *cx, JSObject *obj)
|
||||
{
|
||||
NS_ASSERTION(STOBJ_GET_CLASS(obj) == &sXPC_XOW_JSClass.base, "wrong object");
|
||||
NS_ASSERTION(STOBJ_GET_CLASS(obj) == &XOWClass.base, "wrong object");
|
||||
|
||||
jsval v;
|
||||
if (!JS_GetReservedSlot(cx, obj, XPCWrapper::sFlagsSlot, &v)) {
|
||||
if (!JS_GetReservedSlot(cx, obj, sFlagsSlot, &v)) {
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
@ -805,7 +814,7 @@ GetUXPCObject(JSContext *cx, JSObject *obj)
|
||||
}
|
||||
|
||||
JSObject *uxpco =
|
||||
JS_NewObjectWithGivenProto(cx, &sXPC_XOW_JSClass.base, nsnull,
|
||||
JS_NewObjectWithGivenProto(cx, &XOWClass.base, nsnull,
|
||||
STOBJ_GET_PARENT(obj));
|
||||
if (!uxpco) {
|
||||
return nsnull;
|
||||
@ -814,13 +823,13 @@ GetUXPCObject(JSContext *cx, JSObject *obj)
|
||||
JSAutoTempValueRooter tvr(cx, uxpco);
|
||||
|
||||
jsval wrappedObj, parentScope;
|
||||
if (!JS_GetReservedSlot(cx, obj, XPCWrapper::sWrappedObjSlot, &wrappedObj) ||
|
||||
if (!JS_GetReservedSlot(cx, obj, sWrappedObjSlot, &wrappedObj) ||
|
||||
!JS_GetReservedSlot(cx, obj, XPC_XOW_ScopeSlot, &parentScope)) {
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
if (!JS_SetReservedSlot(cx, uxpco, XPCWrapper::sWrappedObjSlot, wrappedObj) ||
|
||||
!JS_SetReservedSlot(cx, uxpco, XPCWrapper::sFlagsSlot,
|
||||
if (!JS_SetReservedSlot(cx, uxpco, sWrappedObjSlot, wrappedObj) ||
|
||||
!JS_SetReservedSlot(cx, uxpco, sFlagsSlot,
|
||||
INT_TO_JSVAL(FLAG_IS_UXPC_OBJECT)) ||
|
||||
!JS_SetReservedSlot(cx, uxpco, XPC_XOW_ScopeSlot, parentScope)) {
|
||||
return nsnull;
|
||||
@ -867,14 +876,14 @@ XPC_XOW_NewResolve(JSContext *cx, JSObject *obj, jsval id, uintN flags,
|
||||
XPCWrappedNative::GetWrappedNativeOfJSObject(cx, wrappedObj);
|
||||
NS_ASSERTION(wn, "How did we wrap a non-WrappedNative?");
|
||||
if (!IsValFrame(wrappedObj, id, wn)) {
|
||||
nsIScriptSecurityManager *ssm = XPCWrapper::GetSecurityManager();
|
||||
nsIScriptSecurityManager *ssm = GetSecurityManager();
|
||||
if (!ssm) {
|
||||
return ThrowException(NS_ERROR_NOT_INITIALIZED, cx);
|
||||
}
|
||||
|
||||
PRUint32 action = (flags & JSRESOLVE_ASSIGNING)
|
||||
? XPCWrapper::sSecMgrSetProp
|
||||
: XPCWrapper::sSecMgrGetProp;
|
||||
? sSecMgrSetProp
|
||||
: sSecMgrGetProp;
|
||||
rv = ssm->CheckPropertyAccess(cx, wrappedObj,
|
||||
STOBJ_GET_CLASS(wrappedObj)->name,
|
||||
id, action);
|
||||
@ -885,8 +894,8 @@ XPC_XOW_NewResolve(JSContext *cx, JSObject *obj, jsval id, uintN flags,
|
||||
}
|
||||
|
||||
// We're out! We're allowed to resolve this property.
|
||||
return XPCWrapper::ResolveNativeProperty(cx, obj, wrappedObj, wn, id,
|
||||
flags, objp, JS_FALSE);
|
||||
return ResolveNativeProperty(cx, obj, wrappedObj, wn, id,
|
||||
flags, objp, JS_FALSE);
|
||||
|
||||
}
|
||||
|
||||
@ -896,8 +905,8 @@ XPC_XOW_NewResolve(JSContext *cx, JSObject *obj, jsval id, uintN flags,
|
||||
|
||||
if (id == GetRTStringByIndex(cx, XPCJSRuntime::IDX_TO_STRING)) {
|
||||
jsval oldSlotVal;
|
||||
if (!JS_GetReservedSlot(cx, obj, XPCWrapper::sFlagsSlot, &oldSlotVal) ||
|
||||
!JS_SetReservedSlot(cx, obj, XPCWrapper::sFlagsSlot,
|
||||
if (!JS_GetReservedSlot(cx, obj, sFlagsSlot, &oldSlotVal) ||
|
||||
!JS_SetReservedSlot(cx, obj, sFlagsSlot,
|
||||
INT_TO_JSVAL(JSVAL_TO_INT(oldSlotVal) |
|
||||
FLAG_RESOLVING))) {
|
||||
return JS_FALSE;
|
||||
@ -906,7 +915,7 @@ XPC_XOW_NewResolve(JSContext *cx, JSObject *obj, jsval id, uintN flags,
|
||||
JSBool ok = JS_DefineFunction(cx, obj, "toString",
|
||||
XPC_XOW_toString, 0, 0) != nsnull;
|
||||
|
||||
JS_SetReservedSlot(cx, obj, XPCWrapper::sFlagsSlot, oldSlotVal);
|
||||
JS_SetReservedSlot(cx, obj, sFlagsSlot, oldSlotVal);
|
||||
|
||||
if (ok) {
|
||||
*objp = obj;
|
||||
@ -915,7 +924,7 @@ XPC_XOW_NewResolve(JSContext *cx, JSObject *obj, jsval id, uintN flags,
|
||||
return ok;
|
||||
}
|
||||
|
||||
return XPCWrapper::NewResolve(cx, obj, JS_TRUE, wrappedObj, id, flags, objp);
|
||||
return NewResolve(cx, obj, JS_TRUE, wrappedObj, id, flags, objp);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
@ -962,7 +971,7 @@ XPC_XOW_Convert(JSContext *cx, JSObject *obj, JSType type, jsval *vp)
|
||||
|
||||
return NS_SUCCEEDED(rv)
|
||||
? WrapSameOriginProp(cx, obj, vp)
|
||||
: XPC_XOW_RewrapIfNeeded(cx, obj, vp);
|
||||
: RewrapIfNeeded(cx, obj, vp);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -1037,7 +1046,7 @@ XPC_XOW_Call(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
return XPC_XOW_RewrapIfNeeded(cx, callee, rval);
|
||||
return RewrapIfNeeded(cx, callee, rval);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
@ -1070,7 +1079,7 @@ XPC_XOW_Construct(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
return XPC_XOW_RewrapIfNeeded(cx, wrappedObj, rval);
|
||||
return RewrapIfNeeded(cx, wrappedObj, rval);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
@ -1123,8 +1132,8 @@ XPC_XOW_Equality(JSContext *cx, JSObject *obj, jsval v, JSBool *bp)
|
||||
}
|
||||
|
||||
JSObject *test = JSVAL_TO_OBJECT(v);
|
||||
if (STOBJ_GET_CLASS(test) == &sXPC_XOW_JSClass.base) {
|
||||
if (!JS_GetReservedSlot(cx, test, XPCWrapper::sWrappedObjSlot, &v)) {
|
||||
if (STOBJ_GET_CLASS(test) == &XOWClass.base) {
|
||||
if (!JS_GetReservedSlot(cx, test, sWrappedObjSlot, &v)) {
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
@ -1181,7 +1190,7 @@ XPC_XOW_Iterator(JSContext *cx, JSObject *obj, JSBool keysonly)
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
JSObject *wrapperIter = JS_NewObject(cx, &sXPC_XOW_JSClass.base, nsnull,
|
||||
JSObject *wrapperIter = JS_NewObject(cx, &XOWClass.base, nsnull,
|
||||
JS_GetGlobalForObject(cx, obj));
|
||||
if (!wrapperIter) {
|
||||
return nsnull;
|
||||
@ -1191,16 +1200,14 @@ XPC_XOW_Iterator(JSContext *cx, JSObject *obj, JSBool keysonly)
|
||||
|
||||
// Initialize our XOW.
|
||||
jsval v = OBJECT_TO_JSVAL(wrappedObj);
|
||||
if (!JS_SetReservedSlot(cx, wrapperIter, XPCWrapper::sWrappedObjSlot, v) ||
|
||||
!JS_SetReservedSlot(cx, wrapperIter, XPCWrapper::sFlagsSlot,
|
||||
JSVAL_ZERO) ||
|
||||
if (!JS_SetReservedSlot(cx, wrapperIter, sWrappedObjSlot, v) ||
|
||||
!JS_SetReservedSlot(cx, wrapperIter, sFlagsSlot, JSVAL_ZERO) ||
|
||||
!JS_SetReservedSlot(cx, wrapperIter, XPC_XOW_ScopeSlot,
|
||||
PRIVATE_TO_JSVAL(nsnull))) {
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
return XPCWrapper::CreateIteratorObj(cx, wrapperIter, obj, wrappedObj,
|
||||
keysonly);
|
||||
return CreateIteratorObj(cx, wrapperIter, obj, wrappedObj, keysonly);
|
||||
}
|
||||
|
||||
static JSObject *
|
||||
@ -1238,7 +1245,7 @@ XPC_XOW_toString(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
||||
|
||||
nsresult rv = CanAccessWrapper(cx, wrappedObj, nsnull);
|
||||
if (rv == NS_ERROR_DOM_PROP_ACCESS_DENIED) {
|
||||
nsIScriptSecurityManager *ssm = XPCWrapper::GetSecurityManager();
|
||||
nsIScriptSecurityManager *ssm = GetSecurityManager();
|
||||
if (!ssm) {
|
||||
return ThrowException(NS_ERROR_NOT_INITIALIZED, cx);
|
||||
}
|
||||
@ -1253,5 +1260,5 @@ XPC_XOW_toString(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
||||
|
||||
XPCWrappedNative *wn =
|
||||
XPCWrappedNative::GetWrappedNativeOfJSObject(cx, wrappedObj);
|
||||
return XPCWrapper::NativeToString(cx, wn, argc, argv, rval, JS_FALSE);
|
||||
return NativeToString(cx, wn, argc, argv, rval, JS_FALSE);
|
||||
}
|
||||
|
@ -96,10 +96,23 @@ static JSBool
|
||||
XPC_NW_FunctionWrapper(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
||||
jsval *rval);
|
||||
|
||||
using namespace XPCWrapper;
|
||||
|
||||
// Whether this XPCNativeWrapper should be a deep wrapper.
|
||||
static const PRUint32 FLAG_DEEP = XPCWrapper::LAST_FLAG << 1;
|
||||
|
||||
// If this flag is set, then this XPCNativeWrapper is *not* the implicit
|
||||
// wrapper stored in XPCWrappedNative::mWrapperWord. These wrappers may
|
||||
// be exposed to content script and because they are not shared, they do
|
||||
// not have expando properties set on implicit native wrappers.
|
||||
static const PRUint32 FLAG_EXPLICIT = XPCWrapper::LAST_FLAG << 2;
|
||||
|
||||
namespace XPCNativeWrapper { namespace internal {
|
||||
|
||||
// JS class for XPCNativeWrapper (and this doubles as the constructor
|
||||
// for XPCNativeWrapper for the moment too...)
|
||||
|
||||
JSExtendedClass XPCNativeWrapper::sXPC_NW_JSClass = {
|
||||
JSExtendedClass NWClass = {
|
||||
// JSClass (JSExtendedClass.base) initialization
|
||||
{ "XPCNativeWrapper",
|
||||
JSCLASS_HAS_PRIVATE | JSCLASS_PRIVATE_IS_NSISUPPORTS |
|
||||
@ -125,6 +138,163 @@ JSExtendedClass XPCNativeWrapper::sXPC_NW_JSClass = {
|
||||
JSCLASS_NO_RESERVED_MEMBERS
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
|
||||
JSBool
|
||||
GetWrappedNative(JSContext *cx, JSObject *obj,
|
||||
XPCWrappedNative **aWrappedNative)
|
||||
{
|
||||
XPCWrappedNative *wn = static_cast<XPCWrappedNative *>(xpc_GetJSPrivate(obj));
|
||||
*aWrappedNative = wn;
|
||||
if (!wn) {
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
nsIScriptSecurityManager *ssm = GetSecurityManager();
|
||||
if (!ssm) {
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
nsIPrincipal *subjectPrincipal = ssm->GetCxSubjectPrincipal(cx);
|
||||
if (!subjectPrincipal) {
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
XPCWrappedNativeScope *scope = wn->GetScope();
|
||||
nsIPrincipal *objectPrincipal = scope->GetPrincipal();
|
||||
|
||||
PRBool subsumes;
|
||||
nsresult rv = subjectPrincipal->Subsumes(objectPrincipal, &subsumes);
|
||||
if (NS_FAILED(rv) || !subsumes) {
|
||||
PRBool isPrivileged;
|
||||
rv = ssm->IsCapabilityEnabled("UniversalXPConnect", &isPrivileged);
|
||||
return NS_SUCCEEDED(rv) && isPrivileged;
|
||||
}
|
||||
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JSBool
|
||||
WrapFunction(JSContext* cx, JSObject* funobj, jsval *rval)
|
||||
{
|
||||
// If funobj is already a wrapped function, just return it.
|
||||
if (JS_GetFunctionNative(cx,
|
||||
JS_ValueToFunction(cx, OBJECT_TO_JSVAL(funobj))) ==
|
||||
XPC_NW_FunctionWrapper) {
|
||||
*rval = OBJECT_TO_JSVAL(funobj);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
// Ensure that we've been called from JS. Native code should extract
|
||||
// the wrapped native and deal with that directly.
|
||||
// XXX Can we simply trust |cx| here?
|
||||
JSStackFrame *iterator = nsnull;
|
||||
if (!::JS_FrameIterator(cx, &iterator)) {
|
||||
::JS_ReportError(cx, "XPCNativeWrappers must be used from script");
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
// Create a new function that'll call our given function. This new
|
||||
// function's parent will be the original function and that's how we
|
||||
// get the right thing to call when this function is called.
|
||||
// Note that we pass nsnull as the nominal parent so that we'll inherit
|
||||
// our caller's Function.prototype.
|
||||
JSFunction *funWrapper =
|
||||
::JS_NewFunction(cx, XPC_NW_FunctionWrapper, 0, 0, nsnull,
|
||||
"XPCNativeWrapper function wrapper");
|
||||
if (!funWrapper) {
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
JSObject* funWrapperObj = ::JS_GetFunctionObject(funWrapper);
|
||||
::JS_SetParent(cx, funWrapperObj, funobj);
|
||||
*rval = OBJECT_TO_JSVAL(funWrapperObj);
|
||||
|
||||
JS_SetReservedSlot(cx, funWrapperObj, eAllAccessSlot, JSVAL_FALSE);
|
||||
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JSBool
|
||||
RewrapIfDeepWrapper(JSContext *cx, JSObject *obj, jsval v, jsval *rval)
|
||||
{
|
||||
NS_ASSERTION(XPCNativeWrapper::IsNativeWrapper(obj),
|
||||
"Unexpected object");
|
||||
|
||||
JSBool primitive = JSVAL_IS_PRIMITIVE(v);
|
||||
JSObject* nativeObj = primitive ? nsnull : JSVAL_TO_OBJECT(v);
|
||||
|
||||
// We always want to wrap function objects, no matter whether we're deep.
|
||||
if (!primitive && JS_ObjectIsFunction(cx, nativeObj)) {
|
||||
return WrapFunction(cx, nativeObj, rval);
|
||||
}
|
||||
|
||||
jsval flags;
|
||||
::JS_GetReservedSlot(cx, obj, 0, &flags);
|
||||
|
||||
// Re-wrap non-primitive values if this is a deep wrapper, i.e.
|
||||
// if (HAS_FLAGS(flags, FLAG_DEEP).
|
||||
if (HAS_FLAGS(flags, FLAG_DEEP) && !primitive) {
|
||||
// Unwrap a cross origin wrapper, since we're more restrictive.
|
||||
if (STOBJ_GET_CLASS(nativeObj) == &XPCCrossOriginWrapper::XOWClass.base) {
|
||||
if (!::JS_GetReservedSlot(cx, nativeObj, sWrappedObjSlot,
|
||||
&v)) {
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
// If v is primitive, allow nativeObj to remain a cross origin wrapper,
|
||||
// which will fail below (since it isn't a wrapped native).
|
||||
if (!JSVAL_IS_PRIMITIVE(v)) {
|
||||
nativeObj = JSVAL_TO_OBJECT(v);
|
||||
}
|
||||
}
|
||||
|
||||
XPCWrappedNative* wrappedNative =
|
||||
XPCWrappedNative::GetAndMorphWrappedNativeOfJSObject(cx, nativeObj);
|
||||
if (!wrappedNative)
|
||||
return XPCSafeJSObjectWrapper::WrapObject(cx, nsnull, v, rval);
|
||||
|
||||
if (HAS_FLAGS(flags, FLAG_EXPLICIT)) {
|
||||
#ifdef DEBUG_XPCNativeWrapper
|
||||
printf("Rewrapping for deep explicit wrapper\n");
|
||||
#endif
|
||||
if (wrappedNative == XPCNativeWrapper::SafeGetWrappedNative(obj)) {
|
||||
// Already wrapped, return the wrapper.
|
||||
*rval = OBJECT_TO_JSVAL(obj);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
// |obj| is an explicit deep wrapper. We want to construct another
|
||||
// explicit deep wrapper for |v|.
|
||||
|
||||
return XPCNativeWrapper::CreateExplicitWrapper(cx, wrappedNative,
|
||||
JS_TRUE, rval);
|
||||
}
|
||||
|
||||
#ifdef DEBUG_XPCNativeWrapper
|
||||
printf("Rewrapping for deep implicit wrapper\n");
|
||||
#endif
|
||||
// Just using GetNewOrUsed on the return value of
|
||||
// GetWrappedNativeOfJSObject will give the right thing -- the unique deep
|
||||
// implicit wrapper associated with wrappedNative.
|
||||
JSObject* wrapperObj = XPCNativeWrapper::GetNewOrUsed(cx, wrappedNative,
|
||||
nsnull);
|
||||
if (!wrapperObj) {
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
*rval = OBJECT_TO_JSVAL(wrapperObj);
|
||||
} else {
|
||||
*rval = v;
|
||||
}
|
||||
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
} // namespace XPCNativeWrapper
|
||||
|
||||
using namespace XPCNativeWrapper;
|
||||
|
||||
// If one of our class hooks is ever called from a non-system script, bypass
|
||||
// the hook by calling the same hook on our wrapped native, with obj reset to
|
||||
// the wrapped native's flat JSObject, so the hook and args macro parameters
|
||||
@ -204,7 +374,7 @@ JSBool
|
||||
EnsureLegalActivity(JSContext *cx, JSObject *obj,
|
||||
jsval id = JSVAL_VOID, PRUint32 accessType = 0)
|
||||
{
|
||||
nsIScriptSecurityManager *ssm = XPCWrapper::GetSecurityManager();
|
||||
nsIScriptSecurityManager *ssm = GetSecurityManager();
|
||||
if (!ssm) {
|
||||
// If there's no security manager, then we're not running in a browser
|
||||
// context: allow access.
|
||||
@ -243,8 +413,7 @@ EnsureLegalActivity(JSContext *cx, JSObject *obj,
|
||||
|
||||
JSObject* flatObj;
|
||||
if (!JSVAL_IS_VOID(id) &&
|
||||
(accessType & (XPCWrapper::sSecMgrSetProp |
|
||||
XPCWrapper::sSecMgrGetProp)) &&
|
||||
(accessType & (sSecMgrSetProp | sSecMgrGetProp)) &&
|
||||
(flatObj = wn->GetFlatJSObject())) {
|
||||
rv = ssm->CheckPropertyAccess(cx, flatObj,
|
||||
STOBJ_GET_CLASS(flatObj)->name,
|
||||
@ -285,82 +454,6 @@ EnsureLegalActivity(JSContext *cx, JSObject *obj,
|
||||
return ThrowException(NS_ERROR_XPC_SECURITY_MANAGER_VETO, cx);
|
||||
}
|
||||
|
||||
// static
|
||||
JSBool
|
||||
XPCNativeWrapper::GetWrappedNative(JSContext *cx, JSObject *obj,
|
||||
XPCWrappedNative **aWrappedNative)
|
||||
{
|
||||
XPCWrappedNative *wn = static_cast<XPCWrappedNative *>(xpc_GetJSPrivate(obj));
|
||||
*aWrappedNative = wn;
|
||||
if (!wn) {
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
nsIScriptSecurityManager *ssm = XPCWrapper::GetSecurityManager();
|
||||
if (!ssm) {
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
nsIPrincipal *subjectPrincipal = ssm->GetCxSubjectPrincipal(cx);
|
||||
if (!subjectPrincipal) {
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
XPCWrappedNativeScope *scope = wn->GetScope();
|
||||
nsIPrincipal *objectPrincipal = scope->GetPrincipal();
|
||||
|
||||
PRBool subsumes;
|
||||
nsresult rv = subjectPrincipal->Subsumes(objectPrincipal, &subsumes);
|
||||
if (NS_FAILED(rv) || !subsumes) {
|
||||
PRBool isPrivileged;
|
||||
rv = ssm->IsCapabilityEnabled("UniversalXPConnect", &isPrivileged);
|
||||
return NS_SUCCEEDED(rv) && isPrivileged;
|
||||
}
|
||||
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JSBool
|
||||
XPC_NW_WrapFunction(JSContext* cx, JSObject* funobj, jsval *rval)
|
||||
{
|
||||
// If funobj is already a wrapped function, just return it.
|
||||
if (JS_GetFunctionNative(cx,
|
||||
JS_ValueToFunction(cx, OBJECT_TO_JSVAL(funobj))) ==
|
||||
XPC_NW_FunctionWrapper) {
|
||||
*rval = OBJECT_TO_JSVAL(funobj);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
// Ensure that we've been called from JS. Native code should extract
|
||||
// the wrapped native and deal with that directly.
|
||||
// XXX Can we simply trust |cx| here?
|
||||
JSStackFrame *iterator = nsnull;
|
||||
if (!::JS_FrameIterator(cx, &iterator)) {
|
||||
::JS_ReportError(cx, "XPCNativeWrappers must be used from script");
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
// Create a new function that'll call our given function. This new
|
||||
// function's parent will be the original function and that's how we
|
||||
// get the right thing to call when this function is called.
|
||||
// Note that we pass nsnull as the nominal parent so that we'll inherit
|
||||
// our caller's Function.prototype.
|
||||
JSFunction *funWrapper =
|
||||
::JS_NewFunction(cx, XPC_NW_FunctionWrapper, 0, 0, nsnull,
|
||||
"XPCNativeWrapper function wrapper");
|
||||
if (!funWrapper) {
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
JSObject* funWrapperObj = ::JS_GetFunctionObject(funWrapper);
|
||||
::JS_SetParent(cx, funWrapperObj, funobj);
|
||||
*rval = OBJECT_TO_JSVAL(funWrapperObj);
|
||||
|
||||
JS_SetReservedSlot(cx, funWrapperObj, XPCWrapper::eAllAccessSlot, JSVAL_FALSE);
|
||||
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
XPC_NW_AddProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
|
||||
{
|
||||
@ -390,8 +483,8 @@ XPC_NW_AddProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
|
||||
|
||||
// Note: no need to protect *vp from GC here, since it's already in the slot
|
||||
// on |obj|.
|
||||
return EnsureLegalActivity(cx, obj, id, XPCWrapper::sSecMgrSetProp) &&
|
||||
XPC_NW_RewrapIfDeepWrapper(cx, obj, *vp, vp);
|
||||
return EnsureLegalActivity(cx, obj, id, sSecMgrSetProp) &&
|
||||
RewrapIfDeepWrapper(cx, obj, *vp, vp);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
@ -419,82 +512,6 @@ XPC_NW_DelProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JSBool
|
||||
XPC_NW_RewrapIfDeepWrapper(JSContext *cx, JSObject *obj, jsval v, jsval *rval)
|
||||
{
|
||||
NS_ASSERTION(XPCNativeWrapper::IsNativeWrapper(obj),
|
||||
"Unexpected object");
|
||||
|
||||
JSBool primitive = JSVAL_IS_PRIMITIVE(v);
|
||||
JSObject* nativeObj = primitive ? nsnull : JSVAL_TO_OBJECT(v);
|
||||
|
||||
// We always want to wrap function objects, no matter whether we're deep.
|
||||
if (!primitive && JS_ObjectIsFunction(cx, nativeObj)) {
|
||||
return XPC_NW_WrapFunction(cx, nativeObj, rval);
|
||||
}
|
||||
|
||||
jsval flags;
|
||||
::JS_GetReservedSlot(cx, obj, 0, &flags);
|
||||
|
||||
// Re-wrap non-primitive values if this is a deep wrapper, i.e.
|
||||
// if (HAS_FLAGS(flags, FLAG_DEEP).
|
||||
if (HAS_FLAGS(flags, FLAG_DEEP) && !primitive) {
|
||||
// Unwrap a cross origin wrapper, since we're more restrictive.
|
||||
if (STOBJ_GET_CLASS(nativeObj) == &sXPC_XOW_JSClass.base) {
|
||||
if (!::JS_GetReservedSlot(cx, nativeObj, XPCWrapper::sWrappedObjSlot,
|
||||
&v)) {
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
// If v is primitive, allow nativeObj to remain a cross origin wrapper,
|
||||
// which will fail below (since it isn't a wrapped native).
|
||||
if (!JSVAL_IS_PRIMITIVE(v)) {
|
||||
nativeObj = JSVAL_TO_OBJECT(v);
|
||||
}
|
||||
}
|
||||
|
||||
XPCWrappedNative* wrappedNative =
|
||||
XPCWrappedNative::GetAndMorphWrappedNativeOfJSObject(cx, nativeObj);
|
||||
if (!wrappedNative)
|
||||
return XPC_SJOW_Construct(cx, nsnull, 1, &v, rval);
|
||||
|
||||
if (HAS_FLAGS(flags, FLAG_EXPLICIT)) {
|
||||
#ifdef DEBUG_XPCNativeWrapper
|
||||
printf("Rewrapping for deep explicit wrapper\n");
|
||||
#endif
|
||||
if (wrappedNative == XPCNativeWrapper::SafeGetWrappedNative(obj)) {
|
||||
// Already wrapped, return the wrapper.
|
||||
*rval = OBJECT_TO_JSVAL(obj);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
// |obj| is an explicit deep wrapper. We want to construct another
|
||||
// explicit deep wrapper for |v|.
|
||||
|
||||
return XPCNativeWrapper::CreateExplicitWrapper(cx, wrappedNative,
|
||||
JS_TRUE, rval);
|
||||
}
|
||||
|
||||
#ifdef DEBUG_XPCNativeWrapper
|
||||
printf("Rewrapping for deep implicit wrapper\n");
|
||||
#endif
|
||||
// Just using GetNewOrUsed on the return value of
|
||||
// GetWrappedNativeOfJSObject will give the right thing -- the unique deep
|
||||
// implicit wrapper associated with wrappedNative.
|
||||
JSObject* wrapperObj = XPCNativeWrapper::GetNewOrUsed(cx, wrappedNative,
|
||||
nsnull);
|
||||
if (!wrapperObj) {
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
*rval = OBJECT_TO_JSVAL(wrapperObj);
|
||||
} else {
|
||||
*rval = v;
|
||||
}
|
||||
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
XPC_NW_FunctionWrapper(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
||||
jsval *rval)
|
||||
@ -518,9 +535,7 @@ XPC_NW_FunctionWrapper(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
||||
XPCWrappedNative* wrappedNative = nsnull;
|
||||
|
||||
jsval isAllAccess;
|
||||
if (::JS_GetReservedSlot(cx, funObj,
|
||||
XPCWrapper::eAllAccessSlot,
|
||||
&isAllAccess) &&
|
||||
if (::JS_GetReservedSlot(cx, funObj, eAllAccessSlot, &isAllAccess) &&
|
||||
JSVAL_TO_BOOLEAN(isAllAccess)) {
|
||||
wrappedNative = XPCNativeWrapper::SafeGetWrappedNative(obj);
|
||||
} else if (!XPCNativeWrapper::GetWrappedNative(cx, obj, &wrappedNative)) {
|
||||
@ -543,7 +558,7 @@ XPC_NW_FunctionWrapper(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
||||
// Make sure v doesn't get collected while we're re-wrapping it.
|
||||
AUTO_MARK_JSVAL(ccx, v);
|
||||
|
||||
return XPC_NW_RewrapIfDeepWrapper(cx, obj, v, rval);
|
||||
return RewrapIfDeepWrapper(cx, obj, v, rval);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
@ -564,8 +579,7 @@ XPC_NW_GetOrSetProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp,
|
||||
}
|
||||
|
||||
if (!EnsureLegalActivity(cx, obj, id,
|
||||
aIsSet ? XPCWrapper::sSecMgrSetProp
|
||||
: XPCWrapper::sSecMgrGetProp)) {
|
||||
aIsSet ? sSecMgrSetProp : sSecMgrGetProp)) {
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
@ -603,7 +617,7 @@ XPC_NW_GetOrSetProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp,
|
||||
|
||||
jsval nativeVal = OBJECT_TO_JSVAL(nativeObj);
|
||||
|
||||
nsIScriptSecurityManager *ssm = XPCWrapper::GetSecurityManager();
|
||||
nsIScriptSecurityManager *ssm = GetSecurityManager();
|
||||
nsCOMPtr<nsIPrincipal> prin;
|
||||
nsresult rv = ssm->GetObjectPrincipal(cx, nativeObj,
|
||||
getter_AddRefs(prin));
|
||||
@ -617,11 +631,11 @@ XPC_NW_GetOrSetProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp,
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
return XPC_SJOW_Construct(cx, nsnull, 1, &nativeVal, vp);
|
||||
return XPCSafeJSObjectWrapper::WrapObject(cx, nsnull, nativeVal, vp);
|
||||
}
|
||||
|
||||
return XPCWrapper::GetOrSetNativeProperty(cx, obj, wrappedNative, id, vp,
|
||||
aIsSet, JS_TRUE);
|
||||
return GetOrSetNativeProperty(cx, obj, wrappedNative, id, vp, aIsSet,
|
||||
JS_TRUE);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
@ -655,7 +669,7 @@ XPC_NW_Enumerate(JSContext *cx, JSObject *obj)
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
return XPCWrapper::Enumerate(cx, obj, wn->GetFlatJSObject());
|
||||
return Enumerate(cx, obj, wn->GetFlatJSObject());
|
||||
}
|
||||
|
||||
static JSBool
|
||||
@ -673,7 +687,7 @@ XPC_NW_NewResolve(JSContext *cx, JSObject *obj, jsval id, uintN flags,
|
||||
if (id == GetRTStringByIndex(cx, XPCJSRuntime::IDX_TO_STRING)) {
|
||||
*objp = obj;
|
||||
|
||||
// See the comment in XPC_NW_WrapFunction for why we create this function
|
||||
// See the comment in WrapFunction for why we create this function
|
||||
// like this.
|
||||
JSFunction *fun = JS_NewFunction(cx, XPC_NW_toString, 0, 0, nsnull,
|
||||
"toString");
|
||||
@ -689,8 +703,7 @@ XPC_NW_NewResolve(JSContext *cx, JSObject *obj, jsval id, uintN flags,
|
||||
}
|
||||
|
||||
PRUint32 accessType =
|
||||
(flags & JSRESOLVE_ASSIGNING) ? XPCWrapper::sSecMgrSetProp
|
||||
: XPCWrapper::sSecMgrGetProp;
|
||||
(flags & JSRESOLVE_ASSIGNING) ? sSecMgrSetProp : sSecMgrGetProp;
|
||||
if (!EnsureLegalActivity(cx, obj, id, accessType)) {
|
||||
return JS_FALSE;
|
||||
}
|
||||
@ -746,10 +759,8 @@ XPC_NW_NewResolve(JSContext *cx, JSObject *obj, jsval id, uintN flags,
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
return XPCWrapper::ResolveNativeProperty(cx, obj,
|
||||
wrappedNative->GetFlatJSObject(),
|
||||
wrappedNative, id, flags, objp,
|
||||
JS_TRUE);
|
||||
return ResolveNativeProperty(cx, obj, wrappedNative->GetFlatJSObject(),
|
||||
wrappedNative, id, flags, objp, JS_TRUE);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
@ -870,7 +881,7 @@ XPC_NW_Construct(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
||||
return ThrowException(NS_ERROR_ILLEGAL_VALUE, cx);
|
||||
}
|
||||
|
||||
return XPC_NW_RewrapIfDeepWrapper(cx, obj, *rval, rval);
|
||||
return RewrapIfDeepWrapper(cx, obj, *rval, rval);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
@ -947,22 +958,11 @@ XPCNativeWrapperCtor(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
||||
JSObject *nativeObj = JSVAL_TO_OBJECT(native);
|
||||
|
||||
// Unwrap a cross origin wrapper, since we're more restrictive than it is.
|
||||
if (STOBJ_GET_CLASS(nativeObj) == &sXPC_XOW_JSClass.base) {
|
||||
jsval v;
|
||||
if (!::JS_GetReservedSlot(cx, nativeObj, XPCWrapper::sWrappedObjSlot, &v)) {
|
||||
return JS_FALSE;
|
||||
}
|
||||
// If v is primitive, allow nativeObj to remain a cross origin wrapper,
|
||||
// which will fail below (since it isn't a wrapped native).
|
||||
if (!JSVAL_IS_PRIMITIVE(v)) {
|
||||
nativeObj = JSVAL_TO_OBJECT(v);
|
||||
}
|
||||
} else if (STOBJ_GET_CLASS(nativeObj) == &sXPC_SJOW_JSClass.base) {
|
||||
// Also unwrap SJOWs.
|
||||
nativeObj = JS_GetParent(cx, nativeObj);
|
||||
if (!nativeObj) {
|
||||
return ThrowException(NS_ERROR_XPC_BAD_CONVERT_JS, cx);
|
||||
}
|
||||
JSObject *wrapper;
|
||||
if ((wrapper = UnwrapGeneric(cx, &XPCCrossOriginWrapper::XOWClass, nativeObj))) {
|
||||
nativeObj = wrapper;
|
||||
} else if ((wrapper = UnwrapGeneric(cx, &XPCSafeJSObjectWrapper::SJOWClass, nativeObj))) {
|
||||
nativeObj = wrapper;
|
||||
}
|
||||
|
||||
XPCWrappedNative *wrappedNative;
|
||||
@ -1119,8 +1119,8 @@ XPC_NW_Iterator(JSContext *cx, JSObject *obj, JSBool keysonly)
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
return XPCWrapper::CreateIteratorObj(cx, wrapperIter, obj,
|
||||
wn->GetFlatJSObject(), keysonly);
|
||||
return CreateIteratorObj(cx, wrapperIter, obj, wn->GetFlatJSObject(),
|
||||
keysonly);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
@ -1136,7 +1136,7 @@ XPC_NW_toString(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
||||
|
||||
if (!EnsureLegalActivity(cx, obj,
|
||||
GetRTStringByIndex(cx, XPCJSRuntime::IDX_TO_STRING),
|
||||
XPCWrapper::sSecMgrGetProp)) {
|
||||
sSecMgrGetProp)) {
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
@ -1155,8 +1155,7 @@ XPC_NW_toString(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
return XPCWrapper::NativeToString(cx, wrappedNative, argc, argv, rval,
|
||||
JS_TRUE);
|
||||
return NativeToString(cx, wrappedNative, argc, argv, rval, JS_TRUE);
|
||||
}
|
||||
|
||||
// static
|
||||
@ -1165,7 +1164,7 @@ XPCNativeWrapper::AttachNewConstructorObject(XPCCallContext &ccx,
|
||||
JSObject *aGlobalObject)
|
||||
{
|
||||
JSObject *class_obj =
|
||||
::JS_InitClass(ccx, aGlobalObject, nsnull, &sXPC_NW_JSClass.base,
|
||||
::JS_InitClass(ccx, aGlobalObject, nsnull, &internal::NWClass.base,
|
||||
XPCNativeWrapperCtor, 0, nsnull, nsnull,
|
||||
nsnull, nsnull);
|
||||
if (!class_obj) {
|
||||
@ -1183,7 +1182,7 @@ XPCNativeWrapper::AttachNewConstructorObject(XPCCallContext &ccx,
|
||||
|
||||
JSBool found;
|
||||
return ::JS_SetPropertyAttributes(ccx, aGlobalObject,
|
||||
sXPC_NW_JSClass.base.name,
|
||||
internal::NWClass.base.name,
|
||||
JSPROP_READONLY | JSPROP_PERMANENT,
|
||||
&found);
|
||||
}
|
||||
@ -1194,7 +1193,7 @@ XPCNativeWrapper::GetNewOrUsed(JSContext *cx, XPCWrappedNative *wrapper,
|
||||
nsIPrincipal *aObjectPrincipal)
|
||||
{
|
||||
if (aObjectPrincipal) {
|
||||
nsIScriptSecurityManager *ssm = XPCWrapper::GetSecurityManager();
|
||||
nsIScriptSecurityManager *ssm = GetSecurityManager();
|
||||
|
||||
PRBool isSystem;
|
||||
nsresult rv = ssm->IsSystemPrincipal(aObjectPrincipal, &isSystem);
|
||||
@ -1220,7 +1219,7 @@ XPCNativeWrapper::GetNewOrUsed(JSContext *cx, XPCWrappedNative *wrapper,
|
||||
// Make sure v doesn't get collected while we're re-wrapping it.
|
||||
AUTO_MARK_JSVAL(ccx, v);
|
||||
|
||||
if (XPC_SJOW_Construct(cx, nsnull, 1, &v, &v))
|
||||
if (XPCSafeJSObjectWrapper::WrapObject(cx, nsnull, v, &v))
|
||||
return JSVAL_TO_OBJECT(v);
|
||||
|
||||
return nsnull;
|
||||
|
@ -42,49 +42,50 @@
|
||||
|
||||
class nsIPrincipal;
|
||||
|
||||
class XPCNativeWrapper
|
||||
namespace XPCNativeWrapper {
|
||||
|
||||
namespace internal { extern JSExtendedClass NWClass; }
|
||||
|
||||
PRBool
|
||||
AttachNewConstructorObject(XPCCallContext &ccx, JSObject *aGlobalObject);
|
||||
|
||||
JSObject *
|
||||
GetNewOrUsed(JSContext *cx, XPCWrappedNative *wrapper,
|
||||
nsIPrincipal *aObjectPrincipal);
|
||||
JSBool
|
||||
CreateExplicitWrapper(JSContext *cx, XPCWrappedNative *wrapper, JSBool deep,
|
||||
jsval *rval);
|
||||
|
||||
inline PRBool
|
||||
IsNativeWrapperClass(JSClass *clazz)
|
||||
{
|
||||
public:
|
||||
static PRBool AttachNewConstructorObject(XPCCallContext &ccx,
|
||||
JSObject *aGlobalObject);
|
||||
return clazz == &internal::NWClass.base;
|
||||
}
|
||||
|
||||
static JSObject *GetNewOrUsed(JSContext *cx, XPCWrappedNative *wrapper,
|
||||
nsIPrincipal *aObjectPrincipal);
|
||||
static JSBool CreateExplicitWrapper(JSContext *cx, XPCWrappedNative *wrapper,
|
||||
JSBool deep, jsval *rval);
|
||||
|
||||
static PRBool IsNativeWrapperClass(JSClass *clazz)
|
||||
{
|
||||
return clazz == &sXPC_NW_JSClass.base;
|
||||
}
|
||||
|
||||
static PRBool IsNativeWrapper(JSObject *obj)
|
||||
{
|
||||
return STOBJ_GET_CLASS(obj) == &sXPC_NW_JSClass.base;
|
||||
}
|
||||
|
||||
static JSBool GetWrappedNative(JSContext *cx, JSObject *obj,
|
||||
XPCWrappedNative **aWrappedNative);
|
||||
|
||||
// NB: Use the following carefully.
|
||||
static XPCWrappedNative *SafeGetWrappedNative(JSObject *obj)
|
||||
{
|
||||
return static_cast<XPCWrappedNative *>(xpc_GetJSPrivate(obj));
|
||||
}
|
||||
|
||||
|
||||
static JSClass *GetJSClass()
|
||||
{
|
||||
return &sXPC_NW_JSClass.base;
|
||||
}
|
||||
|
||||
static void ClearWrappedNativeScopes(JSContext* cx,
|
||||
XPCWrappedNative* wrapper);
|
||||
|
||||
protected:
|
||||
static JSExtendedClass sXPC_NW_JSClass;
|
||||
};
|
||||
inline PRBool
|
||||
IsNativeWrapper(JSObject *obj)
|
||||
{
|
||||
return STOBJ_GET_CLASS(obj) == &internal::NWClass.base;
|
||||
}
|
||||
|
||||
JSBool
|
||||
XPC_XOW_WrapObject(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
||||
jsval *rval);
|
||||
GetWrappedNative(JSContext *cx, JSObject *obj,
|
||||
XPCWrappedNative **aWrappedNative);
|
||||
|
||||
// NB: Use the following carefully.
|
||||
inline XPCWrappedNative *
|
||||
SafeGetWrappedNative(JSObject *obj)
|
||||
{
|
||||
return static_cast<XPCWrappedNative *>(xpc_GetJSPrivate(obj));
|
||||
}
|
||||
|
||||
inline JSClass *
|
||||
GetJSClass()
|
||||
{
|
||||
return &internal::NWClass.base;
|
||||
}
|
||||
|
||||
void
|
||||
ClearWrappedNativeScopes(JSContext* cx, XPCWrappedNative* wrapper);
|
||||
|
||||
}
|
||||
|
@ -77,7 +77,7 @@ static JSBool
|
||||
XPC_SJOW_Call(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
||||
jsval *rval);
|
||||
|
||||
JSBool
|
||||
static JSBool
|
||||
XPC_SJOW_Construct(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
||||
jsval *rval);
|
||||
|
||||
@ -103,6 +103,9 @@ ThrowException(nsresult ex, JSContext *cx)
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
using namespace XPCSafeJSObjectWrapper;
|
||||
using namespace XPCWrapper;
|
||||
|
||||
// Find the subject and object principal. The argument
|
||||
// subjectPrincipal can be null if the caller doesn't care about the
|
||||
// subject principal, and secMgr can also be null if the caller
|
||||
@ -171,15 +174,10 @@ CanCallerAccess(JSContext *cx, JSObject *unsafeObj)
|
||||
|
||||
// Reserved slot indexes on safe wrappers.
|
||||
|
||||
// Boolean value, initialized to false on object creation and true
|
||||
// only while we're resolving a property on the object.
|
||||
#define XPC_SJOW_SLOT_IS_RESOLVING 0
|
||||
|
||||
// Slot for holding on to the principal to use if a principal other
|
||||
// than that of the unsafe object is desired for this wrapper
|
||||
// (nsIPrincipal, strong reference).
|
||||
#define XPC_SJOW_SLOT_PRINCIPAL 1
|
||||
|
||||
static const PRUint32 sPrincipalSlot = sNumSlots;
|
||||
|
||||
// Returns a weak reference.
|
||||
static nsIPrincipal *
|
||||
@ -187,7 +185,7 @@ FindObjectPrincipals(JSContext *cx, JSObject *safeObj, JSObject *innerObj)
|
||||
{
|
||||
// Check if we have a cached principal first.
|
||||
jsval v;
|
||||
if (!JS_GetReservedSlot(cx, safeObj, XPC_SJOW_SLOT_PRINCIPAL, &v)) {
|
||||
if (!JS_GetReservedSlot(cx, safeObj, sPrincipalSlot, &v)) {
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
@ -203,7 +201,7 @@ FindObjectPrincipals(JSContext *cx, JSObject *safeObj, JSObject *innerObj)
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
if (!JS_SetReservedSlot(cx, safeObj, XPC_SJOW_SLOT_PRINCIPAL,
|
||||
if (!JS_SetReservedSlot(cx, safeObj, sPrincipalSlot,
|
||||
PRIVATE_TO_JSVAL(objPrincipal.get()))) {
|
||||
return nsnull;
|
||||
}
|
||||
@ -212,15 +210,34 @@ FindObjectPrincipals(JSContext *cx, JSObject *safeObj, JSObject *innerObj)
|
||||
return objPrincipal.forget().get();
|
||||
}
|
||||
|
||||
static inline JSObject *
|
||||
FindSafeObject(JSObject *obj)
|
||||
{
|
||||
while (STOBJ_GET_CLASS(obj) != &SJOWClass.base) {
|
||||
obj = STOBJ_GET_PROTO(obj);
|
||||
|
||||
if (!obj) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
XPC_SJOW_toString(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
||||
jsval *rval);
|
||||
|
||||
namespace XPCSafeJSObjectWrapper {
|
||||
|
||||
// JS class for XPCSafeJSObjectWrapper (and this doubles as the
|
||||
// constructor for XPCSafeJSObjectWrapper for the moment too...)
|
||||
|
||||
JSExtendedClass sXPC_SJOW_JSClass = {
|
||||
JSExtendedClass SJOWClass = {
|
||||
// JSClass (JSExtendedClass.base) initialization
|
||||
{ "XPCSafeJSObjectWrapper",
|
||||
JSCLASS_NEW_RESOLVE | JSCLASS_IS_EXTENDED |
|
||||
JSCLASS_HAS_RESERVED_SLOTS(XPCWrapper::sNumSlots + 3),
|
||||
JSCLASS_HAS_RESERVED_SLOTS(XPCWrapper::sNumSlots + 1),
|
||||
XPC_SJOW_AddProperty, XPC_SJOW_DelProperty,
|
||||
XPC_SJOW_GetProperty, XPC_SJOW_SetProperty,
|
||||
XPC_SJOW_Enumerate, (JSResolveOp)XPC_SJOW_NewResolve,
|
||||
@ -239,10 +256,69 @@ JSExtendedClass sXPC_SJOW_JSClass = {
|
||||
JSCLASS_NO_RESERVED_MEMBERS
|
||||
};
|
||||
|
||||
static JSBool
|
||||
XPC_SJOW_toString(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
||||
jsval *rval);
|
||||
JSBool
|
||||
WrapObject(JSContext *cx, JSObject *scope, jsval v, jsval *vp)
|
||||
{
|
||||
*vp = v;
|
||||
return XPC_SJOW_Construct(cx, scope, 1, vp, vp);
|
||||
}
|
||||
|
||||
PRBool
|
||||
AttachNewConstructorObject(XPCCallContext &ccx, JSObject *aGlobalObject)
|
||||
{
|
||||
// Initialize sEvalNative the first time we attach a constructor.
|
||||
// NB: This always happens before any cross origin wrappers are
|
||||
// created, so it's OK to do this here.
|
||||
if (!XPCWrapper::FindEval(ccx, aGlobalObject)) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
JSObject *class_obj =
|
||||
::JS_InitClass(ccx, aGlobalObject, nsnull, &SJOWClass.base,
|
||||
XPC_SJOW_Construct, 0, nsnull, nsnull, nsnull, nsnull);
|
||||
if (!class_obj) {
|
||||
NS_WARNING("can't initialize the XPCSafeJSObjectWrapper class");
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
if (!::JS_DefineFunction(ccx, class_obj, "toString", XPC_SJOW_toString,
|
||||
0, 0)) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
// Null out the class object's parent to prevent code in this class
|
||||
// from thinking the class object is a wrapper for the global
|
||||
// object.
|
||||
::JS_SetParent(ccx, class_obj, nsnull);
|
||||
|
||||
// Make sure our prototype chain is empty and that people can't mess
|
||||
// with XPCSafeJSObjectWrapper.prototype.
|
||||
::JS_SetPrototype(ccx, class_obj, nsnull);
|
||||
if (!::JS_SealObject(ccx, class_obj, JS_FALSE)) {
|
||||
NS_WARNING("Failed to seal XPCSafeJSObjectWrapper.prototype");
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
JSBool found;
|
||||
return ::JS_SetPropertyAttributes(ccx, aGlobalObject,
|
||||
SJOWClass.base.name,
|
||||
JSPROP_READONLY | JSPROP_PERMANENT,
|
||||
&found);
|
||||
}
|
||||
|
||||
JSObject *
|
||||
GetUnsafeObject(JSObject *obj)
|
||||
{
|
||||
obj = FindSafeObject(obj);
|
||||
|
||||
if (!obj) {
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
return STOBJ_GET_PARENT(obj);
|
||||
}
|
||||
|
||||
} // namespace XPCSafeJSObjectWrapper
|
||||
|
||||
// Wrap a JS value in a safe wrapper of a function wrapper if
|
||||
// needed. Note that rval must point to something rooted when calling
|
||||
@ -259,7 +335,7 @@ WrapJSValue(JSContext *cx, JSObject *obj, jsval val, jsval *rval)
|
||||
// parent we pass in here, the construct hook will ensure we get
|
||||
// the right parent for the wrapper.
|
||||
JSObject *safeObj =
|
||||
::JS_ConstructObjectWithArguments(cx, &sXPC_SJOW_JSClass.base, nsnull,
|
||||
::JS_ConstructObjectWithArguments(cx, &SJOWClass.base, nsnull,
|
||||
nsnull, 1, &val);
|
||||
if (!safeObj) {
|
||||
return JS_FALSE;
|
||||
@ -315,7 +391,7 @@ WrapJSValue(JSContext *cx, JSObject *obj, jsval val, jsval *rval)
|
||||
// the principal of the unsafe object to prevent users of the
|
||||
// new object wrapper from evaluating code through the new
|
||||
// wrapper with the principal of the new object.
|
||||
if (!::JS_SetReservedSlot(cx, safeObj, XPC_SJOW_SLOT_PRINCIPAL,
|
||||
if (!::JS_SetReservedSlot(cx, safeObj, sPrincipalSlot,
|
||||
PRIVATE_TO_JSVAL(srcObjPrincipal.get()))) {
|
||||
return JS_FALSE;
|
||||
}
|
||||
@ -331,44 +407,6 @@ WrapJSValue(JSContext *cx, JSObject *obj, jsval val, jsval *rval)
|
||||
return ok;
|
||||
}
|
||||
|
||||
static inline JSObject *
|
||||
FindSafeObject(JSObject *obj)
|
||||
{
|
||||
while (STOBJ_GET_CLASS(obj) != &sXPC_SJOW_JSClass.base) {
|
||||
obj = STOBJ_GET_PROTO(obj);
|
||||
|
||||
if (!obj) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
PRBool
|
||||
IsXPCSafeJSObjectWrapperClass(JSClass *clazz)
|
||||
{
|
||||
return clazz == &sXPC_SJOW_JSClass.base;
|
||||
}
|
||||
|
||||
static inline JSObject *
|
||||
GetUnsafeObject(JSObject *obj)
|
||||
{
|
||||
obj = FindSafeObject(obj);
|
||||
|
||||
if (!obj) {
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
return STOBJ_GET_PARENT(obj);
|
||||
}
|
||||
|
||||
JSObject *
|
||||
XPC_SJOW_GetUnsafeObject(JSObject *obj)
|
||||
{
|
||||
return GetUnsafeObject(obj);
|
||||
}
|
||||
|
||||
static jsval
|
||||
UnwrapJSValue(jsval val)
|
||||
{
|
||||
@ -400,8 +438,7 @@ XPC_SJOW_AddProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
|
||||
// Do nothing here if we're in the middle of resolving a property on
|
||||
// this safe wrapper.
|
||||
jsval isResolving;
|
||||
JSBool ok = ::JS_GetReservedSlot(cx, obj, XPC_SJOW_SLOT_IS_RESOLVING,
|
||||
&isResolving);
|
||||
JSBool ok = ::JS_GetReservedSlot(cx, obj, sFlagsSlot, &isResolving);
|
||||
if (!ok || HAS_FLAGS(isResolving, FLAG_RESOLVING)) {
|
||||
return ok;
|
||||
}
|
||||
@ -619,8 +656,7 @@ XPC_SJOW_Finalize(JSContext *cx, JSObject *obj)
|
||||
{
|
||||
// Release the reference to the cached principal if we have one.
|
||||
jsval v;
|
||||
if (::JS_GetReservedSlot(cx, obj, XPC_SJOW_SLOT_PRINCIPAL, &v) &&
|
||||
!JSVAL_IS_VOID(v)) {
|
||||
if (::JS_GetReservedSlot(cx, obj, sPrincipalSlot, &v) && !JSVAL_IS_VOID(v)) {
|
||||
nsIPrincipal *principal = (nsIPrincipal *)JSVAL_TO_PRIVATE(v);
|
||||
|
||||
NS_RELEASE(principal);
|
||||
@ -738,7 +774,7 @@ XPC_SJOW_Call(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
||||
return WrapJSValue(cx, obj, *rval, rval);
|
||||
}
|
||||
|
||||
JSBool
|
||||
static JSBool
|
||||
XPC_SJOW_Construct(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
||||
jsval *rval)
|
||||
{
|
||||
@ -796,7 +832,7 @@ XPC_SJOW_Construct(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
||||
// Don't use the object the JS engine created for us, it is in most
|
||||
// cases incorectly parented and has a proto from the wrong scope.
|
||||
JSObject *wrapperObj =
|
||||
::JS_NewObjectWithGivenProto(cx, &sXPC_SJOW_JSClass.base, nsnull,
|
||||
::JS_NewObjectWithGivenProto(cx, &SJOWClass.base, nsnull,
|
||||
objToWrap);
|
||||
|
||||
if (!wrapperObj) {
|
||||
@ -804,8 +840,7 @@ XPC_SJOW_Construct(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
if (!::JS_SetReservedSlot(cx, wrapperObj, XPC_SJOW_SLOT_IS_RESOLVING,
|
||||
JSVAL_ZERO)) {
|
||||
if (!::JS_SetReservedSlot(cx, wrapperObj, sFlagsSlot, JSVAL_ZERO)) {
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
@ -893,7 +928,9 @@ XPC_SJOW_Iterator(JSContext *cx, JSObject *obj, JSBool keysonly)
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
JSObject *tmp = XPCWrapper::UnwrapGeneric(cx, &sXPC_XOW_JSClass, unsafeObj);
|
||||
JSObject *tmp =
|
||||
XPCWrapper::UnwrapGeneric(cx, &XPCCrossOriginWrapper::XOWClass,
|
||||
unsafeObj);
|
||||
if (tmp) {
|
||||
unsafeObj = tmp;
|
||||
|
||||
@ -907,14 +944,13 @@ XPC_SJOW_Iterator(JSContext *cx, JSObject *obj, JSBool keysonly)
|
||||
|
||||
// Create our dummy SJOW.
|
||||
JSObject *wrapperIter =
|
||||
::JS_NewObjectWithGivenProto(cx, &sXPC_SJOW_JSClass.base, nsnull,
|
||||
::JS_NewObjectWithGivenProto(cx, &SJOWClass.base, nsnull,
|
||||
unsafeObj);
|
||||
if (!wrapperIter) {
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
if (!::JS_SetReservedSlot(cx, wrapperIter, XPC_SJOW_SLOT_IS_RESOLVING,
|
||||
JSVAL_ZERO)) {
|
||||
if (!::JS_SetReservedSlot(cx, wrapperIter, sFlagsSlot, JSVAL_ZERO)) {
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
@ -977,47 +1013,3 @@ XPC_SJOW_toString(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
||||
}
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
PRBool
|
||||
XPC_SJOW_AttachNewConstructorObject(XPCCallContext &ccx,
|
||||
JSObject *aGlobalObject)
|
||||
{
|
||||
// Initialize sEvalNative the first time we attach a constructor.
|
||||
// NB: This always happens before any cross origin wrappers are
|
||||
// created, so it's OK to do this here.
|
||||
if (!XPCWrapper::FindEval(ccx, aGlobalObject)) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
JSObject *class_obj =
|
||||
::JS_InitClass(ccx, aGlobalObject, nsnull, &sXPC_SJOW_JSClass.base,
|
||||
XPC_SJOW_Construct, 0, nsnull, nsnull, nsnull, nsnull);
|
||||
if (!class_obj) {
|
||||
NS_WARNING("can't initialize the XPCSafeJSObjectWrapper class");
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
if (!::JS_DefineFunction(ccx, class_obj, "toString", XPC_SJOW_toString,
|
||||
0, 0)) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
// Null out the class object's parent to prevent code in this class
|
||||
// from thinking the class object is a wrapper for the global
|
||||
// object.
|
||||
::JS_SetParent(ccx, class_obj, nsnull);
|
||||
|
||||
// Make sure our prototype chain is empty and that people can't mess
|
||||
// with XPCSafeJSObjectWrapper.prototype.
|
||||
::JS_SetPrototype(ccx, class_obj, nsnull);
|
||||
if (!::JS_SealObject(ccx, class_obj, JS_FALSE)) {
|
||||
NS_WARNING("Failed to seal XPCSafeJSObjectWrapper.prototype");
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
JSBool found;
|
||||
return ::JS_SetPropertyAttributes(ccx, aGlobalObject,
|
||||
sXPC_SJOW_JSClass.base.name,
|
||||
JSPROP_READONLY | JSPROP_PERMANENT,
|
||||
&found);
|
||||
}
|
||||
|
@ -85,7 +85,18 @@ XPC_SOW_Iterator(JSContext *cx, JSObject *obj, JSBool keysonly);
|
||||
static JSObject *
|
||||
XPC_SOW_WrappedObject(JSContext *cx, JSObject *obj);
|
||||
|
||||
JSExtendedClass sXPC_SOW_JSClass = {
|
||||
using namespace XPCWrapper;
|
||||
|
||||
// Throws an exception on context |cx|.
|
||||
static inline JSBool
|
||||
ThrowException(nsresult rv, JSContext *cx)
|
||||
{
|
||||
return DoThrowException(rv, cx);
|
||||
}
|
||||
|
||||
namespace SystemOnlyWrapper {
|
||||
|
||||
JSExtendedClass SOWClass = {
|
||||
// JSClass (JSExtendedClass.base) initialization
|
||||
{ "SystemOnlyWrapper",
|
||||
JSCLASS_NEW_RESOLVE | JSCLASS_IS_EXTENDED |
|
||||
@ -109,55 +120,31 @@ JSExtendedClass sXPC_SOW_JSClass = {
|
||||
JSCLASS_NO_RESERVED_MEMBERS
|
||||
};
|
||||
|
||||
static JSBool
|
||||
XPC_SOW_toString(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
||||
jsval *rval);
|
||||
|
||||
// Throws an exception on context |cx|.
|
||||
static inline JSBool
|
||||
ThrowException(nsresult rv, JSContext *cx)
|
||||
JSBool
|
||||
WrapObject(JSContext *cx, JSObject *parent, jsval v, jsval *vp)
|
||||
{
|
||||
return XPCWrapper::ThrowException(rv, cx);
|
||||
}
|
||||
|
||||
// Like GetWrappedObject, but works on other types of wrappers, too.
|
||||
// TODO Move to XPCWrapper?
|
||||
static inline JSObject *
|
||||
GetWrappedJSObject(JSContext *cx, JSObject *obj)
|
||||
{
|
||||
JSClass *clasp = STOBJ_GET_CLASS(obj);
|
||||
if (!(clasp->flags & JSCLASS_IS_EXTENDED)) {
|
||||
return obj;
|
||||
// Slim wrappers don't expect to be wrapped, so morph them to fat wrappers
|
||||
// if we're about to wrap one.
|
||||
JSObject *innerObj = JSVAL_TO_OBJECT(v);
|
||||
if (IS_SLIM_WRAPPER(innerObj) && !MorphSlimWrapper(cx, innerObj)) {
|
||||
return ThrowException(NS_ERROR_FAILURE, cx);
|
||||
}
|
||||
|
||||
JSExtendedClass *xclasp = (JSExtendedClass *)clasp;
|
||||
if (!xclasp->wrappedObject) {
|
||||
return obj;
|
||||
JSObject *wrapperObj =
|
||||
JS_NewObjectWithGivenProto(cx, &SOWClass.base, NULL, parent);
|
||||
if (!wrapperObj) {
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
return xclasp->wrappedObject(cx, obj);
|
||||
}
|
||||
*vp = OBJECT_TO_JSVAL(wrapperObj);
|
||||
JSAutoTempValueRooter tvr(cx, *vp);
|
||||
|
||||
// Get the (possibly non-existant) SOW off of an object
|
||||
static inline
|
||||
JSObject *
|
||||
GetWrapper(JSObject *obj)
|
||||
{
|
||||
while (STOBJ_GET_CLASS(obj) != &sXPC_SOW_JSClass.base) {
|
||||
obj = STOBJ_GET_PROTO(obj);
|
||||
if (!obj) {
|
||||
break;
|
||||
}
|
||||
if (!JS_SetReservedSlot(cx, wrapperObj, sWrappedObjSlot, v) ||
|
||||
!JS_SetReservedSlot(cx, wrapperObj, sFlagsSlot, JSVAL_ZERO)) {
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
static inline
|
||||
JSObject *
|
||||
GetWrappedObject(JSContext *cx, JSObject *wrapper)
|
||||
{
|
||||
return XPCWrapper::UnwrapGeneric(cx, &sXPC_SOW_JSClass, wrapper);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
// If you change this code, change also nsContentUtils::CanAccessNativeAnon()!
|
||||
@ -165,7 +152,7 @@ JSBool
|
||||
AllowedToAct(JSContext *cx, jsval idval)
|
||||
{
|
||||
// TODO bug 508928: Refactor this with the XOW security checking code.
|
||||
nsIScriptSecurityManager *ssm = XPCWrapper::GetSecurityManager();
|
||||
nsIScriptSecurityManager *ssm = GetSecurityManager();
|
||||
if (!ssm) {
|
||||
return JS_TRUE;
|
||||
}
|
||||
@ -227,6 +214,54 @@ AllowedToAct(JSContext *cx, jsval idval)
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
} // namespace SystemOnlyWrapper
|
||||
|
||||
using namespace SystemOnlyWrapper;
|
||||
|
||||
static JSBool
|
||||
XPC_SOW_toString(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
||||
jsval *rval);
|
||||
|
||||
// Like GetWrappedObject, but works on other types of wrappers, too.
|
||||
// TODO Move to XPCWrapper?
|
||||
static inline JSObject *
|
||||
GetWrappedJSObject(JSContext *cx, JSObject *obj)
|
||||
{
|
||||
JSClass *clasp = STOBJ_GET_CLASS(obj);
|
||||
if (!(clasp->flags & JSCLASS_IS_EXTENDED)) {
|
||||
return obj;
|
||||
}
|
||||
|
||||
JSExtendedClass *xclasp = (JSExtendedClass *)clasp;
|
||||
if (!xclasp->wrappedObject) {
|
||||
return obj;
|
||||
}
|
||||
|
||||
return xclasp->wrappedObject(cx, obj);
|
||||
}
|
||||
|
||||
// Get the (possibly non-existant) SOW off of an object
|
||||
static inline
|
||||
JSObject *
|
||||
GetWrapper(JSObject *obj)
|
||||
{
|
||||
while (STOBJ_GET_CLASS(obj) != &SOWClass.base) {
|
||||
obj = STOBJ_GET_PROTO(obj);
|
||||
if (!obj) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
static inline
|
||||
JSObject *
|
||||
GetWrappedObject(JSContext *cx, JSObject *wrapper)
|
||||
{
|
||||
return UnwrapGeneric(cx, &SOWClass, wrapper);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
XPC_SOW_FunctionWrapper(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
||||
jsval *rval)
|
||||
@ -254,8 +289,7 @@ XPC_SOW_FunctionWrapper(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
||||
|
||||
JSObject *funObj = JSVAL_TO_OBJECT(argv[-2]);
|
||||
jsval funToCall;
|
||||
if (!JS_GetReservedSlot(cx, funObj, XPCWrapper::eWrappedFunctionSlot,
|
||||
&funToCall)) {
|
||||
if (!JS_GetReservedSlot(cx, funObj, eWrappedFunctionSlot, &funToCall)) {
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
@ -288,7 +322,7 @@ XPC_SOW_WrapFunction(JSContext *cx, JSObject *outerObj, JSObject *funobj,
|
||||
*rval = OBJECT_TO_JSVAL(funWrapperObj);
|
||||
|
||||
return JS_SetReservedSlot(cx, funWrapperObj,
|
||||
XPCWrapper::eWrappedFunctionSlot,
|
||||
eWrappedFunctionSlot,
|
||||
funobjVal);
|
||||
}
|
||||
|
||||
@ -321,7 +355,7 @@ XPC_SOW_RewrapValue(JSContext *cx, JSObject *wrapperObj, jsval *vp)
|
||||
}
|
||||
|
||||
// It isn't ours, rewrap the wrapped function.
|
||||
if (!JS_GetReservedSlot(cx, obj, XPCWrapper::eWrappedFunctionSlot, &v)) {
|
||||
if (!JS_GetReservedSlot(cx, obj, eWrappedFunctionSlot, &v)) {
|
||||
return JS_FALSE;
|
||||
}
|
||||
obj = JSVAL_TO_OBJECT(v);
|
||||
@ -330,7 +364,7 @@ XPC_SOW_RewrapValue(JSContext *cx, JSObject *wrapperObj, jsval *vp)
|
||||
return XPC_SOW_WrapFunction(cx, wrapperObj, obj, vp);
|
||||
}
|
||||
|
||||
if (STOBJ_GET_CLASS(obj) == &sXPC_SOW_JSClass.base) {
|
||||
if (STOBJ_GET_CLASS(obj) == &SOWClass.base) {
|
||||
// We are extra careful about content-polluted wrappers here. I don't know
|
||||
// if it's possible to reach them through objects that we wrap, but figuring
|
||||
// that out is more expensive (and harder) than simply checking and
|
||||
@ -349,16 +383,16 @@ XPC_SOW_RewrapValue(JSContext *cx, JSObject *wrapperObj, jsval *vp)
|
||||
v = *vp = OBJECT_TO_JSVAL(obj);
|
||||
}
|
||||
|
||||
return XPC_SOW_WrapObject(cx, STOBJ_GET_PARENT(wrapperObj), v, vp);
|
||||
return WrapObject(cx, STOBJ_GET_PARENT(wrapperObj), v, vp);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
XPC_SOW_AddProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
|
||||
{
|
||||
NS_ASSERTION(STOBJ_GET_CLASS(obj) == &sXPC_SOW_JSClass.base, "Wrong object");
|
||||
NS_ASSERTION(STOBJ_GET_CLASS(obj) == &SOWClass.base, "Wrong object");
|
||||
|
||||
jsval resolving;
|
||||
if (!JS_GetReservedSlot(cx, obj, XPCWrapper::sFlagsSlot, &resolving)) {
|
||||
if (!JS_GetReservedSlot(cx, obj, sFlagsSlot, &resolving)) {
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
@ -376,7 +410,7 @@ XPC_SOW_AddProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
return XPCWrapper::AddProperty(cx, obj, JS_TRUE, wrappedObj, id, vp);
|
||||
return AddProperty(cx, obj, JS_TRUE, wrappedObj, id, vp);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
@ -391,7 +425,7 @@ XPC_SOW_DelProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
return XPCWrapper::DelProperty(cx, wrappedObj, id, vp);
|
||||
return DelProperty(cx, wrappedObj, id, vp);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
@ -464,7 +498,7 @@ XPC_SOW_Enumerate(JSContext *cx, JSObject *obj)
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
return XPCWrapper::Enumerate(cx, obj, wrappedObj);
|
||||
return Enumerate(cx, obj, wrappedObj);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
@ -486,8 +520,8 @@ XPC_SOW_NewResolve(JSContext *cx, JSObject *obj, jsval id, uintN flags,
|
||||
|
||||
if (id == GetRTStringByIndex(cx, XPCJSRuntime::IDX_TO_STRING)) {
|
||||
jsval oldSlotVal;
|
||||
if (!JS_GetReservedSlot(cx, obj, XPCWrapper::sFlagsSlot, &oldSlotVal) ||
|
||||
!JS_SetReservedSlot(cx, obj, XPCWrapper::sFlagsSlot,
|
||||
if (!JS_GetReservedSlot(cx, obj, sFlagsSlot, &oldSlotVal) ||
|
||||
!JS_SetReservedSlot(cx, obj, sFlagsSlot,
|
||||
INT_TO_JSVAL(JSVAL_TO_INT(oldSlotVal) |
|
||||
FLAG_RESOLVING))) {
|
||||
return JS_FALSE;
|
||||
@ -496,7 +530,7 @@ XPC_SOW_NewResolve(JSContext *cx, JSObject *obj, jsval id, uintN flags,
|
||||
JSBool ok = JS_DefineFunction(cx, obj, "toString",
|
||||
XPC_SOW_toString, 0, 0) != nsnull;
|
||||
|
||||
JS_SetReservedSlot(cx, obj, XPCWrapper::sFlagsSlot, oldSlotVal);
|
||||
JS_SetReservedSlot(cx, obj, sFlagsSlot, oldSlotVal);
|
||||
|
||||
if (ok) {
|
||||
*objp = obj;
|
||||
@ -505,7 +539,7 @@ XPC_SOW_NewResolve(JSContext *cx, JSObject *obj, jsval id, uintN flags,
|
||||
return ok;
|
||||
}
|
||||
|
||||
return XPCWrapper::NewResolve(cx, obj, JS_TRUE, wrappedObj, id, flags, objp);
|
||||
return NewResolve(cx, obj, JS_TRUE, wrappedObj, id, flags, objp);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
@ -643,7 +677,7 @@ XPC_SOW_Iterator(JSContext *cx, JSObject *obj, JSBool keysonly)
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
JSObject *wrapperIter = JS_NewObject(cx, &sXPC_SOW_JSClass.base, nsnull,
|
||||
JSObject *wrapperIter = JS_NewObject(cx, &SOWClass.base, nsnull,
|
||||
JS_GetGlobalForObject(cx, obj));
|
||||
if (!wrapperIter) {
|
||||
return nsnull;
|
||||
@ -653,14 +687,12 @@ XPC_SOW_Iterator(JSContext *cx, JSObject *obj, JSBool keysonly)
|
||||
|
||||
// Initialize our SOW.
|
||||
jsval v = OBJECT_TO_JSVAL(wrappedObj);
|
||||
if (!JS_SetReservedSlot(cx, wrapperIter, XPCWrapper::sWrappedObjSlot, v) ||
|
||||
!JS_SetReservedSlot(cx, wrapperIter, XPCWrapper::sFlagsSlot,
|
||||
JSVAL_ZERO)) {
|
||||
if (!JS_SetReservedSlot(cx, wrapperIter, sWrappedObjSlot, v) ||
|
||||
!JS_SetReservedSlot(cx, wrapperIter, sFlagsSlot, JSVAL_ZERO)) {
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
return XPCWrapper::CreateIteratorObj(cx, wrapperIter, obj, wrappedObj,
|
||||
keysonly);
|
||||
return CreateIteratorObj(cx, wrapperIter, obj, wrappedObj, keysonly);
|
||||
}
|
||||
|
||||
static JSObject *
|
||||
@ -697,34 +729,5 @@ XPC_SOW_toString(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
||||
|
||||
XPCWrappedNative *wn =
|
||||
XPCWrappedNative::GetWrappedNativeOfJSObject(cx, wrappedObj);
|
||||
return XPCWrapper::NativeToString(cx, wn, argc, argv, rval, JS_FALSE);
|
||||
}
|
||||
|
||||
JSBool
|
||||
XPC_SOW_WrapObject(JSContext *cx, JSObject *parent, jsval v,
|
||||
jsval *vp)
|
||||
{
|
||||
// Slim wrappers don't expect to be wrapped, so morph them to fat wrappers
|
||||
// if we're about to wrap one.
|
||||
JSObject *innerObj = JSVAL_TO_OBJECT(v);
|
||||
if (IS_SLIM_WRAPPER(innerObj) && !MorphSlimWrapper(cx, innerObj)) {
|
||||
return ThrowException(NS_ERROR_FAILURE, cx);
|
||||
}
|
||||
|
||||
JSObject *wrapperObj =
|
||||
JS_NewObjectWithGivenProto(cx, &sXPC_SOW_JSClass.base, NULL, parent);
|
||||
if (!wrapperObj) {
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
*vp = OBJECT_TO_JSVAL(wrapperObj);
|
||||
JSAutoTempValueRooter tvr(cx, *vp);
|
||||
|
||||
if (!JS_SetReservedSlot(cx, wrapperObj, XPCWrapper::sWrappedObjSlot, v) ||
|
||||
!JS_SetReservedSlot(cx, wrapperObj, XPCWrapper::sFlagsSlot,
|
||||
JSVAL_ZERO)) {
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
return JS_TRUE;
|
||||
return NativeToString(cx, wn, argc, argv, rval, JS_FALSE);
|
||||
}
|
||||
|
@ -43,29 +43,24 @@
|
||||
#include "XPCWrapper.h"
|
||||
#include "XPCNativeWrapper.h"
|
||||
|
||||
const PRUint32
|
||||
XPCWrapper::sWrappedObjSlot = 1;
|
||||
namespace XPCWrapper {
|
||||
|
||||
const PRUint32
|
||||
XPCWrapper::sFlagsSlot = 0;
|
||||
const PRUint32 sWrappedObjSlot = 1;
|
||||
const PRUint32 sFlagsSlot = 0;
|
||||
const PRUint32 sNumSlots = 2;
|
||||
JSNative sEvalNative = nsnull;
|
||||
|
||||
const PRUint32
|
||||
XPCWrapper::sNumSlots = 2;
|
||||
const PRUint32 FLAG_RESOLVING = 0x1;
|
||||
const PRUint32 LAST_FLAG = FLAG_RESOLVING;
|
||||
|
||||
JSNative
|
||||
XPCWrapper::sEvalNative = nsnull;
|
||||
const PRUint32 sSecMgrSetProp = nsIXPCSecurityManager::ACCESS_SET_PROPERTY;
|
||||
const PRUint32 sSecMgrGetProp = nsIXPCSecurityManager::ACCESS_GET_PROPERTY;
|
||||
|
||||
const PRUint32
|
||||
XPCWrapper::sSecMgrSetProp = nsIXPCSecurityManager::ACCESS_SET_PROPERTY;
|
||||
const PRUint32
|
||||
XPCWrapper::sSecMgrGetProp = nsIXPCSecurityManager::ACCESS_GET_PROPERTY;
|
||||
|
||||
// static
|
||||
JSObject *
|
||||
XPCWrapper::Unwrap(JSContext *cx, JSObject *wrapper)
|
||||
Unwrap(JSContext *cx, JSObject *wrapper)
|
||||
{
|
||||
JSClass *clasp = STOBJ_GET_CLASS(wrapper);
|
||||
if (clasp == &sXPC_XOW_JSClass.base) {
|
||||
if (clasp == &XPCCrossOriginWrapper::XOWClass.base) {
|
||||
return UnwrapXOW(cx, wrapper);
|
||||
}
|
||||
|
||||
@ -79,10 +74,10 @@ XPCWrapper::Unwrap(JSContext *cx, JSObject *wrapper)
|
||||
return wrappedObj->GetFlatJSObject();
|
||||
}
|
||||
|
||||
if (clasp == &sXPC_SJOW_JSClass.base) {
|
||||
if (clasp == &XPCSafeJSObjectWrapper::SJOWClass.base) {
|
||||
JSObject *wrappedObj = STOBJ_GET_PARENT(wrapper);
|
||||
|
||||
if (NS_FAILED(CanAccessWrapper(cx, wrappedObj, nsnull))) {
|
||||
if (NS_FAILED(XPCCrossOriginWrapper::CanAccessWrapper(cx, wrappedObj, nsnull))) {
|
||||
JS_ClearPendingException(cx);
|
||||
|
||||
return nsnull;
|
||||
@ -91,10 +86,10 @@ XPCWrapper::Unwrap(JSContext *cx, JSObject *wrapper)
|
||||
return wrappedObj;
|
||||
}
|
||||
|
||||
if (clasp == &sXPC_SOW_JSClass.base) {
|
||||
if (clasp == &SystemOnlyWrapper::SOWClass.base) {
|
||||
return UnwrapSOW(cx, wrapper);
|
||||
}
|
||||
if (clasp == &sXPC_COW_JSClass.base) {
|
||||
if (clasp == &ChromeObjectWrapper::COWClass.base) {
|
||||
return UnwrapCOW(cx, wrapper);
|
||||
}
|
||||
|
||||
@ -180,11 +175,10 @@ static JSClass IteratorClass = {
|
||||
JSCLASS_NO_OPTIONAL_MEMBERS
|
||||
};
|
||||
|
||||
// static
|
||||
JSObject *
|
||||
XPCWrapper::CreateIteratorObj(JSContext *cx, JSObject *tempWrapper,
|
||||
JSObject *wrapperObj, JSObject *innerObj,
|
||||
JSBool keysonly)
|
||||
CreateIteratorObj(JSContext *cx, JSObject *tempWrapper,
|
||||
JSObject *wrapperObj, JSObject *innerObj,
|
||||
JSBool keysonly)
|
||||
{
|
||||
// This is rather ugly: we want to use the trick seen in Enumerate,
|
||||
// where we use our wrapper's resolve hook to determine if we should
|
||||
@ -251,11 +245,9 @@ XPCWrapper::CreateIteratorObj(JSContext *cx, JSObject *tempWrapper,
|
||||
return iterObj;
|
||||
}
|
||||
|
||||
// static
|
||||
JSBool
|
||||
XPCWrapper::AddProperty(JSContext *cx, JSObject *wrapperObj,
|
||||
JSBool wantGetterSetter, JSObject *innerObj, jsval id,
|
||||
jsval *vp)
|
||||
AddProperty(JSContext *cx, JSObject *wrapperObj, JSBool wantGetterSetter,
|
||||
JSObject *innerObj, jsval id, jsval *vp)
|
||||
{
|
||||
jsid interned_id;
|
||||
if (!::JS_ValueToId(cx, id, &interned_id)) {
|
||||
@ -275,9 +267,8 @@ XPCWrapper::AddProperty(JSContext *cx, JSObject *wrapperObj,
|
||||
desc.getter, desc.setter, desc.attrs);
|
||||
}
|
||||
|
||||
// static
|
||||
JSBool
|
||||
XPCWrapper::DelProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
|
||||
DelProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
|
||||
{
|
||||
if (JSVAL_IS_STRING(id)) {
|
||||
JSString *str = JSVAL_TO_STRING(id);
|
||||
@ -288,15 +279,14 @@ XPCWrapper::DelProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
|
||||
}
|
||||
|
||||
if (!JSVAL_IS_INT(id)) {
|
||||
return ThrowException(NS_ERROR_NOT_IMPLEMENTED, cx);
|
||||
return DoThrowException(NS_ERROR_NOT_IMPLEMENTED, cx);
|
||||
}
|
||||
|
||||
return ::JS_DeleteElement2(cx, obj, JSVAL_TO_INT(id), vp);
|
||||
}
|
||||
|
||||
// static
|
||||
JSBool
|
||||
XPCWrapper::Enumerate(JSContext *cx, JSObject *wrapperObj, JSObject *innerObj)
|
||||
Enumerate(JSContext *cx, JSObject *wrapperObj, JSObject *innerObj)
|
||||
{
|
||||
// We are being notified of a for-in loop or similar operation on
|
||||
// this wrapper. Forward to the correct high-level object hook,
|
||||
@ -342,11 +332,9 @@ XPCWrapper::Enumerate(JSContext *cx, JSObject *wrapperObj, JSObject *innerObj)
|
||||
return ok;
|
||||
}
|
||||
|
||||
// static
|
||||
JSBool
|
||||
XPCWrapper::NewResolve(JSContext *cx, JSObject *wrapperObj,
|
||||
JSBool wantDetails, JSObject *innerObj, jsval id,
|
||||
uintN flags, JSObject **objp)
|
||||
NewResolve(JSContext *cx, JSObject *wrapperObj, JSBool wantDetails,
|
||||
JSObject *innerObj, jsval id, uintN flags, JSObject **objp)
|
||||
{
|
||||
jsid interned_id;
|
||||
if (!::JS_ValueToId(cx, id, &interned_id)) {
|
||||
@ -385,12 +373,11 @@ XPCWrapper::NewResolve(JSContext *cx, JSObject *wrapperObj,
|
||||
return ok;
|
||||
}
|
||||
|
||||
// static
|
||||
JSBool
|
||||
XPCWrapper::ResolveNativeProperty(JSContext *cx, JSObject *wrapperObj,
|
||||
JSObject *innerObj, XPCWrappedNative *wn,
|
||||
jsval id, uintN flags, JSObject **objp,
|
||||
JSBool isNativeWrapper)
|
||||
ResolveNativeProperty(JSContext *cx, JSObject *wrapperObj,
|
||||
JSObject *innerObj, XPCWrappedNative *wn,
|
||||
jsval id, uintN flags, JSObject **objp,
|
||||
JSBool isNativeWrapper)
|
||||
{
|
||||
// This will do verification and the method lookup for us.
|
||||
XPCCallContext ccx(JS_CALLER, cx, innerObj, nsnull, id);
|
||||
@ -432,7 +419,7 @@ XPCWrapper::ResolveNativeProperty(JSContext *cx, JSObject *wrapperObj,
|
||||
}
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
return ThrowException(rv, cx);
|
||||
return DoThrowException(rv, cx);
|
||||
}
|
||||
|
||||
if (newObj) {
|
||||
@ -457,7 +444,7 @@ XPCWrapper::ResolveNativeProperty(JSContext *cx, JSObject *wrapperObj,
|
||||
// I suspect that we'd need to redo the security check on the new object
|
||||
// (if it has a different class than the original object) and then call
|
||||
// ResolveNativeProperty with *that* as the inner object.
|
||||
return ThrowException(NS_ERROR_NOT_IMPLEMENTED, cx);
|
||||
return DoThrowException(NS_ERROR_NOT_IMPLEMENTED, cx);
|
||||
}
|
||||
}
|
||||
|
||||
@ -472,7 +459,7 @@ XPCWrapper::ResolveNativeProperty(JSContext *cx, JSObject *wrapperObj,
|
||||
XPCWrappedNative* wrapper = ccx.GetWrapper();
|
||||
if (wrapper != wn || !wrapper->IsValid()) {
|
||||
NS_ASSERTION(wrapper == wn, "Uh, how did this happen!");
|
||||
return ThrowException(NS_ERROR_XPC_BAD_CONVERT_JS, cx);
|
||||
return DoThrowException(NS_ERROR_XPC_BAD_CONVERT_JS, cx);
|
||||
}
|
||||
|
||||
// it would be a big surprise if there is a member without an
|
||||
@ -494,7 +481,7 @@ XPCWrapper::ResolveNativeProperty(JSContext *cx, JSObject *wrapperObj,
|
||||
|
||||
JSString *str = JSVAL_TO_STRING(id);
|
||||
if (!str) {
|
||||
return ThrowException(NS_ERROR_UNEXPECTED, cx);
|
||||
return DoThrowException(NS_ERROR_UNEXPECTED, cx);
|
||||
}
|
||||
|
||||
// Get (and perhaps lazily create) the member's value (commonly a
|
||||
@ -506,7 +493,7 @@ XPCWrapper::ResolveNativeProperty(JSContext *cx, JSObject *wrapperObj,
|
||||
|
||||
if (member->IsConstant()) {
|
||||
if (!member->GetConstantValue(ccx, iface, &v)) {
|
||||
return ThrowException(NS_ERROR_XPC_BAD_CONVERT_JS, cx);
|
||||
return DoThrowException(NS_ERROR_XPC_BAD_CONVERT_JS, cx);
|
||||
}
|
||||
} else if (member->IsAttribute()) {
|
||||
// An attribute is being resolved. Define the property, the value
|
||||
@ -524,7 +511,7 @@ XPCWrapper::ResolveNativeProperty(JSContext *cx, JSObject *wrapperObj,
|
||||
jsval funval;
|
||||
if (!member->NewFunctionObject(ccx, iface, wrapper->GetFlatJSObject(),
|
||||
&funval)) {
|
||||
return ThrowException(NS_ERROR_XPC_BAD_CONVERT_JS, cx);
|
||||
return DoThrowException(NS_ERROR_XPC_BAD_CONVERT_JS, cx);
|
||||
}
|
||||
|
||||
AUTO_MARK_JSVAL(ccx, funval);
|
||||
@ -582,12 +569,11 @@ XPCWrapper::ResolveNativeProperty(JSContext *cx, JSObject *wrapperObj,
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
// static
|
||||
JSBool
|
||||
XPCWrapper::GetOrSetNativeProperty(JSContext *cx, JSObject *obj,
|
||||
XPCWrappedNative *wrappedNative,
|
||||
jsval id, jsval *vp, JSBool aIsSet,
|
||||
JSBool isNativeWrapper)
|
||||
GetOrSetNativeProperty(JSContext *cx, JSObject *obj,
|
||||
XPCWrappedNative *wrappedNative,
|
||||
jsval id, jsval *vp, JSBool aIsSet,
|
||||
JSBool isNativeWrapper)
|
||||
{
|
||||
// This will do verification and the method lookup for us.
|
||||
JSObject *nativeObj = wrappedNative->GetFlatJSObject();
|
||||
@ -610,7 +596,7 @@ XPCWrapper::GetOrSetNativeProperty(JSContext *cx, JSObject *obj,
|
||||
}
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
return ThrowException(rv, cx);
|
||||
return DoThrowException(rv, cx);
|
||||
}
|
||||
if (!retval) {
|
||||
return JS_FALSE;
|
||||
@ -643,7 +629,7 @@ XPCWrapper::GetOrSetNativeProperty(JSContext *cx, JSObject *obj,
|
||||
XPCWrappedNative* wrapper = ccx.GetWrapper();
|
||||
if (wrapper != wrappedNative || !wrapper->IsValid()) {
|
||||
NS_ASSERTION(wrapper == wrappedNative, "Uh, how did this happen!");
|
||||
return ThrowException(NS_ERROR_XPC_BAD_CONVERT_JS, cx);
|
||||
return DoThrowException(NS_ERROR_XPC_BAD_CONVERT_JS, cx);
|
||||
}
|
||||
|
||||
// it would be a big surprise if there is a member without an
|
||||
@ -665,13 +651,13 @@ XPCWrapper::GetOrSetNativeProperty(JSContext *cx, JSObject *obj,
|
||||
if (member->IsConstant()) {
|
||||
jsval memberval;
|
||||
if (!member->GetConstantValue(ccx, iface, &memberval)) {
|
||||
return ThrowException(NS_ERROR_XPC_BAD_CONVERT_JS, cx);
|
||||
return DoThrowException(NS_ERROR_XPC_BAD_CONVERT_JS, cx);
|
||||
}
|
||||
|
||||
// Getting the value of constants is easy, just return the
|
||||
// value. Setting is not supported (obviously).
|
||||
if (aIsSet) {
|
||||
return ThrowException(NS_ERROR_XPC_BAD_CONVERT_JS, cx);
|
||||
return DoThrowException(NS_ERROR_XPC_BAD_CONVERT_JS, cx);
|
||||
}
|
||||
|
||||
*vp = memberval;
|
||||
@ -689,7 +675,7 @@ XPCWrapper::GetOrSetNativeProperty(JSContext *cx, JSObject *obj,
|
||||
jsval funval;
|
||||
if (!member->NewFunctionObject(ccx, iface, wrapper->GetFlatJSObject(),
|
||||
&funval)) {
|
||||
return ThrowException(NS_ERROR_XPC_BAD_CONVERT_JS, cx);
|
||||
return DoThrowException(NS_ERROR_XPC_BAD_CONVERT_JS, cx);
|
||||
}
|
||||
|
||||
AUTO_MARK_JSVAL(ccx, funval);
|
||||
@ -700,7 +686,7 @@ XPCWrapper::GetOrSetNativeProperty(JSContext *cx, JSObject *obj,
|
||||
if (aIsSet) {
|
||||
if (member->IsReadOnlyAttribute()) {
|
||||
// Trying to set a property for which there is no setter!
|
||||
return ThrowException(NS_ERROR_NOT_AVAILABLE, cx);
|
||||
return DoThrowException(NS_ERROR_NOT_AVAILABLE, cx);
|
||||
}
|
||||
|
||||
#ifdef DEBUG_XPCNativeWrapper
|
||||
@ -736,11 +722,10 @@ XPCWrapper::GetOrSetNativeProperty(JSContext *cx, JSObject *obj,
|
||||
}
|
||||
}
|
||||
|
||||
// static
|
||||
JSBool
|
||||
XPCWrapper::NativeToString(JSContext *cx, XPCWrappedNative *wrappedNative,
|
||||
uintN argc, jsval *argv, jsval *rval,
|
||||
JSBool isNativeWrapper)
|
||||
NativeToString(JSContext *cx, XPCWrappedNative *wrappedNative,
|
||||
uintN argc, jsval *argv, jsval *rval,
|
||||
JSBool isNativeWrapper)
|
||||
{
|
||||
// Check whether toString was overridden in any object along
|
||||
// the wrapped native's object's prototype chain.
|
||||
@ -757,7 +742,7 @@ XPCWrapper::NativeToString(JSContext *cx, XPCWrappedNative *wrappedNative,
|
||||
XPCCallContext ccx(JS_CALLER, cx, wn_obj, nsnull, idAsVal);
|
||||
if (!ccx.IsValid()) {
|
||||
// Shouldn't really happen.
|
||||
return ThrowException(NS_ERROR_FAILURE, cx);
|
||||
return DoThrowException(NS_ERROR_FAILURE, cx);
|
||||
}
|
||||
|
||||
XPCNativeInterface *iface = ccx.GetInterface();
|
||||
@ -827,11 +812,10 @@ XPCWrapper::NativeToString(JSContext *cx, XPCWrappedNative *wrappedNative,
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
// static
|
||||
JSBool
|
||||
XPCWrapper::GetPropertyAttrs(JSContext *cx, JSObject *obj, jsid interned_id,
|
||||
uintN flags, JSBool wantDetails,
|
||||
JSPropertyDescriptor *desc)
|
||||
GetPropertyAttrs(JSContext *cx, JSObject *obj, jsid interned_id,
|
||||
uintN flags, JSBool wantDetails,
|
||||
JSPropertyDescriptor *desc)
|
||||
{
|
||||
if (!JS_GetPropertyDescriptorById(cx, obj, interned_id, flags, desc)) {
|
||||
return JS_FALSE;
|
||||
@ -864,3 +848,5 @@ XPCWrapper::GetPropertyAttrs(JSContext *cx, JSObject *obj, jsid interned_id,
|
||||
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -45,51 +45,60 @@
|
||||
|
||||
#include "xpcprivate.h"
|
||||
|
||||
/* These are used by XPCNativeWrapper polluted code in the common wrapper. */
|
||||
#define FLAG_DEEP 0x1
|
||||
#define FLAG_EXPLICIT 0x2
|
||||
// FLAG_RESOLVING is used to tag an XPCNativeWrapper when while it's calling
|
||||
// the newResolve hook on the XPCWrappedNative's scriptable info.
|
||||
#define FLAG_RESOLVING 0x4
|
||||
// FLAG_IS_UXPC_OBJECT is used to tag a XPCCrossOriginWrapper that we created
|
||||
// to deal with a cross origin XOW that has UniversalXPConnect privileges.
|
||||
#define FLAG_IS_UXPC_OBJECT (1 << 29)
|
||||
|
||||
#define HAS_FLAGS(_val, _flags) \
|
||||
((PRUint32(JSVAL_TO_INT(_val)) & (_flags)) != 0)
|
||||
namespace XPCNativeWrapper {
|
||||
|
||||
// Given an XPCWrappedNative pointer and the name of the function on
|
||||
// XPCNativeScriptableFlags corresponding with a flag, returns 'true'
|
||||
// if the flag is set.
|
||||
// XXX Convert to using GetFlags() and not a macro.
|
||||
#define NATIVE_HAS_FLAG(_wn, _flag) \
|
||||
((_wn)->GetScriptableInfo() && \
|
||||
(_wn)->GetScriptableInfo()->GetFlags()._flag())
|
||||
|
||||
// Wraps a function in an XPCNativeWrapper function wrapper.
|
||||
JSBool
|
||||
XPC_NW_WrapFunction(JSContext* cx, JSObject* funobj, jsval *rval);
|
||||
WrapFunction(JSContext* cx, JSObject* funobj, jsval *rval);
|
||||
|
||||
// Given a value, if the original XPCNativeWrapper is a deep wrapper,
|
||||
// returns a new XPCNativeWrapper around the value.
|
||||
JSBool
|
||||
XPC_NW_RewrapIfDeepWrapper(JSContext *cx, JSObject *obj, jsval v,
|
||||
jsval *rval);
|
||||
RewrapIfDeepWrapper(JSContext *cx, JSObject *obj, jsval v, jsval *rval);
|
||||
|
||||
/* These are used by XPC_XOW_* polluted code in the common wrapper. */
|
||||
} // namespace XPCNativeWrapper
|
||||
|
||||
namespace XPCCrossOriginWrapper {
|
||||
|
||||
// Wraps an object in an XPCCrossOriginWrapper.
|
||||
JSBool
|
||||
XPC_XOW_WrapFunction(JSContext *cx, JSObject *wrapperObj, JSObject *funobj,
|
||||
jsval *rval);
|
||||
WrapObject(JSContext *cx, JSObject *parent, jsval *vp,
|
||||
XPCWrappedNative *wn = nsnull);
|
||||
|
||||
// Wraps a function in an XPCCrossOriginWrapper function wrapper.
|
||||
JSBool
|
||||
XPC_XOW_RewrapIfNeeded(JSContext *cx, JSObject *wrapperObj, jsval *vp);
|
||||
WrapFunction(JSContext *cx, JSObject *wrapperObj, JSObject *funobj,
|
||||
jsval *rval);
|
||||
|
||||
// Wraps a value in a XOW if we need to wrap it (either it's cross-scope
|
||||
// or ClassNeedsXOW returns true).
|
||||
JSBool
|
||||
XPC_XOW_WrapperMoved(JSContext *cx, XPCWrappedNative *innerObj,
|
||||
XPCWrappedNativeScope *newScope);
|
||||
RewrapIfNeeded(JSContext *cx, JSObject *wrapperObj, jsval *vp);
|
||||
|
||||
// Notify a wrapper's XOWs that the wrapper has been reparented.
|
||||
JSBool
|
||||
WrapperMoved(JSContext *cx, XPCWrappedNative *innerObj,
|
||||
XPCWrappedNativeScope *newScope);
|
||||
|
||||
// Returns 'true' if the current context is same-origin to the wrappedObject.
|
||||
// If we are "same origin" because UniversalXPConnect is enabled and
|
||||
// privilegeEnabled is non-null, then privilegeEnabled is set to true.
|
||||
nsresult
|
||||
CanAccessWrapper(JSContext *cx, JSObject *wrappedObj, JSBool *privilegeEnabled);
|
||||
|
||||
// Used by UnwrapSOW below.
|
||||
JSBool
|
||||
AllowedToAct(JSContext *cx, jsval idval);
|
||||
|
||||
// Some elements can change their principal or otherwise need XOWs, even
|
||||
// if they're same origin. This function returns 'true' if the element's
|
||||
// JSClass's name matches one such element.
|
||||
inline JSBool
|
||||
XPC_XOW_ClassNeedsXOW(const char *name)
|
||||
ClassNeedsXOW(const char *name)
|
||||
{
|
||||
switch (*name) {
|
||||
case 'W':
|
||||
@ -110,306 +119,377 @@ XPC_XOW_ClassNeedsXOW(const char *name)
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
extern JSExtendedClass sXPC_COW_JSClass;
|
||||
extern JSExtendedClass sXPC_SJOW_JSClass;
|
||||
extern JSExtendedClass sXPC_SOW_JSClass;
|
||||
extern JSExtendedClass sXPC_XOW_JSClass;
|
||||
} // namespace XPCCrossOriginWrapper
|
||||
|
||||
// This class wraps some common functionality between the three existing
|
||||
namespace ChromeObjectWrapper {
|
||||
|
||||
JSBool
|
||||
WrapObject(JSContext *cx, JSObject *parent, jsval v, jsval *vp);
|
||||
|
||||
}
|
||||
|
||||
namespace XPCSafeJSObjectWrapper {
|
||||
|
||||
JSObject *
|
||||
GetUnsafeObject(JSObject *obj);
|
||||
|
||||
JSBool
|
||||
WrapObject(JSContext *cx, JSObject *scope, jsval v, jsval *vp);
|
||||
|
||||
PRBool
|
||||
AttachNewConstructorObject(XPCCallContext &ccx, JSObject *aGlobalObject);
|
||||
|
||||
}
|
||||
|
||||
namespace SystemOnlyWrapper {
|
||||
|
||||
JSBool
|
||||
WrapObject(JSContext *cx, JSObject *parent, jsval v, jsval *vp);
|
||||
|
||||
// Used by UnwrapSOW below.
|
||||
JSBool
|
||||
AllowedToAct(JSContext *cx, jsval idval);
|
||||
|
||||
}
|
||||
|
||||
namespace ChromeObjectWrapper { extern JSExtendedClass COWClass; }
|
||||
namespace XPCSafeJSObjectWrapper { extern JSExtendedClass SJOWClass; }
|
||||
namespace SystemOnlyWrapper { extern JSExtendedClass SOWClass; }
|
||||
namespace XPCCrossOriginWrapper { extern JSExtendedClass XOWClass; }
|
||||
|
||||
extern nsIScriptSecurityManager *gScriptSecurityManager;
|
||||
|
||||
// This namespace wraps some common functionality between the three existing
|
||||
// wrappers. Its main purpose is to allow XPCCrossOriginWrapper to act both
|
||||
// as an XPCSafeSJSObjectWrapper and as an XPCNativeWrapper when required to
|
||||
// as an XPCSafeJSObjectWrapper and as an XPCNativeWrapper when required to
|
||||
// do so (the decision is based on the principals of the wrapper and wrapped
|
||||
// objects).
|
||||
class XPCWrapper
|
||||
namespace XPCWrapper {
|
||||
|
||||
// FLAG_RESOLVING is used to tag a wrapper when while it's calling
|
||||
// the newResolve. It tells the addProperty hook to not worry about
|
||||
// what's being defined.
|
||||
extern const PRUint32 FLAG_RESOLVING;
|
||||
|
||||
// This is used by individual wrappers as a starting point to stick
|
||||
// per-wrapper flags into the flags slot. This is guaranteed to only
|
||||
// have one bit set.
|
||||
extern const PRUint32 LAST_FLAG;
|
||||
|
||||
inline JSBool
|
||||
HAS_FLAGS(jsval v, PRUint32 flags)
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Used by the cross origin and safe wrappers: the slot that the wrapped
|
||||
* object is held in.
|
||||
*/
|
||||
static const PRUint32 sWrappedObjSlot;
|
||||
return (PRUint32(JSVAL_TO_INT(v)) & flags) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Used by all wrappers to store flags about their state. For example,
|
||||
* it is used when resolving a property to tell to the addProperty hook
|
||||
* that it shouldn't perform any security checks.
|
||||
*/
|
||||
static const PRUint32 sFlagsSlot;
|
||||
/**
|
||||
* Used by the cross origin and safe wrappers: the slot that the wrapped
|
||||
* object is held in.
|
||||
*/
|
||||
extern const PRUint32 sWrappedObjSlot;
|
||||
|
||||
/**
|
||||
* The base number of slots needed by code using the above constants.
|
||||
*/
|
||||
static const PRUint32 sNumSlots;
|
||||
/**
|
||||
* Used by all wrappers to store flags about their state. For example,
|
||||
* it is used when resolving a property to tell to the addProperty hook
|
||||
* that it shouldn't perform any security checks.
|
||||
*/
|
||||
extern const PRUint32 sFlagsSlot;
|
||||
|
||||
/**
|
||||
* Cross origin wrappers and safe JSObject wrappers both need to know
|
||||
* which native is 'eval' for various purposes.
|
||||
*/
|
||||
static JSNative sEvalNative;
|
||||
/**
|
||||
* The base number of slots needed by code using the above constants.
|
||||
*/
|
||||
extern const PRUint32 sNumSlots;
|
||||
|
||||
enum FunctionObjectSlot {
|
||||
eWrappedFunctionSlot = 0,
|
||||
eAllAccessSlot = 1
|
||||
};
|
||||
/**
|
||||
* Cross origin wrappers and safe JSObject wrappers both need to know
|
||||
* which native is 'eval' for various purposes.
|
||||
*/
|
||||
extern JSNative sEvalNative;
|
||||
|
||||
// Helpful for keeping lines short:
|
||||
static const PRUint32 sSecMgrSetProp, sSecMgrGetProp;
|
||||
|
||||
/**
|
||||
* Given a context and a global object, fill our eval native.
|
||||
*/
|
||||
static JSBool FindEval(XPCCallContext &ccx, JSObject *obj) {
|
||||
if (sEvalNative) {
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
jsval eval_val;
|
||||
if (!::JS_GetProperty(ccx, obj, "eval", &eval_val)) {
|
||||
return ThrowException(NS_ERROR_UNEXPECTED, ccx);
|
||||
}
|
||||
|
||||
if (JSVAL_IS_PRIMITIVE(eval_val) ||
|
||||
!::JS_ObjectIsFunction(ccx, JSVAL_TO_OBJECT(eval_val))) {
|
||||
return ThrowException(NS_ERROR_UNEXPECTED, ccx);
|
||||
}
|
||||
|
||||
sEvalNative =
|
||||
::JS_GetFunctionNative(ccx, ::JS_ValueToFunction(ccx, eval_val));
|
||||
|
||||
if (!sEvalNative) {
|
||||
return ThrowException(NS_ERROR_UNEXPECTED, ccx);
|
||||
}
|
||||
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* A useful function that throws an exception onto cx.
|
||||
*/
|
||||
static JSBool ThrowException(nsresult ex, JSContext *cx) {
|
||||
XPCThrower::Throw(ex, cx);
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the script security manager used by XPConnect.
|
||||
*/
|
||||
static nsIScriptSecurityManager *GetSecurityManager() {
|
||||
extern nsIScriptSecurityManager *gScriptSecurityManager;
|
||||
|
||||
return gScriptSecurityManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to ensure that an XPCWrappedNative stays alive when its scriptable
|
||||
* helper defines an "expando" property on it.
|
||||
*/
|
||||
static JSBool MaybePreserveWrapper(JSContext *cx, XPCWrappedNative *wn,
|
||||
uintN flags) {
|
||||
if ((flags & JSRESOLVE_ASSIGNING) &&
|
||||
(::JS_GetOptions(cx) & JSOPTION_PRIVATE_IS_NSISUPPORTS)) {
|
||||
nsCOMPtr<nsIXPCScriptNotify> scriptNotify =
|
||||
do_QueryInterface(static_cast<nsISupports*>
|
||||
(JS_GetContextPrivate(cx)));
|
||||
if (scriptNotify) {
|
||||
return NS_SUCCEEDED(scriptNotify->PreserveWrapper(wn));
|
||||
}
|
||||
}
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
static JSBool IsSecurityWrapper(JSObject *wrapper)
|
||||
{
|
||||
JSClass *clasp = STOBJ_GET_CLASS(wrapper);
|
||||
return (clasp->flags & JSCLASS_IS_EXTENDED) &&
|
||||
((JSExtendedClass*)clasp)->wrappedObject;
|
||||
}
|
||||
|
||||
/**
|
||||
* Given an arbitrary object, Unwrap will return the wrapped object if the
|
||||
* passed-in object is a wrapper that Unwrap knows about *and* the
|
||||
* currently running code has permission to access both the wrapper and
|
||||
* wrapped object.
|
||||
*
|
||||
* Since this is meant to be called from functions like
|
||||
* XPCWrappedNative::GetWrappedNativeOfJSObject, it does not set an
|
||||
* exception on |cx|.
|
||||
*/
|
||||
static JSObject *Unwrap(JSContext *cx, JSObject *wrapper);
|
||||
|
||||
/**
|
||||
* Unwraps objects whose class is |xclasp|.
|
||||
*/
|
||||
static JSObject *UnwrapGeneric(JSContext *cx, const JSExtendedClass *xclasp,
|
||||
JSObject *wrapper)
|
||||
{
|
||||
if (STOBJ_GET_CLASS(wrapper) != &xclasp->base) {
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
jsval v;
|
||||
if (!JS_GetReservedSlot(cx, wrapper, XPCWrapper::sWrappedObjSlot, &v)) {
|
||||
JS_ClearPendingException(cx);
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
if (JSVAL_IS_PRIMITIVE(v)) {
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
return JSVAL_TO_OBJECT(v);
|
||||
}
|
||||
|
||||
static JSObject *UnwrapSOW(JSContext *cx, JSObject *wrapper) {
|
||||
wrapper = UnwrapGeneric(cx, &sXPC_SOW_JSClass, wrapper);
|
||||
if (!wrapper) {
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
if (!AllowedToAct(cx, JSVAL_VOID)) {
|
||||
JS_ClearPendingException(cx);
|
||||
wrapper = nsnull;
|
||||
}
|
||||
|
||||
return wrapper;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unwraps a XOW into its wrapped native.
|
||||
*/
|
||||
static JSObject *UnwrapXOW(JSContext *cx, JSObject *wrapper) {
|
||||
wrapper = UnwrapGeneric(cx, &sXPC_XOW_JSClass, wrapper);
|
||||
if (!wrapper) {
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
nsresult rv = CanAccessWrapper(cx, wrapper, nsnull);
|
||||
if (NS_FAILED(rv)) {
|
||||
JS_ClearPendingException(cx);
|
||||
wrapper = nsnull;
|
||||
}
|
||||
|
||||
return wrapper;
|
||||
}
|
||||
|
||||
static JSObject *UnwrapCOW(JSContext *cx, JSObject *wrapper) {
|
||||
wrapper = UnwrapGeneric(cx, &sXPC_COW_JSClass, wrapper);
|
||||
if (!wrapper) {
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
nsresult rv = CanAccessWrapper(cx, wrapper, nsnull);
|
||||
if (NS_FAILED(rv)) {
|
||||
JS_ClearPendingException(cx);
|
||||
wrapper = nsnull;
|
||||
}
|
||||
|
||||
return wrapper;
|
||||
}
|
||||
|
||||
/**
|
||||
* Rewraps a property if it needs to be rewrapped. Used by
|
||||
* GetOrSetNativeProperty to rewrap the return value.
|
||||
*/
|
||||
static JSBool RewrapIfDeepWrapper(JSContext *cx, JSObject *obj, jsval v,
|
||||
jsval *rval, JSBool isNativeWrapper) {
|
||||
*rval = v;
|
||||
return isNativeWrapper
|
||||
? XPC_NW_RewrapIfDeepWrapper(cx, obj, v, rval)
|
||||
: XPC_XOW_RewrapIfNeeded(cx, obj, rval);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a wrapper around a JSObject function object. Note
|
||||
* XPCSafeJSObjectWrapper code doesn't have special function wrappers,
|
||||
* obviating the need for this function. Instead, this is used by
|
||||
* XPCNativeWrapper and the cross origin wrapper.
|
||||
*/
|
||||
static inline JSBool WrapFunction(JSContext *cx, JSObject *wrapperObj,
|
||||
JSObject *funobj, jsval *v,
|
||||
JSBool isNativeWrapper) {
|
||||
return isNativeWrapper
|
||||
? XPC_NW_WrapFunction(cx, funobj, v)
|
||||
: XPC_XOW_WrapFunction(cx, wrapperObj, funobj, v);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an iterator object that walks up the prototype of
|
||||
* wrappedObj. This is suitable for for-in loops over a wrapper. If
|
||||
* a property is not supposed to be reflected, the resolve hook
|
||||
* is expected to censor it. tempWrapper must be rooted already.
|
||||
*/
|
||||
static JSObject *CreateIteratorObj(JSContext *cx,
|
||||
JSObject *tempWrapper,
|
||||
JSObject *wrapperObj,
|
||||
JSObject *innerObj,
|
||||
JSBool keysonly);
|
||||
|
||||
/**
|
||||
* Called for the common part of adding a property to obj.
|
||||
*/
|
||||
static JSBool AddProperty(JSContext *cx, JSObject *wrapperObj,
|
||||
JSBool wantGetterSetter, JSObject *innerObj,
|
||||
jsval id, jsval *vp);
|
||||
|
||||
/**
|
||||
* Called for the common part of deleting a property from obj.
|
||||
*/
|
||||
static JSBool DelProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp);
|
||||
|
||||
/**
|
||||
* Called to enumerate the properties of |innerObj| onto |wrapperObj|.
|
||||
*/
|
||||
static JSBool Enumerate(JSContext *cx, JSObject *wrapperObj,
|
||||
JSObject *innerObj);
|
||||
|
||||
/**
|
||||
* Resolves a property (that may be) defined on |innerObj| onto
|
||||
* |wrapperObj|. This will also resolve random, page-defined objects
|
||||
* and is therefore unsuitable for cross-origin resolution.
|
||||
*/
|
||||
static JSBool NewResolve(JSContext *cx, JSObject *wrapperObj,
|
||||
JSBool preserveVal, JSObject *innerObj,
|
||||
jsval id, uintN flags, JSObject **objp);
|
||||
|
||||
/**
|
||||
* Resolve a native property named id from innerObj onto wrapperObj. The
|
||||
* native wrapper will be preserved if necessary. Note that if we resolve
|
||||
* an attribute here, we don't deal with the value until later.
|
||||
*/
|
||||
static JSBool ResolveNativeProperty(JSContext *cx, JSObject *wrapperObj,
|
||||
JSObject *innerObj, XPCWrappedNative *wn,
|
||||
jsval id, uintN flags, JSObject **objp,
|
||||
JSBool isNativeWrapper);
|
||||
|
||||
/**
|
||||
* Gets a native property from obj. This goes directly through XPConnect, it
|
||||
* does not look at Javascript-defined getters or setters. This ensures that
|
||||
* the caller gets a real answer.
|
||||
*/
|
||||
static JSBool GetOrSetNativeProperty(JSContext *cx, JSObject *obj,
|
||||
XPCWrappedNative *wrappedNative,
|
||||
jsval id, jsval *vp, JSBool aIsSet,
|
||||
JSBool isNativeWrapper);
|
||||
|
||||
/**
|
||||
* Gets a string representation of wrappedNative, going through IDL.
|
||||
*/
|
||||
static JSBool NativeToString(JSContext *cx, XPCWrappedNative *wrappedNative,
|
||||
uintN argc, jsval *argv, jsval *rval,
|
||||
JSBool isNativeWrapper);
|
||||
|
||||
/**
|
||||
* Looks up a property on obj. If it exists, then the parameters are filled
|
||||
* in with useful values.
|
||||
*
|
||||
* NB: All parameters must be initialized before the call.
|
||||
*/
|
||||
static JSBool GetPropertyAttrs(JSContext *cx, JSObject *obj,
|
||||
jsid interned_id, uintN flags,
|
||||
JSBool wantDetails,
|
||||
JSPropertyDescriptor *desc);
|
||||
enum FunctionObjectSlot {
|
||||
eWrappedFunctionSlot = 0,
|
||||
eAllAccessSlot = 1
|
||||
};
|
||||
|
||||
// Helpful for keeping lines short:
|
||||
extern const PRUint32 sSecMgrSetProp, sSecMgrGetProp;
|
||||
|
||||
/**
|
||||
* A useful function that throws an exception onto cx.
|
||||
*/
|
||||
inline JSBool
|
||||
DoThrowException(nsresult ex, JSContext *cx)
|
||||
{
|
||||
XPCThrower::Throw(ex, cx);
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a context and a global object, fill our eval native.
|
||||
*/
|
||||
inline JSBool
|
||||
FindEval(XPCCallContext &ccx, JSObject *obj)
|
||||
{
|
||||
if (sEvalNative) {
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
jsval eval_val;
|
||||
if (!::JS_GetProperty(ccx, obj, "eval", &eval_val)) {
|
||||
return DoThrowException(NS_ERROR_UNEXPECTED, ccx);
|
||||
}
|
||||
|
||||
if (JSVAL_IS_PRIMITIVE(eval_val) ||
|
||||
!::JS_ObjectIsFunction(ccx, JSVAL_TO_OBJECT(eval_val))) {
|
||||
return DoThrowException(NS_ERROR_UNEXPECTED, ccx);
|
||||
}
|
||||
|
||||
sEvalNative =
|
||||
::JS_GetFunctionNative(ccx, ::JS_ValueToFunction(ccx, eval_val));
|
||||
|
||||
if (!sEvalNative) {
|
||||
return DoThrowException(NS_ERROR_UNEXPECTED, ccx);
|
||||
}
|
||||
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the script security manager used by XPConnect.
|
||||
*/
|
||||
inline nsIScriptSecurityManager *
|
||||
GetSecurityManager()
|
||||
{
|
||||
return ::gScriptSecurityManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to ensure that an XPCWrappedNative stays alive when its scriptable
|
||||
* helper defines an "expando" property on it.
|
||||
*/
|
||||
inline JSBool
|
||||
MaybePreserveWrapper(JSContext *cx, XPCWrappedNative *wn, uintN flags)
|
||||
{
|
||||
if ((flags & JSRESOLVE_ASSIGNING) &&
|
||||
(::JS_GetOptions(cx) & JSOPTION_PRIVATE_IS_NSISUPPORTS)) {
|
||||
nsCOMPtr<nsIXPCScriptNotify> scriptNotify =
|
||||
do_QueryInterface(static_cast<nsISupports*>
|
||||
(JS_GetContextPrivate(cx)));
|
||||
if (scriptNotify) {
|
||||
return NS_SUCCEEDED(scriptNotify->PreserveWrapper(wn));
|
||||
}
|
||||
}
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
inline JSBool
|
||||
IsSecurityWrapper(JSObject *wrapper)
|
||||
{
|
||||
JSClass *clasp = STOBJ_GET_CLASS(wrapper);
|
||||
return (clasp->flags & JSCLASS_IS_EXTENDED) &&
|
||||
((JSExtendedClass*)clasp)->wrappedObject;
|
||||
}
|
||||
|
||||
/**
|
||||
* Given an arbitrary object, Unwrap will return the wrapped object if the
|
||||
* passed-in object is a wrapper that Unwrap knows about *and* the
|
||||
* currently running code has permission to access both the wrapper and
|
||||
* wrapped object.
|
||||
*
|
||||
* Since this is meant to be called from functions like
|
||||
* XPCWrappedNative::GetWrappedNativeOfJSObject, it does not set an
|
||||
* exception on |cx|.
|
||||
*/
|
||||
JSObject *
|
||||
Unwrap(JSContext *cx, JSObject *wrapper);
|
||||
|
||||
/**
|
||||
* Unwraps objects whose class is |xclasp|.
|
||||
*/
|
||||
inline JSObject *
|
||||
UnwrapGeneric(JSContext *cx, const JSExtendedClass *xclasp, JSObject *wrapper)
|
||||
{
|
||||
if (STOBJ_GET_CLASS(wrapper) != &xclasp->base) {
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
jsval v;
|
||||
if (!JS_GetReservedSlot(cx, wrapper, XPCWrapper::sWrappedObjSlot, &v)) {
|
||||
JS_ClearPendingException(cx);
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
if (JSVAL_IS_PRIMITIVE(v)) {
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
return JSVAL_TO_OBJECT(v);
|
||||
}
|
||||
|
||||
inline JSObject *
|
||||
UnwrapSOW(JSContext *cx, JSObject *wrapper)
|
||||
{
|
||||
wrapper = UnwrapGeneric(cx, &SystemOnlyWrapper::SOWClass, wrapper);
|
||||
if (!wrapper) {
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
if (!SystemOnlyWrapper::AllowedToAct(cx, JSVAL_VOID)) {
|
||||
JS_ClearPendingException(cx);
|
||||
wrapper = nsnull;
|
||||
}
|
||||
|
||||
return wrapper;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unwraps a XOW into its wrapped native.
|
||||
*/
|
||||
inline JSObject *
|
||||
UnwrapXOW(JSContext *cx, JSObject *wrapper)
|
||||
{
|
||||
wrapper = UnwrapGeneric(cx, &XPCCrossOriginWrapper::XOWClass, wrapper);
|
||||
if (!wrapper) {
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
nsresult rv = XPCCrossOriginWrapper::CanAccessWrapper(cx, wrapper, nsnull);
|
||||
if (NS_FAILED(rv)) {
|
||||
JS_ClearPendingException(cx);
|
||||
wrapper = nsnull;
|
||||
}
|
||||
|
||||
return wrapper;
|
||||
}
|
||||
|
||||
inline JSObject *
|
||||
UnwrapCOW(JSContext *cx, JSObject *wrapper)
|
||||
{
|
||||
wrapper = UnwrapGeneric(cx, &ChromeObjectWrapper::COWClass, wrapper);
|
||||
if (!wrapper) {
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
nsresult rv = XPCCrossOriginWrapper::CanAccessWrapper(cx, wrapper, nsnull);
|
||||
if (NS_FAILED(rv)) {
|
||||
JS_ClearPendingException(cx);
|
||||
wrapper = nsnull;
|
||||
}
|
||||
|
||||
return wrapper;
|
||||
}
|
||||
|
||||
/**
|
||||
* Rewraps a property if it needs to be rewrapped. Used by
|
||||
* GetOrSetNativeProperty to rewrap the return value.
|
||||
*/
|
||||
inline JSBool
|
||||
RewrapIfDeepWrapper(JSContext *cx, JSObject *obj, jsval v, jsval *rval,
|
||||
JSBool isNativeWrapper)
|
||||
{
|
||||
*rval = v;
|
||||
return isNativeWrapper
|
||||
? XPCNativeWrapper::RewrapIfDeepWrapper(cx, obj, v, rval)
|
||||
: XPCCrossOriginWrapper::RewrapIfNeeded(cx, obj, rval);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a wrapper around a JSObject function object. Note
|
||||
* XPCSafeJSObjectWrapper code doesn't have special function wrappers,
|
||||
* obviating the need for this function. Instead, this is used by
|
||||
* XPCNativeWrapper and the cross origin wrapper.
|
||||
*/
|
||||
inline JSBool
|
||||
WrapFunction(JSContext *cx, JSObject *wrapperObj, JSObject *funobj, jsval *v,
|
||||
JSBool isNativeWrapper)
|
||||
{
|
||||
return isNativeWrapper
|
||||
? XPCNativeWrapper::WrapFunction(cx, funobj, v)
|
||||
: XPCCrossOriginWrapper::WrapFunction(cx, wrapperObj, funobj, v);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an iterator object that walks up the prototype of
|
||||
* wrappedObj. This is suitable for for-in loops over a wrapper. If
|
||||
* a property is not supposed to be reflected, the resolve hook
|
||||
* is expected to censor it. tempWrapper must be rooted already.
|
||||
*/
|
||||
JSObject *
|
||||
CreateIteratorObj(JSContext *cx, JSObject *tempWrapper,
|
||||
JSObject *wrapperObj, JSObject *innerObj,
|
||||
JSBool keysonly);
|
||||
|
||||
/**
|
||||
* Called for the common part of adding a property to obj.
|
||||
*/
|
||||
JSBool
|
||||
AddProperty(JSContext *cx, JSObject *wrapperObj,
|
||||
JSBool wantGetterSetter, JSObject *innerObj,
|
||||
jsval id, jsval *vp);
|
||||
|
||||
/**
|
||||
* Called for the common part of deleting a property from obj.
|
||||
*/
|
||||
JSBool
|
||||
DelProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp);
|
||||
|
||||
/**
|
||||
* Called to enumerate the properties of |innerObj| onto |wrapperObj|.
|
||||
*/
|
||||
JSBool
|
||||
Enumerate(JSContext *cx, JSObject *wrapperObj, JSObject *innerObj);
|
||||
|
||||
/**
|
||||
* Resolves a property (that may be) defined on |innerObj| onto
|
||||
* |wrapperObj|. This will also resolve random, page-defined objects
|
||||
* and is therefore unsuitable for cross-origin resolution.
|
||||
*/
|
||||
JSBool
|
||||
NewResolve(JSContext *cx, JSObject *wrapperObj,
|
||||
JSBool preserveVal, JSObject *innerObj,
|
||||
jsval id, uintN flags, JSObject **objp);
|
||||
|
||||
/**
|
||||
* Resolve a native property named id from innerObj onto wrapperObj. The
|
||||
* native wrapper will be preserved if necessary. Note that if we resolve
|
||||
* an attribute here, we don't deal with the value until later.
|
||||
*/
|
||||
JSBool
|
||||
ResolveNativeProperty(JSContext *cx, JSObject *wrapperObj,
|
||||
JSObject *innerObj, XPCWrappedNative *wn,
|
||||
jsval id, uintN flags, JSObject **objp,
|
||||
JSBool isNativeWrapper);
|
||||
|
||||
/**
|
||||
* Gets a native property from obj. This goes directly through XPConnect, it
|
||||
* does not look at Javascript-defined getters or setters. This ensures that
|
||||
* the caller gets a real answer.
|
||||
*/
|
||||
JSBool
|
||||
GetOrSetNativeProperty(JSContext *cx, JSObject *obj,
|
||||
XPCWrappedNative *wrappedNative,
|
||||
jsval id, jsval *vp, JSBool aIsSet,
|
||||
JSBool isNativeWrapper);
|
||||
|
||||
/**
|
||||
* Gets a string representation of wrappedNative, going through IDL.
|
||||
*/
|
||||
JSBool
|
||||
NativeToString(JSContext *cx, XPCWrappedNative *wrappedNative,
|
||||
uintN argc, jsval *argv, jsval *rval,
|
||||
JSBool isNativeWrapper);
|
||||
|
||||
/**
|
||||
* Looks up a property on obj. If it exists, then the parameters are filled
|
||||
* in with useful values.
|
||||
*
|
||||
* NB: All parameters must be initialized before the call.
|
||||
*/
|
||||
JSBool
|
||||
GetPropertyAttrs(JSContext *cx, JSObject *obj, jsid interned_id, uintN flags,
|
||||
JSBool wantDetails, JSPropertyDescriptor *desc);
|
||||
|
||||
} // namespace XPCWrapper
|
||||
|
||||
|
||||
#endif
|
||||
|
@ -1068,7 +1068,7 @@ nsXPConnect::InitClasses(JSContext * aJSContext, JSObject * aGlobalJSObj)
|
||||
if (!XPCNativeWrapper::AttachNewConstructorObject(ccx, aGlobalJSObj))
|
||||
return UnexpectedFailure(NS_ERROR_FAILURE);
|
||||
|
||||
if (!XPC_SJOW_AttachNewConstructorObject(ccx, aGlobalJSObj))
|
||||
if (!XPCSafeJSObjectWrapper::AttachNewConstructorObject(ccx, aGlobalJSObj))
|
||||
return UnexpectedFailure(NS_ERROR_FAILURE);
|
||||
}
|
||||
|
||||
@ -1206,7 +1206,7 @@ nsXPConnect::InitClassesWithNewWrappedGlobal(JSContext * aJSContext,
|
||||
if(!XPCNativeWrapper::AttachNewConstructorObject(ccx, globalJSObj))
|
||||
return UnexpectedFailure(NS_ERROR_FAILURE);
|
||||
|
||||
if(!XPC_SJOW_AttachNewConstructorObject(ccx, globalJSObj))
|
||||
if(!XPCSafeJSObjectWrapper::AttachNewConstructorObject(ccx, globalJSObj))
|
||||
return UnexpectedFailure(NS_ERROR_FAILURE);
|
||||
}
|
||||
}
|
||||
@ -2049,7 +2049,7 @@ nsXPConnect::GetXOWForObject(JSContext * aJSContext,
|
||||
jsval * rval)
|
||||
{
|
||||
*rval = OBJECT_TO_JSVAL(aWrappedObj);
|
||||
return XPC_XOW_WrapObject(aJSContext, aParent, rval)
|
||||
return XPCCrossOriginWrapper::WrapObject(aJSContext, aParent, rval)
|
||||
? NS_OK : NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
@ -2060,7 +2060,7 @@ nsXPConnect::GetCOWForObject(JSContext * aJSContext,
|
||||
jsval * rval)
|
||||
{
|
||||
*rval = OBJECT_TO_JSVAL(aWrappedObj);
|
||||
return XPC_COW_WrapObject(aJSContext, aParent, *rval, rval)
|
||||
return ChromeObjectWrapper::WrapObject(aJSContext, aParent, *rval, rval)
|
||||
? NS_OK : NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
@ -2458,7 +2458,8 @@ nsXPConnect::GetWrapperForObject(JSContext* aJSContext,
|
||||
|
||||
JSBool sameOrigin;
|
||||
JSBool sameScope = xpc_SameScope(objectscope, xpcscope, &sameOrigin);
|
||||
JSBool forceXOW = XPC_XOW_ClassNeedsXOW(STOBJ_GET_CLASS(aObject)->name);
|
||||
JSBool forceXOW =
|
||||
XPCCrossOriginWrapper::ClassNeedsXOW(STOBJ_GET_CLASS(aObject)->name);
|
||||
|
||||
// We can do nothing if:
|
||||
// - We're wrapping a system object
|
||||
@ -2491,7 +2492,7 @@ nsXPConnect::GetWrapperForObject(JSContext* aJSContext,
|
||||
else if(aFilenameFlags & JSFILENAME_SYSTEM)
|
||||
{
|
||||
jsval val = OBJECT_TO_JSVAL(aObject);
|
||||
if(XPC_SJOW_Construct(aJSContext, nsnull, 1, &val, &val))
|
||||
if(XPCSafeJSObjectWrapper::WrapObject(aJSContext, nsnull, val, &val))
|
||||
wrappedObj = JSVAL_TO_OBJECT(val);
|
||||
}
|
||||
else
|
||||
@ -2502,7 +2503,7 @@ nsXPConnect::GetWrapperForObject(JSContext* aJSContext,
|
||||
return NS_OK;
|
||||
|
||||
jsval val = OBJECT_TO_JSVAL(aObject);
|
||||
if(XPC_XOW_WrapObject(aJSContext, aScope, &val, wrapper))
|
||||
if(XPCCrossOriginWrapper::WrapObject(aJSContext, aScope, &val, wrapper))
|
||||
wrappedObj = JSVAL_TO_OBJECT(val);
|
||||
}
|
||||
|
||||
@ -2511,7 +2512,7 @@ nsXPConnect::GetWrapperForObject(JSContext* aJSContext,
|
||||
|
||||
*_retval = OBJECT_TO_JSVAL(wrappedObj);
|
||||
if(wrapper && wrapper->NeedsChromeWrapper() &&
|
||||
!XPC_SOW_WrapObject(aJSContext, aScope, *_retval, _retval))
|
||||
!SystemOnlyWrapper::WrapObject(aJSContext, aScope, *_retval, _retval))
|
||||
return NS_ERROR_FAILURE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -1362,7 +1362,7 @@ XPCConvert::NativeInterface2JSObject(XPCLazyCallContext& lccx,
|
||||
"XPCSafeJSObjectWrapper\n");
|
||||
#endif
|
||||
|
||||
if(XPC_SJOW_Construct(ccx, nsnull, 1, &v, &v))
|
||||
if(XPCSafeJSObjectWrapper::WrapObject(ccx, nsnull, v, &v))
|
||||
destObj = JSVAL_TO_OBJECT(v);
|
||||
triedWrapping = JS_TRUE;
|
||||
}
|
||||
@ -1370,7 +1370,7 @@ XPCConvert::NativeInterface2JSObject(XPCLazyCallContext& lccx,
|
||||
{
|
||||
// Reaching across scopes from content code. Wrap
|
||||
// the new object in a XOW.
|
||||
if (XPC_XOW_WrapObject(ccx, scope, &v))
|
||||
if (XPCCrossOriginWrapper::WrapObject(ccx, scope, &v))
|
||||
destObj = JSVAL_TO_OBJECT(v);
|
||||
triedWrapping = JS_TRUE;
|
||||
}
|
||||
@ -1384,9 +1384,10 @@ XPCConvert::NativeInterface2JSObject(XPCLazyCallContext& lccx,
|
||||
AUTO_MARK_JSVAL(ccx, &wrappedObjVal);
|
||||
if(wrapper->NeedsChromeWrapper())
|
||||
{
|
||||
if(!XPC_SOW_WrapObject(ccx, xpcscope->GetGlobalJSObject(),
|
||||
OBJECT_TO_JSVAL(destObj),
|
||||
&wrappedObjVal))
|
||||
using SystemOnlyWrapper::WrapObject;
|
||||
if(!WrapObject(ccx, xpcscope->GetGlobalJSObject(),
|
||||
OBJECT_TO_JSVAL(destObj),
|
||||
&wrappedObjVal))
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
@ -1400,7 +1401,7 @@ XPCConvert::NativeInterface2JSObject(XPCLazyCallContext& lccx,
|
||||
if(allowNativeWrapper &&
|
||||
!(flags & JSFILENAME_SYSTEM) &&
|
||||
!JS_IsSystemObject(ccx, flat) &&
|
||||
XPC_XOW_ClassNeedsXOW(name))
|
||||
XPCCrossOriginWrapper::ClassNeedsXOW(name))
|
||||
{
|
||||
// From here on we might create new JSObjects, so we need to
|
||||
// make sure that wrapper stays alive.
|
||||
@ -1408,10 +1409,10 @@ XPCConvert::NativeInterface2JSObject(XPCLazyCallContext& lccx,
|
||||
strongWrapper = wrapper;
|
||||
|
||||
AUTO_MARK_JSVAL(ccx, &v);
|
||||
return XPC_XOW_WrapObject(ccx, scope, &v) &&
|
||||
return XPCCrossOriginWrapper::WrapObject(ccx, scope, &v) &&
|
||||
(!wrapper->NeedsChromeWrapper() ||
|
||||
XPC_SOW_WrapObject(ccx, xpcscope->GetGlobalJSObject(),
|
||||
v, &v)) &&
|
||||
SystemOnlyWrapper::WrapObject(ccx, xpcscope->GetGlobalJSObject(),
|
||||
v, &v)) &&
|
||||
CreateHolderIfNeeded(ccx, JSVAL_TO_OBJECT(v), d, dest);
|
||||
}
|
||||
|
||||
@ -1419,10 +1420,12 @@ XPCConvert::NativeInterface2JSObject(XPCLazyCallContext& lccx,
|
||||
if(allowNativeWrapper)
|
||||
{
|
||||
if(wrapper->NeedsChromeWrapper())
|
||||
if(!XPC_SOW_WrapObject(ccx, xpcscope->GetGlobalJSObject(), v, d))
|
||||
if(!SystemOnlyWrapper::WrapObject(ccx,
|
||||
xpcscope->GetGlobalJSObject(),
|
||||
v, d))
|
||||
return JS_FALSE;
|
||||
if(wrapper->IsDoubleWrapper())
|
||||
if(!XPC_COW_WrapObject(ccx, xpcscope->GetGlobalJSObject(), v, d))
|
||||
if(!ChromeObjectWrapper::WrapObject(ccx, xpcscope->GetGlobalJSObject(), v, d))
|
||||
return JS_FALSE;
|
||||
}
|
||||
if(dest)
|
||||
|
@ -4347,31 +4347,6 @@ xpc_SameScope(XPCWrappedNativeScope *objectscope,
|
||||
nsISupports *
|
||||
XPC_GetIdentityObject(JSContext *cx, JSObject *obj);
|
||||
|
||||
PRBool
|
||||
IsXPCSafeJSObjectWrapperClass(JSClass *clazz);
|
||||
|
||||
JSObject *
|
||||
XPC_SJOW_GetUnsafeObject(JSObject *obj);
|
||||
|
||||
JSBool
|
||||
XPC_SJOW_Construct(JSContext *cx, JSObject *obj, uintN, jsval *argv,
|
||||
jsval *rval);
|
||||
|
||||
PRBool
|
||||
XPC_SJOW_AttachNewConstructorObject(XPCCallContext &ccx,
|
||||
JSObject *aGlobalObject);
|
||||
|
||||
JSBool
|
||||
XPC_XOW_WrapObject(JSContext *cx, JSObject *parent, jsval *vp,
|
||||
XPCWrappedNative *wn = nsnull);
|
||||
|
||||
JSBool
|
||||
XPC_SOW_WrapObject(JSContext *cx, JSObject *parent, jsval v,
|
||||
jsval *vp);
|
||||
|
||||
JSBool
|
||||
XPC_COW_WrapObject(JSContext *cx, JSObject *parent, jsval v, jsval *vp);
|
||||
|
||||
#ifdef XPC_IDISPATCH_SUPPORT
|
||||
|
||||
#ifdef WINCE
|
||||
|
@ -1523,7 +1523,7 @@ XPCWrappedNative::ReparentWrapperIfFound(XPCCallContext& ccx,
|
||||
|
||||
if(wrapper)
|
||||
{
|
||||
if(!XPC_XOW_WrapperMoved(ccx, wrapper, aNewScope))
|
||||
if(!XPCCrossOriginWrapper::WrapperMoved(ccx, wrapper, aNewScope))
|
||||
{
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
@ -1736,7 +1736,7 @@ return_tearoff:
|
||||
// Protect against infinite recursion through XOWs.
|
||||
JSObject *unsafeObj;
|
||||
clazz = STOBJ_GET_CLASS(outer);
|
||||
if(clazz == &sXPC_XOW_JSClass.base &&
|
||||
if(clazz == &XPCCrossOriginWrapper::XOWClass.base &&
|
||||
(unsafeObj = XPCWrapper::UnwrapXOW(cx, outer)))
|
||||
{
|
||||
outer = unsafeObj;
|
||||
|
@ -818,7 +818,7 @@ XPC_GetIdentityObject(JSContext *cx, JSObject *obj)
|
||||
wrapper = XPCWrappedNative::GetWrappedNativeOfJSObject(cx, obj);
|
||||
|
||||
if(!wrapper) {
|
||||
JSObject *unsafeObj = XPC_SJOW_GetUnsafeObject(obj);
|
||||
JSObject *unsafeObj = XPCSafeJSObjectWrapper::GetUnsafeObject(obj);
|
||||
if(unsafeObj)
|
||||
return XPC_GetIdentityObject(cx, unsafeObj);
|
||||
|
||||
@ -853,9 +853,9 @@ XPC_WN_Equality(JSContext *cx, JSObject *obj, jsval v, JSBool *bp)
|
||||
return Throw(rv, cx);
|
||||
|
||||
if(!*bp && !JSVAL_IS_PRIMITIVE(v) &&
|
||||
IsXPCSafeJSObjectWrapperClass(STOBJ_GET_CLASS(JSVAL_TO_OBJECT(v))))
|
||||
STOBJ_GET_CLASS(JSVAL_TO_OBJECT(v)) == &XPCSafeJSObjectWrapper::SJOWClass.base)
|
||||
{
|
||||
v = OBJECT_TO_JSVAL(XPC_SJOW_GetUnsafeObject(JSVAL_TO_OBJECT(v)));
|
||||
v = OBJECT_TO_JSVAL(XPCSafeJSObjectWrapper::GetUnsafeObject(JSVAL_TO_OBJECT(v)));
|
||||
|
||||
rv = si->GetCallback()->Equality(wrapper, cx, obj, v, bp);
|
||||
if(NS_FAILED(rv))
|
||||
|
Loading…
Reference in New Issue
Block a user