Merge backout.

This commit is contained in:
Jason Orendorff 2010-07-01 20:06:55 -05:00
commit eada40c175
29 changed files with 633 additions and 1390 deletions

View File

@ -1590,7 +1590,6 @@ jsval nsDOMClassInfo::sPackages_id = JSVAL_VOID;
static const JSClass *sObjectClass = nsnull;
JSPropertyOp nsDOMClassInfo::sXPCNativeWrapperGetPropertyOp = nsnull;
JSPropertyOp nsDOMClassInfo::sXrayWrapperPropertyHolderGetPropertyOp = nsnull;
/**
* Set our JSClass pointer for the Object class
@ -1850,25 +1849,6 @@ nsDOMClassInfo::ThrowJSException(JSContext *cx, nsresult aResult)
return NS_OK;
}
// static
PRBool
nsDOMClassInfo::ObjectIsNativeWrapper(JSContext* cx, JSObject* obj)
{
#ifdef DEBUG
{
nsIScriptContext *scx = GetScriptContextFromJSContext(cx);
NS_PRECONDITION(!scx || !scx->IsContextInitialized() ||
sXPCNativeWrapperGetPropertyOp,
"Must know what the XPCNativeWrapper class GetProperty op is!");
}
#endif
JSPropertyOp op = obj->getClass()->getProperty;
return !!op && (op == sXPCNativeWrapperGetPropertyOp ||
op == sXrayWrapperPropertyHolderGetPropertyOp);
}
nsDOMClassInfo::nsDOMClassInfo(nsDOMClassInfoData* aData) : mData(aData)
{
}

View File

@ -166,25 +166,37 @@ public:
static nsresult ThrowJSException(JSContext *cx, nsresult aResult);
/**
* Get our JSClass pointer for the XPCNativeWrapper class
*/
static JSPropertyOp GetXPCNativeWrapperGetPropertyOp() {
return sXPCNativeWrapperGetPropertyOp;
}
/**
* Set our JSClass pointer for the XPCNativeWrapper class
*/
static void SetXPCNativeWrapperGetPropertyOp(JSPropertyOp getPropertyOp) {
NS_ASSERTION(!sXPCNativeWrapperGetPropertyOp,
"Double set of sXPCNativeWrapperGetPropertyOp");
sXPCNativeWrapperGetPropertyOp = getPropertyOp;
}
static JSPropertyOp GetXrayWrapperPropertyHolderGetPropertyOp() {
return sXrayWrapperPropertyHolderGetPropertyOp;
}
static PRBool ObjectIsNativeWrapper(JSContext* cx, JSObject* obj)
{
#ifdef DEBUG
{
nsIScriptContext *scx = GetScriptContextFromJSContext(cx);
static void SetXrayWrapperPropertyHolderGetPropertyOp(JSPropertyOp getPropertyOp) {
sXrayWrapperPropertyHolderGetPropertyOp = getPropertyOp;
}
NS_PRECONDITION(!scx || !scx->IsContextInitialized() ||
sXPCNativeWrapperGetPropertyOp,
"Must know what the XPCNativeWrapper class GetProperty op is!");
}
#endif
static PRBool ObjectIsNativeWrapper(JSContext* cx, JSObject* obj);
return sXPCNativeWrapperGetPropertyOp &&
::JS_GET_CLASS(cx, obj)->getProperty == sXPCNativeWrapperGetPropertyOp;
}
static nsISupports *GetNative(nsIXPConnectWrappedNative *wrapper, JSObject *obj);
@ -351,7 +363,6 @@ protected:
static jsval sPackages_id;
static JSPropertyOp sXPCNativeWrapperGetPropertyOp;
static JSPropertyOp sXrayWrapperPropertyHolderGetPropertyOp;
};

View File

@ -2631,17 +2631,12 @@ nsJSContext::InitContext(nsIScriptGlobalObject *aGlobalObject)
NS_ENSURE_SUCCESS(rv, rv);
// Now check whether we need to grab a pointer to the
// XPCNativeWrapper and XrayWrapperPropertyHolder getProperty ops.
// XPCNativeWrapper class
if (!nsDOMClassInfo::GetXPCNativeWrapperGetPropertyOp()) {
JSPropertyOp getProperty;
xpc->GetNativeWrapperGetPropertyOp(&getProperty);
nsDOMClassInfo::SetXPCNativeWrapperGetPropertyOp(getProperty);
}
if (!nsDOMClassInfo::GetXrayWrapperPropertyHolderGetPropertyOp()) {
JSPropertyOp getProperty;
xpc->GetXrayWrapperPropertyHolderGetPropertyOp(&getProperty);
nsDOMClassInfo::SetXrayWrapperPropertyHolderGetPropertyOp(getProperty);
}
} else {
// There's already a global object. We are preparing this outer window
// object for use as a real outer window (i.e. everything needs to live on

View File

@ -2085,7 +2085,7 @@ private:
* threshold when p is not null. The function takes the pointer and not
* a boolean flag to minimize the amount of code in its inlined callers.
*/
JS_FRIEND_API(void) checkMallocGCPressure(void *p);
void checkMallocGCPressure(void *p);
};
JS_ALWAYS_INLINE JSObject *
@ -2806,7 +2806,7 @@ js_ReportOutOfScriptQuota(JSContext *cx);
extern void
js_ReportOverRecursed(JSContext *cx);
extern JS_FRIEND_API(void)
extern void
js_ReportAllocationOverflow(JSContext *cx);
#define JS_CHECK_RECURSION(cx, onerror) \

View File

