Bug 754044 - Introduce sameCompartmentWrapObjectCallback. r=mrbkap

We leave it null for gecko for the time being to keep this patch small.
This commit is contained in:
Bobby Holley 2012-05-14 23:30:07 +02:00
parent 28257a13d5
commit 0ff9136104
6 changed files with 47 additions and 10 deletions

View File

@ -35,6 +35,13 @@ wrap(JSContext *cx, JSObject *toWrap, JSObject *target)
return wrapper; return wrapper;
} }
static JSObject *
SameCompartmentWrap(JSContext *cx, JSObject *obj)
{
JS_GC(JS_GetRuntime(cx));
return obj;
}
static JSObject * static JSObject *
PreWrap(JSContext *cx, JSObject *scope, JSObject *obj, unsigned flags) PreWrap(JSContext *cx, JSObject *scope, JSObject *obj, unsigned flags)
{ {
@ -78,7 +85,7 @@ BEGIN_TEST(testBug604087)
CHECK(next); CHECK(next);
} }
JS_SetWrapObjectCallbacks(JS_GetRuntime(cx), Wrap, PreWrap); JS_SetWrapObjectCallbacks(JS_GetRuntime(cx), Wrap, SameCompartmentWrap, PreWrap);
CHECK(JS_TransplantObject(cx, outerObj, next)); CHECK(JS_TransplantObject(cx, outerObj, next));
return true; return true;
} }

View File