@ -698,7 +698,7 @@ struct JSObject {
inline void dropProperty(JSContext *cx, JSProperty *prop);
JS_FRIEND_API(JSCompartment *) getCompartment(JSContext *cx);
JSCompartment *getCompartment(JSContext *cx);
void swap(JSObject *obj);
@ -721,8 +721,10 @@ struct JSObject {
inline bool isObjectProxy() const;
inline bool isFunctionProxy() const;
JS_FRIEND_API(bool) isWrapper() const;
JS_FRIEND_API(JSObject *) unwrap(uintN *flagsp = NULL);
bool isWrapper() const;
JSObject *unwrap();
bool isCrossCompartmentWrapper() const;
inline bool unbrand(JSContext *cx);
};

View File

@ -68,21 +68,21 @@ class JSProxyHandler {
virtual bool fix(JSContext *cx, JSObject *proxy, jsval *vp) = 0;
/* ES5 Harmony derived proxy traps. */
virtual JS_FRIEND_API(bool) has(JSContext *cx, JSObject *proxy, jsid id, bool *bp);
virtual JS_FRIEND_API(bool) hasOwn(JSContext *cx, JSObject *proxy, jsid id, bool *bp);
virtual JS_FRIEND_API(bool) get(JSContext *cx, JSObject *proxy, JSObject *receiver, jsid id, jsval *vp);
virtual JS_FRIEND_API(bool) set(JSContext *cx, JSObject *proxy, JSObject *receiver, jsid id, jsval *vp);
virtual JS_FRIEND_API(bool) enumerateOwn(JSContext *cx, JSObject *proxy, js::AutoValueVector &props);
virtual JS_FRIEND_API(bool) iterate(JSContext *cx, JSObject *proxy, uintN flags, jsval *vp);
virtual bool has(JSContext *cx, JSObject *proxy, jsid id, bool *bp);
virtual bool hasOwn(JSContext *cx, JSObject *proxy, jsid id, bool *bp);
virtual bool get(JSContext *cx, JSObject *proxy, JSObject *receiver, jsid id, jsval *vp);
virtual bool set(JSContext *cx, JSObject *proxy, JSObject *receiver, jsid id, jsval *vp);
virtual bool enumerateOwn(JSContext *cx, JSObject *proxy, js::AutoValueVector &props);
virtual bool iterate(JSContext *cx, JSObject *proxy, uintN flags, jsval *vp);
/* Spidermonkey extensions. */
virtual JS_FRIEND_API(bool) call(JSContext *cx, JSObject *proxy, uintN argc, jsval *vp);
virtual JS_FRIEND_API(bool) construct(JSContext *cx, JSObject *proxy, JSObject *receiver,
uintN argc, jsval *argv, jsval *rval);
virtual JS_FRIEND_API(JSString *) obj_toString(JSContext *cx, JSObject *proxy);
virtual JS_FRIEND_API(JSString *) fun_toString(JSContext *cx, JSObject *proxy, uintN indent);
virtual JS_FRIEND_API(void) finalize(JSContext *cx, JSObject *proxy);
virtual JS_FRIEND_API(void) trace(JSTracer *trc, JSObject *proxy);
virtual bool call(JSContext *cx, JSObject *proxy, uintN argc, jsval *vp);
virtual bool construct(JSContext *cx, JSObject *proxy, JSObject *receiver,
uintN argc, jsval *argv, jsval *rval);
virtual JSString *obj_toString(JSContext *cx, JSObject *proxy);
virtual JSString *fun_toString(JSContext *cx, JSObject *proxy, uintN indent);
virtual void finalize(JSContext *cx, JSObject *proxy);
virtual void trace(JSTracer *trc, JSObject *proxy);
inline void *family() {
return mFamily;

View File

@ -582,7 +582,7 @@ typedef JSBool
* destination compartment.
*/
typedef JSObject *
(* JSWrapObjectCallback)(JSContext *cx, JSObject *obj, JSObject *proto, uintN flags);
(* JSWrapObjectCallback)(JSContext *cx, JSObject *obj, JSObject *proto);
JS_END_EXTERN_C

View File

@ -59,20 +59,15 @@ JSObject::isWrapper() const
}
JSObject *
JSObject::unwrap(uintN *flagsp)
JSObject::unwrap()
{
JSObject *wrapped = this;
uintN flags = 0;
if (wrapped->isWrapper()) {
flags |= static_cast<JSWrapper *>(wrapped->getProxyHandler())->flags();
while (wrapped->isWrapper())
wrapped = JSVAL_TO_OBJECT(wrapped->getProxyPrivate());
}
if (flagsp)
*flagsp = flags;
return wrapped;
}
JSWrapper::JSWrapper(uintN flags) : JSProxyHandler(&sWrapperFamily), mFlags(flags)
JSWrapper::JSWrapper(void *kind) : JSProxyHandler(&sWrapperFamily), mKind(kind)
{
}
@ -80,195 +75,116 @@ JSWrapper::~JSWrapper()
{
}
#define CHECKED(op, set) \
JS_BEGIN_MACRO \
if (!enter(cx, wrapper, id, set)) \
return false; \
bool ok = (op); \
leave(cx, wrapper); \
return ok; \
JS_END_MACRO
#define SET(action) CHECKED(action, true)
#define GET(action) CHECKED(action, false)
bool
JSWrapper::getPropertyDescriptor(JSContext *cx, JSObject *wrapper, jsid id,
JSWrapper::getPropertyDescriptor(JSContext *cx, JSObject *proxy, jsid id,
JSPropertyDescriptor *desc)
{
GET(JS_GetPropertyDescriptorById(cx, wrappedObject(wrapper), id, JSRESOLVE_QUALIFIED, desc));
}
static bool
GetOwnPropertyDescriptor(JSContext *cx, JSObject *obj, jsid id, uintN flags, JSPropertyDescriptor *desc)
{
if (!JS_GetPropertyDescriptorById(cx, obj, id, flags, desc))
return false;
if (desc->obj != obj)
desc->obj = NULL;
return true;
JSObject *wobj = wrappedObject(proxy);
return JS_GetPropertyDescriptorById(cx, wobj, id, JSRESOLVE_QUALIFIED, desc);
}
bool
JSWrapper::getOwnPropertyDescriptor(JSContext *cx, JSObject *wrapper, jsid id,
JSWrapper::getOwnPropertyDescriptor(JSContext *cx, JSObject *proxy, jsid id,
JSPropertyDescriptor *desc)
{
GET(GetOwnPropertyDescriptor(cx, wrappedObject(wrapper), id, JSRESOLVE_QUALIFIED, desc));
return JS_GetPropertyDescriptorById(cx, wrappedObject(proxy), id, JSRESOLVE_QUALIFIED, desc);
}
bool
JSWrapper::defineProperty(JSContext *cx, JSObject *wrapper, jsid id,
JSWrapper::defineProperty(JSContext *cx, JSObject *proxy, jsid id,
JSPropertyDescriptor *desc)
{
SET(JS_DefinePropertyById(cx, wrappedObject(wrapper), id, desc->value,
desc->getter, desc->setter, desc->attrs));
return JS_DefinePropertyById(cx, wrappedObject(proxy), id, desc->value,
desc->getter, desc->setter, desc->attrs);
}
bool
JSWrapper::getOwnPropertyNames(JSContext *cx, JSObject *wrapper, AutoValueVector &props)
JSWrapper::getOwnPropertyNames(JSContext *cx, JSObject *proxy, AutoValueVector &props)
{
static jsid id = JSVAL_VOID;
GET(GetPropertyNames(cx, wrappedObject(wrapper), JSITER_OWNONLY | JSITER_HIDDEN, props));
return GetPropertyNames(cx, wrappedObject(proxy), JSITER_OWNONLY | JSITER_HIDDEN, props);
}
static bool
ValueToBoolean(jsval *vp, bool *bp)
bool
JSWrapper::delete_(JSContext *cx, JSObject *proxy, jsid id, bool *bp)
{
*bp = js_ValueToBoolean(*vp);
AutoValueRooter tvr(cx);
if (!JS_DeletePropertyById2(cx, wrappedObject(proxy), id, tvr.addr()))
return false;
*bp = js_ValueToBoolean(tvr.value());
return true;
}
bool
JSWrapper::delete_(JSContext *cx, JSObject *wrapper, jsid id, bool *bp)
JSWrapper::enumerate(JSContext *cx, JSObject *proxy, AutoValueVector &props)
{
jsval v;
SET(JS_DeletePropertyById2(cx, wrappedObject(wrapper), id, &v) &&
ValueToBoolean(&v, bp));
return GetPropertyNames(cx, wrappedObject(proxy), 0, props);
}
bool
JSWrapper::enumerate(JSContext *cx, JSObject *wrapper, AutoValueVector &props)
{
static jsid id = JSVAL_VOID;
GET(GetPropertyNames(cx, wrappedObject(wrapper), 0, props));
}
bool
JSWrapper::fix(JSContext *cx, JSObject *wrapper, jsval *vp)
JSWrapper::fix(JSContext *cx, JSObject *proxy, jsval *vp)
{
*vp = JSVAL_VOID;
return true;
}
static bool
Cond(JSBool b, bool *bp)
{
*bp = !!b;
return true;
}
bool
JSWrapper::has(JSContext *cx, JSObject *wrapper, jsid id, bool *bp)
JSWrapper::has(JSContext *cx, JSObject *proxy, jsid id, bool *bp)
{
JSBool found;
GET(JS_HasPropertyById(cx, wrappedObject(wrapper), id, &found) &&
Cond(found, bp));
}
bool
JSWrapper::hasOwn(JSContext *cx, JSObject *wrapper, jsid id, bool *bp)
{
JSPropertyDescriptor desc;
JSObject *wobj = wrappedObject(wrapper);
GET(JS_GetPropertyDescriptorById(cx, wobj, id, JSRESOLVE_QUALIFIED, &desc) &&
Cond(desc.obj == wobj, bp));
}
bool
JSWrapper::get(JSContext *cx, JSObject *wrapper, JSObject *receiver, jsid id, jsval *vp)
{
GET(JS_GetPropertyById(cx, wrappedObject(wrapper), id, vp));
}
bool
JSWrapper::set(JSContext *cx, JSObject *wrapper, JSObject *receiver, jsid id, jsval *vp)
{
SET(JS_SetPropertyById(cx, wrappedObject(wrapper), id, vp));
}
bool
JSWrapper::enumerateOwn(JSContext *cx, JSObject *wrapper, AutoValueVector &props)
{
const jsid id = JSVAL_VOID;
GET(GetPropertyNames(cx, wrappedObject(wrapper), JSITER_OWNONLY, props));
}
bool
JSWrapper::iterate(JSContext *cx, JSObject *wrapper, uintN flags, jsval *vp)
{
const jsid id = JSVAL_VOID;
GET(GetIterator(cx, wrappedObject(wrapper), flags, vp));
}
bool
JSWrapper::call(JSContext *cx, JSObject *wrapper, uintN argc, jsval *vp)
{
const jsid id = JSVAL_VOID;
GET(JSProxyHandler::call(cx, wrapper, argc, vp));
}
bool
JSWrapper::construct(JSContext *cx, JSObject *wrapper, JSObject *receiver,
uintN argc, jsval *argv, jsval *rval)
{
const jsid id = JSVAL_VOID;
GET(JSProxyHandler::construct(cx, wrapper, receiver, argc, argv, rval));
}
JSString *
JSWrapper::obj_toString(JSContext *cx, JSObject *wrapper)
{
JSString *str;
if (!enter(cx, wrapper, JSVAL_VOID, false))
return NULL;
str = JSProxyHandler::obj_toString(cx, wrapper);
leave(cx, wrapper);
return str;
}
JSString *
JSWrapper::fun_toString(JSContext *cx, JSObject *wrapper, uintN indent)
{
JSString *str;
if (!enter(cx, wrapper, JSVAL_VOID, false))
return NULL;
str = JSProxyHandler::fun_toString(cx, wrapper, indent);
leave(cx, wrapper);
return str;
}
void
JSWrapper::trace(JSTracer *trc, JSObject *wrapper)
{
JS_CALL_OBJECT_TRACER(trc, wrappedObject(wrapper), "wrappedObject");
}
bool
JSWrapper::enter(JSContext *cx, JSObject *wrapper, jsval id, bool set)
{
if (!JS_HasPropertyById(cx, wrappedObject(proxy), id, &found))
return false;
*bp = !!found;
return true;
}
void
JSWrapper::leave(JSContext *cx, JSObject *wrapper)
bool
JSWrapper::hasOwn(JSContext *cx, JSObject *proxy, jsid id, bool *bp)
{
JSPropertyDescriptor desc;
JSObject *wobj = wrappedObject(proxy);
if (!JS_GetPropertyDescriptorById(cx, wobj, id, JSRESOLVE_QUALIFIED, &desc))
return false;
*bp = (desc.obj == wobj);
return true;
}
JSWrapper JSWrapper::singleton(0);
bool
JSWrapper::get(JSContext *cx, JSObject *proxy, JSObject *receiver, jsid id, jsval *vp)
{
return JS_GetPropertyById(cx, wrappedObject(proxy), id, vp);
}
bool
JSWrapper::set(JSContext *cx, JSObject *proxy, JSObject *receiver, jsid id, jsval *vp)
{
return JS_SetPropertyById(cx, wrappedObject(proxy), id, vp);
}
bool
JSWrapper::enumerateOwn(JSContext *cx, JSObject *proxy, AutoValueVector &props)
{
return GetPropertyNames(cx, wrappedObject(proxy), JSITER_OWNONLY, props);
}
bool
JSWrapper::iterate(JSContext *cx, JSObject *proxy, uintN flags, jsval *vp)
{
return GetIterator(cx, wrappedObject(proxy), flags, vp);
}
void
JSWrapper::trace(JSTracer *trc, JSObject *proxy)
{
JS_CALL_OBJECT_TRACER(trc, wrappedObject(proxy), "wrappedObject");
}
static int sTransparentWrapperKind;
JSWrapper JSWrapper::singleton(&sTransparentWrapperKind);
JSObject *
JSWrapper::New(JSContext *cx, JSObject *obj, JSObject *proto, JSObject *parent,
JSWrapper *handler)
JSProxyHandler *handler)
{
return NewProxyObject(cx, handler, OBJECT_TO_JSVAL(obj), proto, parent,
obj->isCallable() ? obj : NULL, NULL);
@ -279,9 +195,8 @@ JSWrapper::New(JSContext *cx, JSObject *obj, JSObject *proto, JSObject *parent,
namespace js {
extern JSObject *
TransparentObjectWrapper(JSContext *cx, JSObject *obj, JSObject *wrappedProto, uintN flags)
TransparentObjectWrapper(JSContext *cx, JSObject *obj, JSObject *wrappedProto)
{
JS_ASSERT(!obj->isWrapper());
return JSWrapper::New(cx, obj, wrappedProto, NULL, &JSCrossCompartmentWrapper::singleton);
}
@ -307,8 +222,6 @@ JSCompartment::wrap(JSContext *cx, jsval *vp)
{
JS_ASSERT(cx->compartment == this);
uintN flags = 0;
JS_CHECK_RECURSION(cx, return false);
/* Only GC things have to be wrapped or copied. */
@ -325,7 +238,7 @@ JSCompartment::wrap(JSContext *cx, jsval *vp)
/* Unwrap incoming objects. */
if (!JSVAL_IS_PRIMITIVE(*vp)) {
JSObject *obj = JSVAL_TO_OBJECT(*vp)->unwrap(&flags);
JSObject *obj = JSVAL_TO_OBJECT(*vp)->unwrap();
*vp = OBJECT_TO_JSVAL(obj);
/* If the wrapped object is already in this compartment, we are done. */
if (obj->getCompartment(cx) == this)
@ -358,19 +271,14 @@ JSCompartment::wrap(JSContext *cx, jsval *vp)
* here (since Object.prototype->parent->proto leads to Object.prototype
* itself).
*/
JSObject *proto = obj->getProto();
if (!wrap(cx, &proto))
AutoObjectRooter proto(cx, obj->getProto());
if (!wrap(cx, proto.addr()))
return false;
/*
* We hand in the original wrapped object into the wrap hook to allow
* the wrap hook to reason over what wrappers are currently applied
* to the object.
*/
JSObject *wrapper = cx->runtime->wrapObjectCallback(cx, obj, proto, flags);
JSObject *wrapper = cx->runtime->wrapObjectCallback(cx, obj, proto.object());
if (!wrapper)
return false;
wrapper->setProto(proto);
wrapper->setProto(proto.object());
*vp = OBJECT_TO_JSVAL(wrapper);
if (!crossCompartmentWrappers.put(wrapper->getProxyPrivate(), *vp))
return false;
@ -547,7 +455,16 @@ AutoCompartment::leave()
/* Cross compartment wrappers. */
JSCrossCompartmentWrapper::JSCrossCompartmentWrapper(uintN flags) : JSWrapper(flags)
static int sCrossCompartmentWrapperKind = 0;
bool
JSObject::isCrossCompartmentWrapper() const
{
return isWrapper() &&
static_cast<JSWrapper *>(getProxyHandler())->kind() == &sCrossCompartmentWrapperKind;
}
JSCrossCompartmentWrapper::JSCrossCompartmentWrapper() : JSWrapper(&sCrossCompartmentWrapperKind)
{
}
@ -555,122 +472,116 @@ JSCrossCompartmentWrapper::~JSCrossCompartmentWrapper()
{
}
bool
JSCrossCompartmentWrapper::isCrossCompartmentWrapper(JSObject *obj)
{
return obj->getProxyHandler() == &JSCrossCompartmentWrapper::singleton;
}
#define PIERCE(cx, wrapper, mode, pre, op, post) \
JS_BEGIN_MACRO \
AutoCompartment call(cx, wrappedObject(wrapper)); \
if (!call.enter()) \
return false; \
bool ok = (pre) && (op); \
call.leave(); \
return ok && (post); \
#define PIERCE(cx, proxy, mode, pre, op, post) \
JS_BEGIN_MACRO \
AutoCompartment call(cx, wrappedObject(proxy)); \
if (!call.enter() || !(pre) || !enter(cx, proxy, id, mode) || !(op)) \
return false; \
leave(cx, proxy); \
call.leave(); \
return (post); \
JS_END_MACRO
#define NOTHING (true)
bool
JSCrossCompartmentWrapper::getPropertyDescriptor(JSContext *cx, JSObject *wrapper, jsid id, JSPropertyDescriptor *desc)
JSCrossCompartmentWrapper::getPropertyDescriptor(JSContext *cx, JSObject *proxy, jsid id, JSPropertyDescriptor *desc)
{
PIERCE(cx, wrapper, GET,
PIERCE(cx, proxy, GET,
call.destination->wrapId(cx, &id),
JSWrapper::getPropertyDescriptor(cx, wrapper, id, desc),
JSWrapper::getPropertyDescriptor(cx, proxy, id, desc),
call.origin->wrap(cx, desc));
}
bool
JSCrossCompartmentWrapper::getOwnPropertyDescriptor(JSContext *cx, JSObject *wrapper, jsid id, JSPropertyDescriptor *desc)
JSCrossCompartmentWrapper::getOwnPropertyDescriptor(JSContext *cx, JSObject *proxy, jsid id, JSPropertyDescriptor *desc)
{
PIERCE(cx, wrapper, GET,
PIERCE(cx, proxy, GET,
call.destination->wrapId(cx, &id),
JSWrapper::getOwnPropertyDescriptor(cx, wrapper, id, desc),
JSWrapper::getOwnPropertyDescriptor(cx, proxy, id, desc),
call.origin->wrap(cx, desc));
}
bool
JSCrossCompartmentWrapper::defineProperty(JSContext *cx, JSObject *wrapper, jsid id, JSPropertyDescriptor *desc)
JSCrossCompartmentWrapper::defineProperty(JSContext *cx, JSObject *proxy, jsid id, JSPropertyDescriptor *desc)
{
AutoDescriptor desc2(cx, desc);
PIERCE(cx, wrapper, SET,
PIERCE(cx, proxy, SET,
call.destination->wrapId(cx, &id) && call.destination->wrap(cx, &desc2),
JSWrapper::defineProperty(cx, wrapper, id, &desc2),
JSWrapper::getOwnPropertyDescriptor(cx, proxy, id, &desc2),
NOTHING);
}
bool
JSCrossCompartmentWrapper::getOwnPropertyNames(JSContext *cx, JSObject *wrapper, AutoValueVector &props)
JSCrossCompartmentWrapper::getOwnPropertyNames(JSContext *cx, JSObject *proxy, AutoValueVector &props)
{
PIERCE(cx, wrapper, GET,
PIERCE(cx, proxy, GET,
NOTHING,
JSWrapper::getOwnPropertyNames(cx, wrapper, props),
JSWrapper::getOwnPropertyNames(cx, proxy, props),
call.origin->wrap(cx, props));
}
bool
JSCrossCompartmentWrapper::delete_(JSContext *cx, JSObject *wrapper, jsid id, bool *bp)
JSCrossCompartmentWrapper::delete_(JSContext *cx, JSObject *proxy, jsid id, bool *bp)
{
PIERCE(cx, wrapper, SET,
PIERCE(cx, proxy, SET,
call.destination->wrapId(cx, &id),
JSWrapper::delete_(cx, wrapper, id, bp),
JSWrapper::delete_(cx, proxy, id, bp),
NOTHING);
}
bool
JSCrossCompartmentWrapper::enumerate(JSContext *cx, JSObject *wrapper, AutoValueVector &props)
JSCrossCompartmentWrapper::enumerate(JSContext *cx, JSObject *proxy, AutoValueVector &props)
{
PIERCE(cx, wrapper, GET,
PIERCE(cx, proxy, GET,
NOTHING,
JSWrapper::enumerate(cx, wrapper, props),
JSWrapper::enumerate(cx, proxy, props),
call.origin->wrap(cx, props));
}
bool
JSCrossCompartmentWrapper::has(JSContext *cx, JSObject *wrapper, jsid id, bool *bp)
JSCrossCompartmentWrapper::has(JSContext *cx, JSObject *proxy, jsid id, bool *bp)
{
PIERCE(cx, wrapper, GET,
PIERCE(cx, proxy, GET,
call.destination->wrapId(cx, &id),
JSWrapper::has(cx, wrapper, id, bp),
JSWrapper::has(cx, proxy, id, bp),
NOTHING);
}
bool
JSCrossCompartmentWrapper::hasOwn(JSContext *cx, JSObject *wrapper, jsid id, bool *bp)
JSCrossCompartmentWrapper::hasOwn(JSContext *cx, JSObject *proxy, jsid id, bool *bp)
{
PIERCE(cx, wrapper, GET,
PIERCE(cx, proxy, GET,
call.destination->wrapId(cx, &id),
JSWrapper::hasOwn(cx, wrapper, id, bp),
JSWrapper::hasOwn(cx, proxy, id, bp),
NOTHING);
}
bool
JSCrossCompartmentWrapper::get(JSContext *cx, JSObject *wrapper, JSObject *receiver, jsid id, jsval *vp)
JSCrossCompartmentWrapper::get(JSContext *cx, JSObject *proxy, JSObject *receiver, jsid id, jsval *vp)
{
PIERCE(cx, wrapper, GET,
PIERCE(cx, proxy, GET,
call.destination->wrap(cx, &receiver) && call.destination->wrapId(cx, &id),
JSWrapper::get(cx, wrapper, receiver, id, vp),
JSWrapper::get(cx, proxy, receiver, id, vp),
call.origin->wrap(cx, vp));
}
bool
JSCrossCompartmentWrapper::set(JSContext *cx, JSObject *wrapper, JSObject *receiver, jsid id, jsval *vp)
JSCrossCompartmentWrapper::set(JSContext *cx, JSObject *proxy, JSObject *receiver, jsid id, jsval *vp)
{
AutoValueRooter tvr(cx, *vp);
PIERCE(cx, wrapper, SET,
PIERCE(cx, proxy, SET,
call.destination->wrap(cx, &receiver) && call.destination->wrapId(cx, &id) && call.destination->wrap(cx, tvr.addr()),
JSWrapper::set(cx, wrapper, receiver, id, tvr.addr()),
JSWrapper::set(cx, proxy, receiver, id, tvr.addr()),
NOTHING);
}
bool
JSCrossCompartmentWrapper::enumerateOwn(JSContext *cx, JSObject *wrapper, AutoValueVector &props)
JSCrossCompartmentWrapper::enumerateOwn(JSContext *cx, JSObject *proxy, AutoValueVector &props)
{
PIERCE(cx, wrapper, GET,
PIERCE(cx, proxy, GET,
NOTHING,
JSWrapper::enumerateOwn(cx, wrapper, props),
JSWrapper::enumerateOwn(cx, proxy, props),
call.origin->wrap(cx, props));
}
@ -707,18 +618,18 @@ Reify(JSContext *cx, JSCompartment *origin, jsval *vp)
}
bool
JSCrossCompartmentWrapper::iterate(JSContext *cx, JSObject *wrapper, uintN flags, jsval *vp)
JSCrossCompartmentWrapper::iterate(JSContext *cx, JSObject *proxy, uintN flags, jsval *vp)
{
PIERCE(cx, wrapper, GET,
PIERCE(cx, proxy, GET,
NOTHING,
JSWrapper::iterate(cx, wrapper, flags, vp),
JSWrapper::iterate(cx, proxy, flags, vp),
CanReify(vp) ? Reify(cx, call.origin, vp) : call.origin->wrap(cx, vp));
}
bool
JSCrossCompartmentWrapper::call(JSContext *cx, JSObject *wrapper, uintN argc, jsval *vp)
JSCrossCompartmentWrapper::call(JSContext *cx, JSObject *proxy, uintN argc, jsval *vp)
{
AutoCompartment call(cx, wrappedObject(wrapper));
AutoCompartment call(cx, wrappedObject(proxy));
if (!call.enter())
return false;
@ -733,18 +644,19 @@ JSCrossCompartmentWrapper::call(JSContext *cx, JSObject *wrapper, uintN argc, js
jsval *fakevp = call.getvp();
fakevp[0] = vp[0];
fakevp[1] = vp[1];
if (!JSWrapper::call(cx, wrapper, argc, vp))
if (!enter(cx, proxy, JSVAL_VOID, GET) || !JSWrapper::call(cx, proxy, argc, vp))
return false;
leave(cx, proxy);
call.leave();
return call.origin->wrap(cx, vp);
}
bool
JSCrossCompartmentWrapper::construct(JSContext *cx, JSObject *wrapper, JSObject *receiver,
JSCrossCompartmentWrapper::construct(JSContext *cx, JSObject *proxy, JSObject *receiver,
uintN argc, jsval *argv, jsval *rval)
{
AutoCompartment call(cx, wrappedObject(wrapper));
AutoCompartment call(cx, wrappedObject(proxy));
if (!call.enter())
return false;
@ -755,26 +667,32 @@ JSCrossCompartmentWrapper::construct(JSContext *cx, JSObject *wrapper, JSObject
jsval *vp = call.getvp();
vp[0] = OBJECT_TO_JSVAL(call.target);
if (!call.destination->wrap(cx, &receiver) ||
!JSWrapper::construct(cx, wrapper, receiver, argc, argv, rval)) {
!enter(cx, proxy, JSVAL_VOID, GET) ||
!JSWrapper::construct(cx, proxy, receiver, argc, argv, rval)) {
return false;
}
leave(cx, proxy);
call.leave();
return call.origin->wrap(cx, rval) &&
call.origin->wrapException(cx);
}
JSString *
JSCrossCompartmentWrapper::obj_toString(JSContext *cx, JSObject *wrapper)
JSCrossCompartmentWrapper::obj_toString(JSContext *cx, JSObject *proxy)
{
AutoCompartment call(cx, wrappedObject(wrapper));
AutoCompartment call(cx, wrappedObject(proxy));
if (!call.enter())
return NULL;
JSString *str = JSWrapper::obj_toString(cx, wrapper);
if (!enter(cx, proxy, JSVAL_VOID, GET))
return NULL;
JSString *str = JSWrapper::obj_toString(cx, proxy);
if (!str)
return NULL;
AutoValueRooter tvr(cx, str);
leave(cx, proxy);
call.leave();
if (!call.origin->wrap(cx, &str))
return NULL;
@ -782,20 +700,35 @@ JSCrossCompartmentWrapper::obj_toString(JSContext *cx, JSObject *wrapper)
}
JSString *
JSCrossCompartmentWrapper::fun_toString(JSContext *cx, JSObject *wrapper, uintN indent)
JSCrossCompartmentWrapper::fun_toString(JSContext *cx, JSObject *proxy, uintN indent)
{
AutoCompartment call(cx, wrappedObject(wrapper));
AutoCompartment call(cx, wrappedObject(proxy));
if (!call.enter())
return NULL;
JSString *str = JSWrapper::fun_toString(cx, wrapper, indent);
if (!enter(cx, proxy, JSVAL_VOID, GET))
return NULL;
JSString *str = JSWrapper::fun_toString(cx, proxy, indent);
if (!str)
return NULL;
AutoValueRooter tvr(cx, str);
leave(cx, proxy);
call.leave();
if (!call.origin->wrap(cx, &str))
return NULL;
return str;
}
JSCrossCompartmentWrapper JSCrossCompartmentWrapper::singleton(0);
bool
JSCrossCompartmentWrapper::enter(JSContext *cx, JSObject *proxy, jsval id, Mode mode)
{
return true;
}
void
JSCrossCompartmentWrapper::leave(JSContext *cx, JSObject *proxy)
{
}
JSCrossCompartmentWrapper JSCrossCompartmentWrapper::singleton;

View File

@ -47,99 +47,95 @@
/* No-op wrapper handler base class. */
class JSWrapper : public js::JSProxyHandler {
uintN mFlags;
void *mKind;
protected:
explicit JS_FRIEND_API(JSWrapper(void *kind));
public:
uintN flags() const { return mFlags; }
explicit JS_FRIEND_API(JSWrapper(uintN flags));
typedef enum { PermitObjectAccess, PermitPropertyAccess, DenyAccess } Permission;
JS_FRIEND_API(virtual ~JSWrapper());
/* ES5 Harmony fundamental wrapper traps. */
virtual JS_FRIEND_API(bool) getPropertyDescriptor(JSContext *cx, JSObject *wrapper, jsid id,
/* ES5 Harmony fundamental proxy traps. */
virtual JS_FRIEND_API(bool) getPropertyDescriptor(JSContext *cx, JSObject *proxy, jsid id,
JSPropertyDescriptor *desc);
virtual JS_FRIEND_API(bool) getOwnPropertyDescriptor(JSContext *cx, JSObject *wrapper, jsid id,
virtual JS_FRIEND_API(bool) getOwnPropertyDescriptor(JSContext *cx, JSObject *proxy, jsid id,
JSPropertyDescriptor *desc);
virtual JS_FRIEND_API(bool) defineProperty(JSContext *cx, JSObject *wrapper, jsid id,
virtual JS_FRIEND_API(bool) defineProperty(JSContext *cx, JSObject *proxy, jsid id,
JSPropertyDescriptor *desc);
virtual JS_FRIEND_API(bool) getOwnPropertyNames(JSContext *cx, JSObject *wrapper,
virtual JS_FRIEND_API(bool) getOwnPropertyNames(JSContext *cx, JSObject *proxy,
js::AutoValueVector &props);
virtual JS_FRIEND_API(bool) delete_(JSContext *cx, JSObject *wrapper, jsid id, bool *bp);
virtual JS_FRIEND_API(bool) enumerate(JSContext *cx, JSObject *wrapper, js::AutoValueVector &props);
virtual JS_FRIEND_API(bool) fix(JSContext *cx, JSObject *wrapper, jsval *vp);
virtual JS_FRIEND_API(bool) delete_(JSContext *cx, JSObject *proxy, jsid id, bool *bp);
virtual JS_FRIEND_API(bool) enumerate(JSContext *cx, JSObject *proxy, js::AutoValueVector &props);
virtual JS_FRIEND_API(bool) fix(JSContext *cx, JSObject *proxy, jsval *vp);
/* ES5 Harmony derived wrapper traps. */
virtual JS_FRIEND_API(bool) has(JSContext *cx, JSObject *wrapper, jsid id, bool *bp);
virtual JS_FRIEND_API(bool) hasOwn(JSContext *cx, JSObject *wrapper, jsid id, bool *bp);
virtual JS_FRIEND_API(bool) get(JSContext *cx, JSObject *wrapper, JSObject *receiver, jsid id,
/* ES5 Harmony derived proxy traps. */
virtual JS_FRIEND_API(bool) has(JSContext *cx, JSObject *proxy, jsid id, bool *bp);
virtual JS_FRIEND_API(bool) hasOwn(JSContext *cx, JSObject *proxy, jsid id, bool *bp);
virtual JS_FRIEND_API(bool) get(JSContext *cx, JSObject *proxy, JSObject *receiver, jsid id,
jsval *vp);
virtual JS_FRIEND_API(bool) set(JSContext *cx, JSObject *wrapper, JSObject *receiver, jsid id,
virtual JS_FRIEND_API(bool) set(JSContext *cx, JSObject *proxy, JSObject *receiver, jsid id,
jsval *vp);
virtual JS_FRIEND_API(bool) enumerateOwn(JSContext *cx, JSObject *wrapper, js::AutoValueVector &props);
virtual JS_FRIEND_API(bool) iterate(JSContext *cx, JSObject *wrapper, uintN flags, jsval *vp);
virtual JS_FRIEND_API(bool) enumerateOwn(JSContext *cx, JSObject *proxy, js::AutoValueVector &props);
virtual JS_FRIEND_API(bool) iterate(JSContext *cx, JSObject *proxy, uintN flags, jsval *vp);
/* Spidermonkey extensions. */
virtual JS_FRIEND_API(bool) call(JSContext *cx, JSObject *wrapper, uintN argc, jsval *vp);
virtual JS_FRIEND_API(bool) construct(JSContext *cx, JSObject *wrapper, JSObject *receiver,
uintN argc, jsval *argv, jsval *rval);
virtual JS_FRIEND_API(JSString *) obj_toString(JSContext *cx, JSObject *wrapper);
virtual JS_FRIEND_API(JSString *) fun_toString(JSContext *cx, JSObject *wrapper, uintN indent);
virtual JS_FRIEND_API(void) trace(JSTracer *trc, JSObject *wrapper);
/* Policy enforcement traps. */
virtual JS_FRIEND_API(bool) enter(JSContext *cx, JSObject *wrapper, jsid id, bool set);
virtual JS_FRIEND_API(void) leave(JSContext *cx, JSObject *wrapper);
virtual JS_FRIEND_API(void) trace(JSTracer *trc, JSObject *proxy);
static JS_FRIEND_API(JSWrapper) singleton;
static JS_FRIEND_API(JSObject *) New(JSContext *cx, JSObject *obj,
JSObject *proto, JSObject *parent,
JSWrapper *handler);
JSProxyHandler *handler);
static inline JSObject *wrappedObject(JSObject *wrapper) {
return JSVAL_TO_OBJECT(wrapper->getProxyPrivate());
inline void *kind() {
return mKind;
}
static inline JSObject *wrappedObject(JSObject *proxy) {
return JSVAL_TO_OBJECT(proxy->getProxyPrivate());
}
};
/* Base class for all cross compartment wrapper handlers. */
class JSCrossCompartmentWrapper : public JSWrapper {
protected:
JS_FRIEND_API(JSCrossCompartmentWrapper());
public:
JS_FRIEND_API(JSCrossCompartmentWrapper(uintN flags));
typedef enum { GET, SET } Mode;
virtual JS_FRIEND_API(~JSCrossCompartmentWrapper());
/* ES5 Harmony fundamental wrapper traps. */
virtual JS_FRIEND_API(bool) getPropertyDescriptor(JSContext *cx, JSObject *wrapper, jsid id,
JSPropertyDescriptor *desc);
virtual JS_FRIEND_API(bool) getOwnPropertyDescriptor(JSContext *cx, JSObject *wrapper, jsid id,
JSPropertyDescriptor *desc);
virtual JS_FRIEND_API(bool) defineProperty(JSContext *cx, JSObject *wrapper, jsid id,
JSPropertyDescriptor *desc);
virtual JS_FRIEND_API(bool) getOwnPropertyNames(JSContext *cx, JSObject *wrapper, js::AutoValueVector &props);
virtual JS_FRIEND_API(bool) delete_(JSContext *cx, JSObject *wrapper, jsid id, bool *bp);
virtual JS_FRIEND_API(bool) enumerate(JSContext *cx, JSObject *wrapper, js::AutoValueVector &props);
/* ES5 Harmony fundamental proxy traps. */
virtual bool getPropertyDescriptor(JSContext *cx, JSObject *proxy, jsid id,
JSPropertyDescriptor *desc);
virtual bool getOwnPropertyDescriptor(JSContext *cx, JSObject *proxy, jsid id,
JSPropertyDescriptor *desc);
virtual bool defineProperty(JSContext *cx, JSObject *proxy, jsid id,
JSPropertyDescriptor *desc);
virtual bool getOwnPropertyNames(JSContext *cx, JSObject *proxy, js::AutoValueVector &props);
virtual bool delete_(JSContext *cx, JSObject *proxy, jsid id, bool *bp);
virtual bool enumerate(JSContext *cx, JSObject *proxy, js::AutoValueVector &props);
/* ES5 Harmony derived wrapper traps. */
virtual JS_FRIEND_API(bool) has(JSContext *cx, JSObject *wrapper, jsid id, bool *bp);
virtual JS_FRIEND_API(bool) hasOwn(JSContext *cx, JSObject *wrapper, jsid id, bool *bp);
virtual JS_FRIEND_API(bool) get(JSContext *cx, JSObject *wrapper, JSObject *receiver, jsid id, jsval *vp);
virtual JS_FRIEND_API(bool) set(JSContext *cx, JSObject *wrapper, JSObject *receiver, jsid id, jsval *vp);
virtual JS_FRIEND_API(bool) enumerateOwn(JSContext *cx, JSObject *wrapper, js::AutoValueVector &props);
virtual JS_FRIEND_API(bool) iterate(JSContext *cx, JSObject *wrapper, uintN flags, jsval *vp);
/* ES5 Harmony derived proxy traps. */
virtual bool has(JSContext *cx, JSObject *proxy, jsid id, bool *bp);
virtual bool hasOwn(JSContext *cx, JSObject *proxy, jsid id, bool *bp);
virtual bool get(JSContext *cx, JSObject *proxy, JSObject *receiver, jsid id, jsval *vp);
virtual bool set(JSContext *cx, JSObject *proxy, JSObject *receiver, jsid id, jsval *vp);
virtual bool enumerateOwn(JSContext *cx, JSObject *proxy, js::AutoValueVector &props);
virtual bool iterate(JSContext *cx, JSObject *proxy, uintN flags, jsval *vp);
/* Spidermonkey extensions. */
virtual JS_FRIEND_API(bool) call(JSContext *cx, JSObject *wrapper, uintN argc, jsval *vp);
virtual JS_FRIEND_API(bool) construct(JSContext *cx, JSObject *wrapper, JSObject *receiver,
virtual bool call(JSContext *cx, JSObject *proxy, uintN argc, jsval *vp);
virtual bool construct(JSContext *cx, JSObject *proxy, JSObject *receiver,
uintN argc, jsval *argv, jsval *rval);
virtual JS_FRIEND_API(JSString *) obj_toString(JSContext *cx, JSObject *wrapper);
virtual JS_FRIEND_API(JSString *) fun_toString(JSContext *cx, JSObject *wrapper, uintN indent);
virtual JSString *obj_toString(JSContext *cx, JSObject *proxy);
virtual JSString *fun_toString(JSContext *cx, JSObject *proxy, uintN indent);
static JS_FRIEND_API(bool) isCrossCompartmentWrapper(JSObject *obj);
/* Policy enforcement traps. */
virtual bool enter(JSContext *cx, JSObject *proxy, jsid id, Mode mode);
virtual void leave(JSContext *cx, JSObject *proxy);
static JS_FRIEND_API(JSCrossCompartmentWrapper) singleton;
static JSCrossCompartmentWrapper singleton;
/* Default id used for filter when the trap signature does not contain an id. */
static const jsid id = JSVAL_VOID;
@ -180,7 +176,7 @@ class AutoCompartment
};
extern JSObject *
TransparentObjectWrapper(JSContext *cx, JSObject *obj, JSObject *wrappedProto, uintN flags);
TransparentObjectWrapper(JSContext *cx, JSObject *obj, JSObject *wrappedProto);
}

View File

@ -2998,7 +2998,7 @@ EvalInContext(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
JSStackFrame *fp = JS_GetScriptedCaller(cx, NULL);
{
JSAutoCrossCompartmentCall ac;
if (JSCrossCompartmentWrapper::isCrossCompartmentWrapper(sobj)) {
if (sobj->isCrossCompartmentWrapper()) {
sobj = sobj->unwrap();
if (!ac.enter(cx, sobj))
return false;

View File

@ -397,7 +397,7 @@ interface nsIXPCFunctionThisTranslator : nsISupports
{ 0xbd, 0xd6, 0x0, 0x0, 0x64, 0x65, 0x73, 0x74 } }
%}
[uuid(c53c54ac-afc1-458a-98f5-cadb52574e40)]
[uuid(0332b12a-8103-4601-aed3-b9933a0d9441)]
interface nsIXPConnect : nsISupports
{
%{ C++
@ -871,5 +871,4 @@ interface nsIXPConnect : nsISupports
%}
[notxpcom] void getNativeWrapperGetPropertyOp(out JSPropertyOp getProperty);
[notxpcom] void getXrayWrapperPropertyHolderGetPropertyOp(out JSPropertyOp getProperty);
};

View File

@ -134,16 +134,14 @@ EXTRA_DSO_LDOPTS += \
$(MOZ_JS_LIBS) \
$(NULL)
LIBS = wrappers/$(LIB_PREFIX)wrappers.$(LIB_SUFFIX)
ifdef MOZ_JSLOADER
SHARED_LIBRARY_LIBS = \
../loader/$(LIB_PREFIX)jsloader_s.$(LIB_SUFFIX) \
$(NULL)
endif
SHARED_LIBRARY_LIBS += \
./wrappers/$(LIB_PREFIX)xpcwrappers_s.$(LIB_SUFFIX) \
$(NULL)
include $(topsrcdir)/config/rules.mk
DEFINES += \

View File

@ -56,8 +56,6 @@
#include "jstypedarray.h"
#include "wrappers/XrayWrapper.h"
NS_IMPL_THREADSAFE_ISUPPORTS6(nsXPConnect,
nsIXPConnect,
nsISupportsWeakReference,
@ -2592,7 +2590,7 @@ nsXPConnect::GetWrapperForObject(JSContext* aJSContext,
return NS_ERROR_FAILURE;
*_retval = OBJECT_TO_JSVAL(wrappedObj);
if(wrapper && wrapper->NeedsSOW() &&
if(wrapper && wrapper->NeedsChromeWrapper() &&
!SystemOnlyWrapper::WrapObject(aJSContext, aScope, *_retval, _retval))
return NS_ERROR_FAILURE;
return NS_OK;
@ -2795,12 +2793,6 @@ nsXPConnect::GetPrincipal(JSObject* obj, PRBool allowShortCircuit) const
return nsnull;
}
NS_IMETHODIMP_(void)
nsXPConnect::GetXrayWrapperPropertyHolderGetPropertyOp(JSPropertyOp *getPropertyPtr)
{
*getPropertyPtr = xpc::HolderClass.getProperty;
}
NS_IMETHODIMP_(void)
nsXPConnect::GetNativeWrapperGetPropertyOp(JSPropertyOp *getPropertyPtr)
{

View File

@ -37,211 +37,46 @@
*
* ***** END LICENSE BLOCK ***** */
#include "AccessCheck.h"
#include "nsJSPrincipals.h"
#include "nsIDOMWindow.h"
#include "nsIDOMWindowCollection.h"
#include "jsapi.h"
#include "jswrapper.h"
#include "XPCWrapper.h"
#include "nsJSPrincipals.h"
#include "AccessCheck.h"
namespace xpc {
static nsIPrincipal *
nsIPrincipal *
GetCompartmentPrincipal(JSCompartment *compartment)
{
return static_cast<nsJSPrincipals *>(compartment->principals)->nsIPrincipalPtr;
}
bool
AccessCheck::isSameOrigin(JSCompartment *a, JSCompartment *b)
{
PRBool cond;
return NS_SUCCEEDED(GetCompartmentPrincipal(a)->Equals(GetCompartmentPrincipal(b), &cond)) &&
cond;
}
bool
AccessCheck::isChrome(JSCompartment *compartment)
AccessCheck::isPrivileged(JSCompartment *compartment)
{
nsIScriptSecurityManager *ssm = XPCWrapper::GetSecurityManager();
if (!ssm) {
return false;
if(!ssm) {
return true;
}
PRBool privileged;
nsIPrincipal *principal = GetCompartmentPrincipal(compartment);
return NS_SUCCEEDED(ssm->IsSystemPrincipal(principal, &privileged)) && privileged;
}
#define NAME(ch, str, cases) case ch: if (!strcmp(name, str)) switch (prop[0]) { cases }; break;
#define PROP(ch, actions) case ch: { actions }; break;
#define RW(str) if (!strcmp(prop, str)) return true;
#define R(str) if (!set && !strcmp(prop, str)) return true;
#define W(str) if (set && !strcmp(prop, str)) return true;
// Hardcoded policy for cross origin property access. This was culled from the
// preferences file (all.js). We don't want users to overwrite highly sensitive
// security policies.
static bool
IsPermitted(const char *name, const char* prop, bool set)
{
switch(name[0]) {
NAME('D', "DOMException",
PROP('c', RW("code"))
PROP('m', RW("message"))
PROP('n', RW("name"))
PROP('r', RW("result")))
NAME('H', "History",
PROP('b', R("back"))
PROP('f', R("forward"))
PROP('g', R("go")))
NAME('N', "Navigator",
PROP('p', RW("preference")))
NAME('W', "Window",
PROP('b', R("blur"))
PROP('c', R("close") R("closed"))
PROP('f', R("focus") R("frames"))
PROP('h', R("history"))
PROP('l', RW("location") R("length"))
PROP('o', R("opener"))
PROP('p', R("parent") R("postMessage"))
PROP('s', R("self"))
PROP('t', R("top"))
PROP('w', R("window")))
NAME('X', "XMLHttpRequest",
PROP('o', RW("open-uri")))
NAME('S', "SOAPCall",
PROP('i', RW("invokeVerifySourceHeader")))
if(NS_SUCCEEDED(ssm->IsSystemPrincipal(GetCompartmentPrincipal(compartment), &privileged))
&& privileged) {
return true;
}
if(NS_SUCCEEDED(ssm->IsCapabilityEnabled("UniversalXPConnect", &privileged)) && privileged) {
return true;
}
return false;
}
#undef NAME
#undef RW
#undef R
#undef W
static bool
IsFrameId(JSObject *obj, jsid id)
{
XPCWrappedNative *wn = static_cast<XPCWrappedNative *>(obj->getPrivate());
nsCOMPtr<nsIDOMWindow> domwin(do_QueryWrappedNative(wn));
if (!domwin) {
return false;
}
nsCOMPtr<nsIDOMWindowCollection> col;
domwin->GetFrames(getter_AddRefs(col));
if (!col) {
return false;
}
if (JSID_IS_INT(id)) {
col->Item(JSID_TO_INT(id), getter_AddRefs(domwin));
} else if (JSID_IS_ATOM(id)) {
nsAutoString str(reinterpret_cast<PRUnichar *>
(JS_GetStringChars(ATOM_TO_STRING(JSID_TO_ATOM(id)))));
col->NamedItem(str, getter_AddRefs(domwin));
} else {
return false;
}
return domwin != nsnull;
}
static bool
IsWindow(const char *name)
{
return name[0] == 'W' && !strcmp(name, "Window");
}
bool
AccessCheck::isCrossOriginAccessPermitted(JSContext *cx, JSObject *wrapper, jsid id, bool set)
{
JSObject *obj = JSWrapper::wrappedObject(wrapper);
nsIScriptSecurityManager *ssm = XPCWrapper::GetSecurityManager();
if (!ssm) {
return true;
}
const char *name = obj->getClass()->name;
if (JSID_IS_ATOM(id)) {
JSString *str = ATOM_TO_STRING(JSID_TO_ATOM(id));
const char *prop = JS_GetStringBytes(str);
if (IsPermitted(name, prop, set))
return true;
}
if (IsWindow(name) && IsFrameId(obj, id))
return true;
PRBool privileged;
return NS_SUCCEEDED(ssm->IsCapabilityEnabled("UniversalXPConnect", &privileged)) && privileged;
}
bool
AccessCheck::isSystemOnlyAccessPermitted(JSContext *cx)
{
nsIScriptSecurityManager *ssm = XPCWrapper::GetSecurityManager();
if (!ssm) {
return true;
}
JSStackFrame *fp;
nsIPrincipal *principal = ssm->GetCxSubjectPrincipalAndFrame(cx, &fp);
if (!principal) {
return false;
}
if (!fp) {
if (!JS_FrameIterator(cx, &fp)) {
// No code at all is running. So we must be arriving here as the result
// of C++ code asking us to do something. Allow access.
return true;
}
// Some code is running, we can't make the assumption, as above, but we
// can't use a native frame, so clear fp.
fp = NULL;
} else if (!fp->script) {
fp = NULL;
}
PRBool privileged;
if (NS_SUCCEEDED(ssm->IsSystemPrincipal(principal, &privileged)) &&
privileged) {
return true;
}
// Allow any code loaded from chrome://global/ to touch us, even if it was
// cloned into a less privileged context.
static const char prefix[] = "chrome://global/";
const char *filename;
if (fp &&
(filename = fp->script->filename) &&
!strncmp(filename, prefix, NS_ARRAY_LENGTH(prefix) - 1)) {
return true;
}
return NS_SUCCEEDED(ssm->IsCapabilityEnabled("UniversalXPConnect", &privileged)) && privileged;
}
bool
AccessCheck::needsSystemOnlyWrapper(JSObject *obj)
{
NS_ASSERTION(IS_WN_WRAPPER_OBJECT(obj), "expected a wrapped native here");
XPCWrappedNative *wn = static_cast<XPCWrappedNative *>(obj->getPrivate());
return wn->NeedsSOW();
}
void
AccessCheck::deny(JSContext *cx, jsid id)
{
if (id == JSVAL_VOID) {
if(id == JSVAL_VOID) {
JS_ReportError(cx, "Permission denied to access object");
} else {
JSString *str = JS_ValueToString(cx, id);
@ -249,97 +84,32 @@ AccessCheck::deny(JSContext *cx, jsid id)
}
}
typedef enum { READ = (1<<0), WRITE = (1<<1), NO_ACCESS = 0 } Access;
bool
ExposedPropertiesOnly::check(JSContext *cx, JSObject *wrapper, jsid id, bool set, Permission &perm)
AccessCheck::enter(JSContext *cx, JSObject *wrapper, JSObject *wrappedObject, jsid id,
JSCrossCompartmentWrapper::Mode mode)
{
JSObject *holder = JSWrapper::wrappedObject(wrapper);
perm = DenyAccess;
jsid exposedPropsId = GetRTIdByIndex(cx, XPCJSRuntime::IDX_EXPOSEDPROPS);
JSBool found = JS_FALSE;
if (!JS_HasPropertyById(cx, holder, exposedPropsId, &found))
return false;
if (!found) {
perm = PermitObjectAccess;
return true; // Allow
}
if (id == JSVAL_VOID) {
// This will force the caller to call us back for individual property accesses.
perm = PermitPropertyAccess;
nsIScriptSecurityManager *ssm = XPCWrapper::GetSecurityManager();
if(!ssm) {
return true;
}
jsval exposedProps;
if (!JS_LookupPropertyById(cx, holder, exposedPropsId, &exposedProps))
return false;
if (JSVAL_IS_VOID(exposedProps) || JSVAL_IS_NULL(exposedProps)) {
return true; // Deny
}
if (!JSVAL_IS_OBJECT(exposedProps)) {
JS_ReportError(cx, "__exposedProps__ must be undefined, null, or an Object");
JSStackFrame *fp = NULL;
nsresult rv = ssm->PushContextPrincipal(cx, JS_FrameIterator(cx, &fp),
GetCompartmentPrincipal(wrappedObject->getCompartment(cx)));
if(NS_FAILED(rv)) {
NS_WARNING("Not allowing call because we're out of memory");
JS_ReportOutOfMemory(cx);
return false;
}
return true;
}
JSObject *hallpass = JSVAL_TO_OBJECT(exposedProps);
Access access = NO_ACCESS;
jsval v;
if (!JS_LookupPropertyById(cx, hallpass, id, &v)) {
return false; // Error
void
AccessCheck::leave(JSContext *cx, JSObject *wrapper, JSObject *wrappedObject)
{
nsIScriptSecurityManager *ssm = XPCWrapper::GetSecurityManager();
if(ssm) {
ssm->PopContextPrincipal(cx);
}
if (!JSVAL_IS_STRING(v)) {
JS_ReportError(cx, "property must be a string");
return false;
}
JSString *str = JSVAL_TO_STRING(v);
const jschar *chars = JS_GetStringChars(str);
size_t length = JS_GetStringLength(str);
for (size_t i = 0; i < length; ++i) {
switch (chars[i]) {
case 'r':
if (access & READ) {
JS_ReportError(cx, "duplicate 'readable' property flag");
return false;
}
access = Access(access | READ);
break;
case 'w':
if (access & WRITE) {
JS_ReportError(cx, "duplicate 'writable' property flag");
return false;
}
access = Access(access | WRITE);
break;
default:
JS_ReportError(cx, "properties can only be readable or read and writable");
return false;
}
}
if (access == NO_ACCESS) {
JS_ReportError(cx, "specified properties must have a permission bit set");
return false;
}
if ((set && !(access & WRITE)) ||
(!set && !(access & READ))) {
return true; // Deny
}
perm = PermitPropertyAccess;
return true; // Allow
}
}

View File

@ -44,58 +44,14 @@ namespace xpc {
class AccessCheck {
public:
static bool isSameOrigin(JSCompartment *a, JSCompartment *b);
static bool isChrome(JSCompartment *compartment);
static bool isCrossOriginAccessPermitted(JSContext *cx, JSObject *obj, jsid id, bool set);
static bool isSystemOnlyAccessPermitted(JSContext *cx);
static bool needsSystemOnlyWrapper(JSObject *obj);
static bool subsumes(JSCompartment *subject, JSCompartment *object, bool *yesno);
static bool isPrivileged(JSCompartment *compartment);
static void deny(JSContext *cx, jsid id);
};
struct Policy {
typedef JSWrapper::Permission Permission;
static const Permission PermitObjectAccess = JSWrapper::PermitObjectAccess;
static const Permission PermitPropertyAccess = JSWrapper::PermitPropertyAccess;
static const Permission DenyAccess = JSWrapper::DenyAccess;
};
// This policy permits access to all properties.
struct Permissive : public Policy {
static bool check(JSContext *cx, JSObject *wrapper, jsid id, bool set, Permission &perm) {
perm = PermitObjectAccess;
return true;
}
};
// This policy only permits access to the object if the subject can touch
// system objects.
struct OnlyIfSubjectIsSystem : public Policy {
static bool check(JSContext *cx, JSObject *wrapper, jsid id, bool set, Permission &perm) {
perm = DenyAccess;
if (AccessCheck::isSystemOnlyAccessPermitted(cx))
perm = PermitObjectAccess;
return true;
}
};
// This policy only permits access to properties that are safe to be used
// across origins.
struct CrossOriginAccessiblePropertiesOnly : public Policy {
static bool check(JSContext *cx, JSObject *wrapper, jsid id, bool set, Permission &perm) {
perm = DenyAccess;
if (AccessCheck::isCrossOriginAccessPermitted(cx, wrapper, id, set))
perm = PermitPropertyAccess;
return true;
}
};
// This policy only permits access to properties if they appear in the
// objects exposed properties list.
struct ExposedPropertiesOnly : public Policy {
static bool check(JSContext *cx, JSObject *wrapper, jsid id, bool set, Permission &perm);
static bool enter(JSContext *cx, JSObject *wrapper, JSObject *wrappedObject, jsid id,
JSCrossCompartmentWrapper::Mode mode);
static void leave(JSContext *cx, JSObject *wrapper, JSObject *wrappedObject);
};
}

View File

@ -0,0 +1,244 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=4 sw=4 et tw=99 ft=cpp:
*
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code, released
* June 24, 2010.
*
* The Initial Developer of the Original Code is
* The Mozilla Foundation
*
* Contributor(s):
* Andreas Gal <gal@mozilla.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "ChromeWrapper.h"
#include "AccessCheck.h"
#include "XPCWrapper.h"
using namespace js;
namespace xpc {
ChromeWrapper ChromeWrapper::singleton;
ChromeWrapper::ChromeWrapper() : JSCrossCompartmentWrapper()
{
}
ChromeWrapper::~ChromeWrapper()
{
}
typedef enum { READ = (1<<0), WRITE = (1<<1), DENIED=0 } Permission;
static bool
Allow(JSContext *cx, bool *yesno)
{
if(yesno) {
*yesno = true;
}
return true;
}
static bool
Deny(JSContext *cx, bool *yesno, const char *error)
{
if(yesno) {
*yesno = false;
return true;
}
JS_ReportError(cx, error);
return false;
}
static bool
CheckAccess(JSContext *cx, JSObject *hallpass, jsid id, JSCrossCompartmentWrapper::Mode mode,
bool *yesno = NULL)
{
if(!hallpass) {
return Allow(cx, yesno);
}
Permission perm = DENIED;
jsval v;
if(!JS_LookupPropertyById(cx, hallpass, id, &v)) {
return false;
}
if(!JSVAL_IS_STRING(v)) {
return Deny(cx, yesno, "property permission must be a string");
}
JSString *str = JSVAL_TO_STRING(v);
const jschar *chars = JS_GetStringChars(str);
size_t length = JS_GetStringLength(str);
for (size_t i = 0; i < length; ++i) {
switch (chars[i]) {
case 'r':
if(perm & READ) {
return Deny(cx, yesno, "duplicate 'readable' property flag");
}
perm = Permission(perm | READ);
break;
case 'w':
if(perm & WRITE) {
return Deny(cx, yesno, "duplicate 'writable' property flag");
}
perm = Permission(perm | WRITE);
break;
default:
return Deny(cx, yesno, "property permission can only be readable or read and writable");
}
}
if(perm == DENIED) {
return Deny(cx, yesno, "invalid property permission");
}
if((mode == JSCrossCompartmentWrapper::GET && !(perm & READ)) ||
(mode == JSCrossCompartmentWrapper::SET && !(perm & WRITE))) {
if(yesno) {
*yesno = false;
return true;
}
AccessCheck::deny(cx, id);
return false;
}
return Allow(cx, yesno);
}
static bool
GetHallPass(JSContext *cx, JSObject *wrappedObject, jsid id, JSObject **hallpassp)
{
jsid exposedPropsId = GetRTIdByIndex(cx, XPCJSRuntime::IDX_EXPOSEDPROPS);
JSBool found = JS_FALSE;
if(!JS_HasPropertyById(cx, wrappedObject, exposedPropsId, &found))
return false;
if(!found) {
*hallpassp = NULL;
return true;
}
jsval exposedProps;
if(!JS_LookupPropertyById(cx, wrappedObject, exposedPropsId, &exposedProps))
return false;
if(JSVAL_IS_VOID(exposedProps) || JSVAL_IS_NULL(exposedProps)) {
AccessCheck::deny(cx, id);
return false;
}
if(!JSVAL_IS_OBJECT(exposedProps)) {
JS_ReportError(cx,
"__exposedProps__ must be undefined, null, or an object");
return false;
}
*hallpassp = JSVAL_TO_OBJECT(exposedProps);
return true;
}
static bool
Filter(JSContext *cx, JSObject *wrappedObject, AutoValueVector &props)
{
JSObject *hallpass;
if(!GetHallPass(cx, wrappedObject, JSVAL_VOID, &hallpass))
return false;
if(!hallpass)
return true;
size_t w = 0;
for (size_t n = 0; n < props.length(); ++n) {
bool yes;
jsid id = props[n];
if(!CheckAccess(cx, hallpass, id, JSCrossCompartmentWrapper::GET, &yes))
return false;
if(yes) {
props[w++] = id;
}
}
props.resize(w);
return true;
}
bool
ChromeWrapper::getOwnPropertyNames(JSContext *cx, JSObject *wrapper, AutoValueVector &props)
{
return JSCrossCompartmentWrapper::getOwnPropertyNames(cx, wrapper, props) &&
Filter(cx, wrappedObject(wrapper), props);
}
bool
ChromeWrapper::enumerate(JSContext *cx, JSObject *wrapper, AutoValueVector &props)
{
return JSCrossCompartmentWrapper::enumerate(cx, wrapper, props) &&
Filter(cx, wrappedObject(wrapper), props);
}
bool
ChromeWrapper::enumerateOwn(JSContext *cx, JSObject *wrapper, AutoValueVector &props)
{
return JSCrossCompartmentWrapper::enumerateOwn(cx, wrapper, props) &&
Filter(cx, wrappedObject(wrapper), props);
}
bool
ChromeWrapper::iterate(JSContext *cx, JSObject *wrapper, uintN flags, jsval *vp)
{
// We refuse to trigger the iterator hook across chrome wrappers because
// we don't know how to censor custom iterator objects. Instead we trigger
// the default proxy iterate trap, which will ask ChromeWrapper::enumerate()
// for the list of (consored) ids.
return JSProxyHandler::iterate(cx, wrapper, flags, vp);
}
bool
ChromeWrapper::enter(JSContext *cx, JSObject *wrapper, jsid id, Mode mode)
{
JSObject *hallpass;
return GetHallPass(cx, wrappedObject(wrapper), id, &hallpass) &&
CheckAccess(cx, hallpass, id, mode);
}
JSString *
ChromeWrapper::fun_toString(JSContext *cx, JSObject *wrapper, uintN indent)
{
// Censor Function.prototype.toString.call(wrapper) and decompile Function instead.
JSObject *ctor;
if(!JS_GetClassObject(cx, wrapper->getGlobal(), JSProto_Function, &ctor))
return false;
return JS_DecompileFunction(cx, JS_ValueToConstructor(cx, OBJECT_TO_JSVAL(ctor)), indent);
}
}

View File

@ -37,25 +37,26 @@
*
* ***** END LICENSE BLOCK ***** */
#include <jsapi.h>
#include <jswrapper.h>
#include "jsapi.h"
#include "jswrapper.h"
namespace xpc {
template <typename Base, typename Policy>
class FilteringWrapper : public Base {
class ChromeWrapper : public JSCrossCompartmentWrapper {
public:
FilteringWrapper(uintN flags);
virtual ~FilteringWrapper();
ChromeWrapper();
virtual ~ChromeWrapper();
virtual bool getOwnPropertyNames(JSContext *cx, JSObject *wrapper, js::AutoValueVector &props);
virtual bool enumerate(JSContext *cx, JSObject *wrapper, js::AutoValueVector &props);
virtual bool enumerateOwn(JSContext *cx, JSObject *wrapper, js::AutoValueVector &props);
virtual bool iterate(JSContext *cx, JSObject *proxy, uintN flags, jsval *vp);
virtual bool enter(JSContext *cx, JSObject *wrapper, jsid id, bool set);
virtual bool enter(JSContext *cx, JSObject *wrapper, jsid id, Mode mode);
static FilteringWrapper singleton;
virtual JSString *fun_toString(JSContext *cx, JSObject *wrapper, uintN indent);
static ChromeWrapper singleton;
};
}

View File

@ -37,30 +37,31 @@
*
* ***** END LICENSE BLOCK ***** */
#include "jsapi.h"
#include "jswrapper.h"
// Xray wrappers re-resolve the original native properties on the native
// object and always directly access to those properties.
#include "ContentWrapper.h"
#include "AccessCheck.h"
namespace xpc {
extern JSClass HolderClass;
ContentWrapper ContentWrapper::singleton;
template <typename Base>
class XrayWrapper : public Base {
public:
XrayWrapper(uintN flags);
virtual ~XrayWrapper();
ContentWrapper::ContentWrapper() : JSCrossCompartmentWrapper()
{
}
virtual bool getPropertyDescriptor(JSContext *cx, JSObject *wrapper, jsid id,
JSPropertyDescriptor *desc);
virtual bool getOwnPropertyDescriptor(JSContext *cx, JSObject *wrapper, jsid id,
JSPropertyDescriptor *desc);
virtual bool has(JSContext *cx, JSObject *wrapper, jsid id, bool *bp);
virtual bool hasOwn(JSContext *cx, JSObject *wrapper, jsid id, bool *bp);
ContentWrapper::~ContentWrapper()
{
}
static XrayWrapper singleton;
};
bool
ContentWrapper::enter(JSContext *cx, JSObject *wrapper, jsid id, Mode mode)
{
return AccessCheck::enter(cx, wrapper, wrappedObject(wrapper), id, mode);
}
void
ContentWrapper::leave(JSContext *cx, JSObject *wrapper)
{
return AccessCheck::leave(cx, wrapper, wrappedObject(wrapper));
}
}

View File

@ -37,25 +37,28 @@
*
* ***** END LICENSE BLOCK ***** */
#ifndef __CrossOriginWrapper_h__
#define __CrossOriginWrapper_h__
#include "jsapi.h"
#include "jswrapper.h"
// Content wrappers allow unmitigated access and are only used if the
// origin (subject) compartment's principals subsume the target (object)
// compartment's principals.
//
// The main responsibility of the content wrapper is to push and pop the
// target (object) compartment's principals when entering and leaving
// that compartment.
namespace xpc {
class CrossOriginWrapper : public JSCrossCompartmentWrapper {
class ContentWrapper : public JSCrossCompartmentWrapper {
public:
CrossOriginWrapper(uintN flags);
virtual ~CrossOriginWrapper();
ContentWrapper();
virtual ~ContentWrapper();
virtual bool enter(JSContext *cx, JSObject *wrapper, jsid id, bool set);
virtual bool enter(JSContext *cx, JSObject *wrapper, jsid id, Mode mode);
virtual void leave(JSContext *cx, JSObject *wrapper);
static CrossOriginWrapper singleton;
static ContentWrapper singleton;
};
}
#endif

View File

@ -1,89 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=4 sw=4 et tw=99 ft=cpp:
*
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code, released
* June 24, 2010.
*
* The Initial Developer of the Original Code is
* The Mozilla Foundation
*
* Contributor(s):
* Andreas Gal <gal@mozilla.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "CrossOriginWrapper.h"
#include "nsJSPrincipals.h"
#include "XPCWrapper.h"
namespace xpc {
CrossOriginWrapper::CrossOriginWrapper(uintN flags) : JSCrossCompartmentWrapper(flags)
{
}
CrossOriginWrapper::~CrossOriginWrapper()
{
}
static nsIPrincipal *
GetCompartmentPrincipal(JSCompartment *compartment)
{
return static_cast<nsJSPrincipals *>(compartment->principals)->nsIPrincipalPtr;
}
bool
CrossOriginWrapper::enter(JSContext *cx, JSObject *wrapper, jsid id, bool set)
{
nsIScriptSecurityManager *ssm = XPCWrapper::GetSecurityManager();
if (!ssm) {
return true;
}
JSStackFrame *fp = NULL;
nsIPrincipal *principal = GetCompartmentPrincipal(wrappedObject(wrapper)->getCompartment(cx));
nsresult rv = ssm->PushContextPrincipal(cx, JS_FrameIterator(cx, &fp), principal);
if (NS_FAILED(rv)) {
NS_WARNING("Not allowing call because we're out of memory");
JS_ReportOutOfMemory(cx);
return false;
}
return true;
}
void
CrossOriginWrapper::leave(JSContext *cx, JSObject *wrapper)
{
nsIScriptSecurityManager *ssm = XPCWrapper::GetSecurityManager();
if (ssm) {
ssm->PopContextPrincipal(cx);
}
}
}

View File

@ -1,155 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=4 sw=4 et tw=99 ft=cpp:
*
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code, released
* June 24, 2010.
*
* The Initial Developer of the Original Code is
* The Mozilla Foundation
*
* Contributor(s):
* Andreas Gal <gal@mozilla.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "FilteringWrapper.h"
#include "AccessCheck.h"
#include "CrossOriginWrapper.h"
#include "XrayWrapper.h"
#include "XPCWrapper.h"
using namespace js;
namespace xpc {
template <typename Base, typename Policy>
FilteringWrapper<Base, Policy>::FilteringWrapper(uintN flags) : Base(flags)
{
}
template <typename Base, typename Policy>
FilteringWrapper<Base, Policy>::~FilteringWrapper()
{
}
typedef JSWrapper::Permission Permission;
static const Permission PermitObjectAccess = JSWrapper::PermitObjectAccess;
static const Permission PermitPropertyAccess = JSWrapper::PermitPropertyAccess;
static const Permission DenyAccess = JSWrapper::DenyAccess;
template <typename Policy>
static bool
Filter(JSContext *cx, JSObject *wrapper, AutoValueVector &props)
{
size_t w = 0;
for (size_t n = 0; n < props.length(); ++n) {
jsid id = props[n];
Permission perm;
if (perm != PermitObjectAccess && !Policy::check(cx, wrapper, id, false, perm))
return false; // Error
if (perm != DenyAccess) {
props[w++] = id;
}
}
props.resize(w);
return true;
}
template <typename Policy>
static bool
CheckAndReport(JSContext *cx, JSObject *wrapper, jsid id, bool set, Permission &perm)
{
if (!Policy::check(cx, wrapper, id, set, perm)) {
return false;
}
if (perm == DenyAccess) {
AccessCheck::deny(cx, id);
return false;
}
return true;
}
template <typename Base, typename Policy>
bool
FilteringWrapper<Base, Policy>::getOwnPropertyNames(JSContext *cx, JSObject *wrapper, AutoValueVector &props)
{
return Base::getOwnPropertyNames(cx, wrapper, props) &&
Filter<Policy>(cx, wrapper, props);
}
template <typename Base, typename Policy>
bool
FilteringWrapper<Base, Policy>::enumerate(JSContext *cx, JSObject *wrapper, AutoValueVector &props)
{
return Base::enumerate(cx, wrapper, props) &&
Filter<Policy>(cx, wrapper, props);
}
template <typename Base, typename Policy>
bool
FilteringWrapper<Base, Policy>::enumerateOwn(JSContext *cx, JSObject *wrapper, AutoValueVector &props)
{
return Base::enumerateOwn(cx, wrapper, props) &&
Filter<Policy>(cx, wrapper, props);
}
template <typename Base, typename Policy>
bool
FilteringWrapper<Base, Policy>::iterate(JSContext *cx, JSObject *wrapper, uintN flags, jsval *vp)
{
// We refuse to trigger the iterator hook across chrome wrappers because
// we don't know how to censor custom iterator objects. Instead we trigger
// the default proxy iterate trap, which will ask enumerate() for the list
// of (consored) ids.
return JSProxyHandler::iterate(cx, wrapper, flags, vp);
}
template <typename Base, typename Policy>
bool
FilteringWrapper<Base, Policy>::enter(JSContext *cx, JSObject *wrapper, jsid id, bool set)
{
Permission perm;
return CheckAndReport<Policy>(cx, wrapper, JSVAL_VOID, set, perm) &&
Base::enter(cx, wrapper, id, set);
}
#define SOW FilteringWrapper<JSCrossCompartmentWrapper, OnlyIfSubjectIsSystem>
#define COW FilteringWrapper<JSCrossCompartmentWrapper, ExposedPropertiesOnly>
#define XOW FilteringWrapper<XrayWrapper<CrossOriginWrapper>, CrossOriginAccessiblePropertiesOnly>
template<> SOW SOW::singleton(0);
template<> COW COW::singleton(0);
template<> XOW XOW::singleton(0);
template class SOW;
template class COW;
template class XOW;
}

View File

@ -47,10 +47,9 @@ LIBRARY_NAME = xpcwrappers_s
FORCE_STATIC_LIB = 1
LIBXUL_LIBRARY = 1
CPPSRCS = AccessCheck.cpp \
CrossOriginWrapper.cpp \
FilteringWrapper.cpp \
XrayWrapper.cpp \
CPPSRCS = ContentWrapper.cpp \
ChromeWrapper.cpp \
AccessCheck.cpp \
WrapperFactory.cpp
LOCAL_INCLUDES = \

View File

@ -37,79 +37,20 @@
*
* ***** END LICENSE BLOCK ***** */
#include "jsobj.h"
#include "WrapperFactory.h"
#include "CrossOriginWrapper.h"
#include "FilteringWrapper.h"
#include "XrayWrapper.h"
#include "ContentWrapper.h"
#include "ChromeWrapper.h"
#include "AccessCheck.h"
#include "xpcprivate.h"
namespace xpc {
// When chrome pulls a naked property across the membrane using
// .wrappedJSObject, we want it to cross the membrane into the
// chrome compartment without automatically being wrapped into an
// X-ray wrapper. We achieve this by wrapping it into a special
// transparent wrapper in the origin (non-chrome) compartment. When
// an object with that special wrapper applied crosses into chrome,
// we know to not apply an X-ray wrapper.
JSWrapper WaiveXrayWrapperWrapper(WrapperFactory::WAIVE_XRAY_WRAPPER_FLAG);
// When objects for which we waived the X-ray wrapper cross into
// chrome, we wrap them into a special cross-compartment wrapper
// that transitively extends the waiver to all properties we get
// off it.
JSCrossCompartmentWrapper XrayWrapperWaivedWrapper(WrapperFactory::WAIVE_XRAY_WRAPPER_FLAG);
JSObject *
WrapperFactory::Rewrap(JSContext *cx, JSObject *obj, JSObject *wrappedProto, uintN flags)
JSCrossCompartmentWrapper *
WrapperFactory::select(JSContext *cx, JSCompartment *subject, JSCompartment *object)
{
NS_ASSERTION(!obj->isWrapper(), "wrapped object passed to rewrap");
JSCompartment *origin = obj->getCompartment(cx);
JSCompartment *target = cx->compartment;
JSWrapper *wrapper;
if (AccessCheck::isChrome(target)) {
NS_ASSERTION(!AccessCheck::isChrome(origin), "we shouldn't rewrap from chrome into chrome");
// If we waived the X-ray wrapper for this object, wrap it into a
// special wrapper to transitively maintain the X-ray waiver.
if (flags & WAIVE_XRAY_WRAPPER_FLAG) {
wrapper = &XrayWrapperWaivedWrapper;
} else {
// Native objects must be wrapped into an X-ray wrapper.
wrapper = IS_WN_WRAPPER_OBJECT(obj)
? &XrayWrapper<JSCrossCompartmentWrapper>::singleton
: &JSCrossCompartmentWrapper::singleton;
}
} else if (AccessCheck::isChrome(origin)) {
// If an object that needs a system only wrapper crosses into content
// from chrome, we have to wrap it into a system only wrapper on the
// fly. In this case we don't need to restrict to exposed properties
// since only privileged content will be allowed to touch it anyway.
if (AccessCheck::needsSystemOnlyWrapper(obj)) {
wrapper = &FilteringWrapper<JSCrossCompartmentWrapper,
OnlyIfSubjectIsSystem>::singleton;
} else {
wrapper = &FilteringWrapper<JSCrossCompartmentWrapper,
ExposedPropertiesOnly>::singleton;
}
} else if (AccessCheck::isSameOrigin(origin, target)) {
// Same origin we use a transparent wrapper;
wrapper = &JSCrossCompartmentWrapper::singleton;
} else {
// Cross origin we want to disallow scripting and limit access to
// a predefined set of properties. XrayWrapper adds a property
// (.wrappedJSObject) which allows bypassing the XrayWrapper, but
// we filter out access to that property.
wrapper = &FilteringWrapper<XrayWrapper<CrossOriginWrapper>,
CrossOriginAccessiblePropertiesOnly>::singleton;
if(AccessCheck::isPrivileged(object)) {
return &ChromeWrapper::singleton;
}
return JSWrapper::New(cx, obj, wrappedProto, NULL, wrapper);
return &ContentWrapper::singleton;
}
}

View File

@ -43,21 +43,10 @@
namespace xpc {
class WrapperFactory {
public:
enum { WAIVE_XRAY_WRAPPER_FLAG = (1<<0) };
// Return true if any of any of the nested wrappers have the flag set.
bool HasWrapperFlag(JSObject *wrapper, uintN flag) {
uintN flags = 0;
wrapper->unwrap(&flags);
return !!(flags & flag);
}
// Rewrap an object that is about to cross compartment boundaries.
static JSObject *Rewrap(JSContext *cx,
JSObject *obj,
JSObject *wrappedProto,
uintN flags);
// Return the wrapper handler to use, or NULL in case of error.
static JSCrossCompartmentWrapper *select(JSContext *cx,
JSCompartment *subject,
JSCompartment *object);
};
}

View File

@ -1,323 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=4 sw=4 et tw=99 ft=cpp:
*
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code, released
* June 24, 2010.
*
* The Initial Developer of the Original Code is
* The Mozilla Foundation
*
* Contributor(s):
* Andreas Gal <gal@mozilla.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "XrayWrapper.h"
#include "AccessCheck.h"
#include "FilteringWrapper.h"
#include "CrossOriginWrapper.h"
#include "WrapperFactory.h"
#include "jscntxt.h"
#include "XPCWrapper.h"
#include "xpcprivate.h"
namespace xpc {
using namespace js;
static const uint32 JSSLOT_WN_OBJ = JSSLOT_PRIVATE;
static JSBool
holder_get(JSContext *cx, JSObject *holder, jsid id, jsval *vp);
static JSBool
holder_set(JSContext *cx, JSObject *holder, jsid id, jsval *vp);
static JSBool
holder_enumerate(JSContext *cx, JSObject *holder);
JSClass HolderClass = {
"NativePropertyHolder",
JSCLASS_HAS_RESERVED_SLOTS(1),
JS_PropertyStub, JS_PropertyStub, holder_get, holder_set,
holder_enumerate, JS_ResolveStub, JS_ConvertStub, NULL,
NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL
};
template <typename Base>
XrayWrapper<Base>::XrayWrapper(uintN flags) : Base(flags)
{
}
template <typename Base>
XrayWrapper<Base>::~XrayWrapper()
{
}
static XPCWrappedNative *
GetWrappedNative(JSObject *obj)
{
NS_ASSERTION(IS_WN_WRAPPER_OBJECT(obj), "expected a wrapped native here");
return static_cast<XPCWrappedNative *>(obj->getPrivate());
}
static JSObject *
GetWrappedNativeObjectFromHolder(JSObject *holder)
{
NS_ASSERTION(holder->getClass() == &HolderClass, "expected a native property holder object");
return JSVAL_TO_OBJECT(holder->getSlot(JSSLOT_WN_OBJ));
}
// Some DOM objects have shared properties that don't have an explicit
// getter/setter and rely on the class getter/setter. We install a
// class getter/setter on the holder object to trigger them.
static JSBool
holder_get(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
{
JSObject *wnObject = GetWrappedNativeObjectFromHolder(obj);
XPCWrappedNative *wn = GetWrappedNative(wnObject);
if (NATIVE_HAS_FLAG(wn, WantGetProperty)) {
JSBool retval = true;
nsresult rv = wn->GetScriptableCallback()->GetProperty(wn, cx, obj, id, vp, &retval);
if (NS_FAILED(rv)) {
if (retval) {
XPCThrower::Throw(rv, cx);
}
return false;
}
}
return true;
}
static JSBool
holder_set(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
{
JSObject *wnObject = GetWrappedNativeObjectFromHolder(obj);
XPCWrappedNative *wn = GetWrappedNative(wnObject);
if (NATIVE_HAS_FLAG(wn, WantSetProperty)) {
JSBool retval = true;
nsresult rv = wn->GetScriptableCallback()->SetProperty(wn, cx, obj, id, vp, &retval);
if (NS_FAILED(rv)) {
if (retval) {
XPCThrower::Throw(rv, cx);
}
return false;
}
}
return true;
}
static bool
ResolveNativeProperty(JSContext *cx, JSObject *holder, jsval id, bool set, JSPropertyDescriptor *desc)
{
desc->obj = NULL;
NS_ASSERTION(holder->getClass() == &HolderClass, "expected a native property holder object");
JSObject *wnObject = GetWrappedNativeObjectFromHolder(holder);
XPCWrappedNative *wn = GetWrappedNative(wnObject);
// This will do verification and the method lookup for us.
XPCCallContext ccx(JS_CALLER, cx, holder, nsnull, id);
// Run the resolve hook of the wrapped native.
JSBool retval = true;
JSObject *pobj = NULL;
uintN flags = cx->resolveFlags | (set ? JSRESOLVE_ASSIGNING : 0);
nsresult rv = wn->GetScriptableInfo()->GetCallback()->NewResolve(wn, cx, holder, id, flags,
&pobj, &retval);
if (NS_FAILED(rv)) {
if (retval) {
XPCThrower::Throw(rv, cx);
}
return false;
}
if (pobj) {
return JS_GetPropertyDescriptorById(cx, pobj, id, cx->resolveFlags, desc);
}
// There are no native numeric properties, so we can shortcut here. We will not
// find the property.
if (!JSID_IS_ATOM(id)) {
/* Not found */
return true;
}
XPCNativeInterface *iface;
XPCNativeMember *member;
if (ccx.GetWrapper() != wn ||
!wn->IsValid() ||
!(iface = ccx.GetInterface()) ||
!(member = ccx.GetMember())) {
/* Not found */
return true;
}
desc->obj = holder;
desc->attrs = JSPROP_ENUMERATE;
desc->getter = NULL;
desc->setter = NULL;
desc->shortid = NULL;
desc->value = JSVAL_VOID;
if (member->IsConstant()) {
if (!member->GetConstantValue(ccx, iface, &desc->value)) {
JS_ReportError(cx, "Failed to convert constant native property to JS value");
return false;
}
} else if (member->IsAttribute()) {
// This is a getter/setter. Clone a function for it.
jsval fval;
if (!member->NewFunctionObject(ccx, iface, wnObject, &fval)) {
JS_ReportError(cx, "Failed to clone function object for native getter/setter");
return false;
}
desc->getter = CastAsPropertyOp(JSVAL_TO_OBJECT(fval));
desc->attrs |= JSPROP_GETTER;
if (member->IsWritableAttribute()) {
desc->setter = desc->getter;;
desc->attrs |= JSPROP_SETTER;
}
// Make the property shared on the holder so no slot is allocated
// for it. This avoids keeping garbage alive through that slot.
desc->attrs |= JSPROP_SHARED;
} else {
// This is a method. Clone a function for it.
if (!member->NewFunctionObject(ccx, iface, wnObject, &desc->value)) {
JS_ReportError(cx, "Failed to clone function object for native function");
return false;
}
// Without a wrapper the function would live on the prototype. Since we
// don't have one, we have to avoid calling the scriptable helper's
// GetProperty method for this property, so stub out the getter and
// setter here explicitly.
desc->getter = desc->setter = JS_PropertyStub;
}
// Define the property.
return JS_DefinePropertyById(cx, holder, id, desc->value,
desc->getter, desc->setter, desc->attrs);
}
static JSBool
holder_enumerate(JSContext *cx, JSObject *holder)
{
// Ask the native wrapper for all its ids
JSIdArray *ida = JS_Enumerate(cx, GetWrappedNativeObjectFromHolder(holder));
if (!ida)
return false;
jsid *idp = ida->vector;
size_t length = ida->length;
// Resolve the underlyign native properties onto the holder object
while (length-- > 0) {
JSPropertyDescriptor dummy;
if (!ResolveNativeProperty(cx, holder, *idp++, false, &dummy))
return false;
}
return true;
}
struct NativePropertiesOnly : public Policy {
static bool check(JSContext *cx, JSObject *obj, jsid id, bool set, Permission &perm);
};
extern JSWrapper WaiveXrayWrapperWrapper;
static JSBool
wrappedJSObject_getter(JSContext *cx, JSObject *holder, jsid id, jsval *vp)
{
// If the caller intentionally waives the X-ray wrapper we usually
// apply for wrapped natives, use a special wrapper to make sure the
// membrane will not automatically apply an X-ray wrapper.
JSObject *wn = GetWrappedNativeObjectFromHolder(holder);
JSObject *obj = JSWrapper::New(cx, wn, NULL, wn->getParent(), &WaiveXrayWrapperWrapper);
if (!obj)
return false;
*vp = OBJECT_TO_JSVAL(obj);
return true;
}
template <typename Base>
bool
XrayWrapper<Base>::getPropertyDescriptor(JSContext *cx, JSObject *wrapper, jsid id, JSPropertyDescriptor *desc)
{
if (id == XPCJSRuntime::IDX_WRAPPED_JSOBJECT) {
desc->obj = wrapper;
desc->attrs = JSPROP_ENUMERATE|JSPROP_SHARED;
desc->getter = wrappedJSObject_getter;
desc->setter = NULL;
desc->shortid = NULL;
desc->value = JSVAL_VOID;
return true;
}
if (!Base::getPropertyDescriptor(cx, wrapper, id, desc)) {
return false;
}
if (desc->obj)
return true;
return ResolveNativeProperty(cx, Base::wrappedObject(wrapper), id, false, desc);
}
template <typename Base>
bool
XrayWrapper<Base>::getOwnPropertyDescriptor(JSContext *cx, JSObject *wrapper, jsid id, JSPropertyDescriptor *desc)
{
return getPropertyDescriptor(cx, wrapper, id, desc);
}
template <typename Base>
bool
XrayWrapper<Base>::has(JSContext *cx, JSObject *wrapper, jsid id, bool *bp)
{
// Use the default implementation, which forwards to getPropertyDescriptor.
return JSProxyHandler::has(cx, wrapper, id, bp);
}
template <typename Base>
bool
XrayWrapper<Base>::hasOwn(JSContext *cx, JSObject *wrapper, jsid id, bool *bp)
{
// Use the default implementation, which forwards to getOwnPropertyDescriptor.
return JSProxyHandler::hasOwn(cx, wrapper, id, bp);
}
#define SJOW XrayWrapper<JSCrossCompartmentWrapper>
#define XOSJOW XrayWrapper<CrossOriginWrapper>
template <> SJOW SJOW::singleton(0);
template <> XOSJOW XOSJOW::singleton(0);
template class SJOW;
template class XOSJOW;
}

View File

@ -1391,7 +1391,7 @@ XPCConvert::NativeInterface2JSObject(XPCLazyCallContext& lccx,
jsval wrappedObjVal = OBJECT_TO_JSVAL(destObj);
AUTO_MARK_JSVAL(ccx, &wrappedObjVal);
if(wrapper->NeedsSOW())
if(wrapper->NeedsChromeWrapper())
{
using SystemOnlyWrapper::WrapObject;
if(!WrapObject(ccx, xpcscope->GetGlobalJSObject(),
@ -1419,7 +1419,7 @@ XPCConvert::NativeInterface2JSObject(XPCLazyCallContext& lccx,
AUTO_MARK_JSVAL(ccx, &v);
return XPCCrossOriginWrapper::WrapObject(ccx, scope, &v) &&
(!wrapper->NeedsSOW() ||
(!wrapper->NeedsChromeWrapper() ||
SystemOnlyWrapper::WrapObject(ccx, xpcscope->GetGlobalJSObject(),
v, &v)) &&
CreateHolderIfNeeded(ccx, JSVAL_TO_OBJECT(v), d, dest);
@ -1428,12 +1428,12 @@ XPCConvert::NativeInterface2JSObject(XPCLazyCallContext& lccx,
*d = v;
if(allowNativeWrapper)
{
if(wrapper->NeedsSOW())
if(wrapper->NeedsChromeWrapper())
if(!SystemOnlyWrapper::WrapObject(ccx,
xpcscope->GetGlobalJSObject(),
v, d))
return JS_FALSE;
if(wrapper->NeedsCOW())
if(wrapper->IsDoubleWrapper())
if(!ChromeObjectWrapper::WrapObject(ccx, xpcscope->GetGlobalJSObject(), v, d))
return JS_FALSE;
}

View File

@ -2632,10 +2632,10 @@ public:
JSBool HasExternalReference() const {return mRefCnt > 1;}
JSBool NeedsSOW() { return !!(mWrapperWord & NEEDS_SOW); }
void SetNeedsSOW() { mWrapperWord |= NEEDS_SOW; }
JSBool NeedsCOW() { return !!(mWrapperWord & NEEDS_COW); }
void SetNeedsCOW() { mWrapperWord |= NEEDS_COW; }
JSBool NeedsChromeWrapper() { return !!(mWrapperWord & CHROME_ONLY); }
void SetNeedsChromeWrapper() { mWrapperWord |= CHROME_ONLY; }
JSBool IsDoubleWrapper() { return !!(mWrapperWord & DOUBLE_WRAPPER); }
void SetIsDoubleWrapper() { mWrapperWord |= DOUBLE_WRAPPER; }
JSBool NeedsXOW() { return !!(mWrapperWord & NEEDS_XOW); }
JSObject* GetWrapper()
@ -2644,13 +2644,13 @@ public:
}
void SetWrapper(JSObject *obj)
{
PRWord needsSOW = NeedsSOW() ? NEEDS_SOW : 0;
PRWord needsCOW = NeedsCOW() ? NEEDS_COW : 0;
PRWord needsChrome = NeedsChromeWrapper() ? CHROME_ONLY : 0;
PRWord doubleWrapper = IsDoubleWrapper() ? DOUBLE_WRAPPER : 0;
PRWord needsXOW = NeedsXOW() ? NEEDS_XOW : 0;
mWrapperWord = PRWord(obj) |
needsSOW |
needsCOW |
needsXOW;
needsXOW |
doubleWrapper |
needsChrome;
}
void NoteTearoffs(nsCycleCollectionTraversalCallback& cb);
@ -2687,8 +2687,8 @@ protected:
private:
enum {
NEEDS_SOW = JS_BIT(0),
NEEDS_COW = JS_BIT(1),
CHROME_ONLY = JS_BIT(0),
DOUBLE_WRAPPER = JS_BIT(1),
NEEDS_XOW = JS_BIT(2),
LAST_FLAG = NEEDS_XOW

View File

@ -428,8 +428,8 @@ XPCWrappedNative::GetNewOrUsed(XPCCallContext& ccx,
jsval newParentVal = JSVAL_NULL;
XPCMarkableJSVal newParentVal_markable(&newParentVal);
AutoMarkingJSVal newParentVal_automarker(ccx, &newParentVal_markable);
JSBool needsSOW = JS_FALSE;
JSBool needsCOW = JS_FALSE;
JSBool chromeOnly = JS_FALSE;
JSBool crossDoubleWrapped = JS_FALSE;
JSBool needsXOW = JS_FALSE;
if(sciWrapper.GetFlags().WantPreCreate())
@ -441,7 +441,7 @@ XPCWrappedNative::GetNewOrUsed(XPCCallContext& ccx,
return rv;
if(rv == NS_SUCCESS_CHROME_ACCESS_ONLY)
needsSOW = JS_TRUE;
chromeOnly = JS_TRUE;
else if(rv == NS_SUCCESS_NEEDS_XOW)
needsXOW = JS_TRUE;
rv = NS_OK;
@ -517,7 +517,7 @@ XPCWrappedNative::GetNewOrUsed(XPCCallContext& ccx,
JS_GetGlobalForObject(ccx, obj)->isSystem()) &&
!Scope->GetGlobalJSObject()->isSystem())
{
needsCOW = JS_TRUE;
crossDoubleWrapped = JS_TRUE;
}
}
}
@ -590,10 +590,10 @@ XPCWrappedNative::GetNewOrUsed(XPCCallContext& ccx,
return rv;
}
if(needsSOW)
wrapper->SetNeedsSOW();
if(needsCOW)
wrapper->SetNeedsCOW();
if(chromeOnly)
wrapper->SetNeedsChromeWrapper();
if(crossDoubleWrapped)
wrapper->SetIsDoubleWrapper();
return FinishCreate(ccx, Scope, Interface, cache, wrapper, resultWrapper);
}

View File

@ -1088,9 +1088,9 @@ XPCWrappedNativeScope::GetWrapperFor(JSContext *cx, JSObject *obj,
if(wrapper)
{
NS_ASSERTION(!wrapper->NeedsCOW(),
NS_ASSERTION(!wrapper->IsDoubleWrapper(),
"chrome object that's double wrapped makes no sense");
if(wrapper->NeedsSOW())
if(wrapper->NeedsChromeWrapper())
return WrapperType(SOW | hint);
}
@ -1116,9 +1116,9 @@ XPCWrappedNativeScope::GetWrapperFor(JSContext *cx, JSObject *obj,
// NB: obj2 controls whether or not this is actually a "wrapped native".
if(wrapper)
{
if(wrapper->NeedsSOW())
if(wrapper->NeedsChromeWrapper())
return WrapperType(SOW | (hint & (SJOW | XPCNW_EXPLICIT | COW)));
if(wrapper->NeedsCOW())
if(wrapper->IsDoubleWrapper())
{
#ifdef DEBUG
{