@ -792,6 +792,7 @@ JSRuntime::JSRuntime()
pendingProxyOperation(NULL), pendingProxyOperation(NULL),
trustedPrincipals_(NULL), trustedPrincipals_(NULL),
wrapObjectCallback(TransparentObjectWrapper), wrapObjectCallback(TransparentObjectWrapper),
sameCompartmentWrapObjectCallback(NULL),
preWrapObjectCallback(NULL), preWrapObjectCallback(NULL),
preserveWrapperCallback(NULL), preserveWrapperCallback(NULL),
#ifdef DEBUG #ifdef DEBUG
@ -1340,10 +1341,12 @@ JS_SetDestroyCompartmentCallback(JSRuntime *rt, JSDestroyCompartmentCallback cal
JS_PUBLIC_API(JSWrapObjectCallback) JS_PUBLIC_API(JSWrapObjectCallback)
JS_SetWrapObjectCallbacks(JSRuntime *rt, JS_SetWrapObjectCallbacks(JSRuntime *rt,
JSWrapObjectCallback callback, JSWrapObjectCallback callback,
JSSameCompartmentWrapObjectCallback sccallback,
JSPreWrapCallback precallback) JSPreWrapCallback precallback)
{ {
JSWrapObjectCallback old = rt->wrapObjectCallback; JSWrapObjectCallback old = rt->wrapObjectCallback;
rt->wrapObjectCallback = callback; rt->wrapObjectCallback = callback;
rt->sameCompartmentWrapObjectCallback = sccallback;
rt->preWrapObjectCallback = precallback; rt->preWrapObjectCallback = precallback;
return old; return old;
} }

View File

@ -1693,6 +1693,19 @@ typedef JSObject *
typedef JSObject * typedef JSObject *
(* JSPreWrapCallback)(JSContext *cx, JSObject *scope, JSObject *obj, unsigned flags); (* JSPreWrapCallback)(JSContext *cx, JSObject *scope, JSObject *obj, unsigned flags);
/*
* Callback used when wrapping determines that the underlying object is already
* in the compartment for which it is being wrapped. This allows consumers to
* maintain same-compartment wrapping invariants.
*
* |obj| is guaranteed to be same-compartment as |cx|, but it may (or may not)
* be a security or cross-compartment wrapper. This is an unfortunate contract,
* but is important for to avoid unnecessarily recomputing every cross-
* compartment wrapper that gets passed to wrap.
*/
typedef JSObject *
(* JSSameCompartmentWrapObjectCallback)(JSContext *cx, JSObject *obj);
typedef void typedef void
(* JSDestroyCompartmentCallback)(JSFreeOp *fop, JSCompartment *compartment); (* JSDestroyCompartmentCallback)(JSFreeOp *fop, JSCompartment *compartment);
@ -2783,6 +2796,7 @@ JS_SetDestroyCompartmentCallback(JSRuntime *rt, JSDestroyCompartmentCallback cal
extern JS_PUBLIC_API(JSWrapObjectCallback) extern JS_PUBLIC_API(JSWrapObjectCallback)
JS_SetWrapObjectCallbacks(JSRuntime *rt, JS_SetWrapObjectCallbacks(JSRuntime *rt,
JSWrapObjectCallback callback, JSWrapObjectCallback callback,
JSSameCompartmentWrapObjectCallback sccallback,
JSPreWrapCallback precallback); JSPreWrapCallback precallback);
extern JS_PUBLIC_API(JSCrossCompartmentCall *) extern JS_PUBLIC_API(JSCrossCompartmentCall *)

View File

@ -779,9 +779,10 @@ struct JSRuntime : js::RuntimeFriendFields
/* Tables of strings that are pre-allocated in the atomsCompartment. */ /* Tables of strings that are pre-allocated in the atomsCompartment. */
js::StaticStrings staticStrings; js::StaticStrings staticStrings;
JSWrapObjectCallback wrapObjectCallback; JSWrapObjectCallback wrapObjectCallback;
JSPreWrapCallback preWrapObjectCallback; JSSameCompartmentWrapObjectCallback sameCompartmentWrapObjectCallback;
js::PreserveWrapperCallback preserveWrapperCallback; JSPreWrapCallback preWrapObjectCallback;
js::PreserveWrapperCallback preserveWrapperCallback;
js::ScriptFilenameTable scriptFilenameTable; js::ScriptFilenameTable scriptFilenameTable;

View File

@ -132,6 +132,19 @@ JSCompartment::setNeedsBarrier(bool needs)
needsBarrier_ = needs; needsBarrier_ = needs;
} }
static bool
WrapForSameCompartment(JSContext *cx, JSObject *obj, Value *vp)
{
JS_ASSERT(cx->compartment == obj->compartment());
if (cx->runtime->sameCompartmentWrapObjectCallback) {
obj = cx->runtime->sameCompartmentWrapObjectCallback(cx, obj);
if (!obj)
return false;
}
vp->setObject(*obj);
return true;
}
bool bool
JSCompartment::wrap(JSContext *cx, Value *vp) JSCompartment::wrap(JSContext *cx, Value *vp)
{ {
@ -179,9 +192,8 @@ JSCompartment::wrap(JSContext *cx, Value *vp)
if (vp->isObject()) { if (vp->isObject()) {
JSObject *obj = &vp->toObject(); JSObject *obj = &vp->toObject();
/* If the object is already in this compartment, we are done. */
if (obj->compartment() == this) if (obj->compartment() == this)
return true; return WrapForSameCompartment(cx, obj, vp);
/* Translate StopIteration singleton. */ /* Translate StopIteration singleton. */
if (obj->isStopIteration()) if (obj->isStopIteration())
@ -190,9 +202,8 @@ JSCompartment::wrap(JSContext *cx, Value *vp)
/* Unwrap the object, but don't unwrap outer windows. */ /* Unwrap the object, but don't unwrap outer windows. */
obj = UnwrapObject(&vp->toObject(), /* stopAtOuter = */ true, &flags); obj = UnwrapObject(&vp->toObject(), /* stopAtOuter = */ true, &flags);
vp->setObject(*obj);
if (obj->compartment() == this) if (obj->compartment() == this)
return true; return WrapForSameCompartment(cx, obj, vp);
if (cx->runtime->preWrapObjectCallback) { if (cx->runtime->preWrapObjectCallback) {
obj = cx->runtime->preWrapObjectCallback(cx, global, obj, flags); obj = cx->runtime->preWrapObjectCallback(cx, global, obj, flags);
@ -200,9 +211,9 @@ JSCompartment::wrap(JSContext *cx, Value *vp)
return false; return false;
} }
vp->setObject(*obj);
if (obj->compartment() == this) if (obj->compartment() == this)
return true; return WrapForSameCompartment(cx, obj, vp);
vp->setObject(*obj);
#ifdef DEBUG #ifdef DEBUG
{ {

View File

@ -1999,6 +1999,7 @@ XPCJSRuntime::XPCJSRuntime(nsXPConnect* aXPConnect)
JS_SetGrayGCRootsTracer(mJSRuntime, TraceGrayJS, this); JS_SetGrayGCRootsTracer(mJSRuntime, TraceGrayJS, this);
JS_SetWrapObjectCallbacks(mJSRuntime, JS_SetWrapObjectCallbacks(mJSRuntime,
xpc::WrapperFactory::Rewrap, xpc::WrapperFactory::Rewrap,
NULL,
xpc::WrapperFactory::PrepareForWrapping); xpc::WrapperFactory::PrepareForWrapping);
js::SetPreserveWrapperCallback(mJSRuntime, PreserveWrapper); js::SetPreserveWrapperCallback(mJSRuntime, PreserveWrapper);
#ifdef MOZ_CRASHREPORTER #ifdef MOZ_CRASHREPORTER