author | Blake Kaplan <mrbkap@gmail.com> |
Tue, 25 Jan 2011 15:06:45 -0800 | |
changeset 61453 | a2825fbe23e39d34451769d44ab0cf2e3a883253 |
parent 61452 | 68931522981d42fd4ca3b8b5f8447d5e73cc52fe |
child 61454 | 8474f8f13bb1ad491364ec4eca67628590628fc8 |
push id | 18358 |
push user | cleary@mozilla.com |
push date | Fri, 28 Jan 2011 04:07:41 +0000 |
treeherder | mozilla-central@787b1e101a5f [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | gal |
bugs | 611485 |
milestone | 2.0b10pre |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/content/base/src/nsContentUtils.cpp +++ b/content/base/src/nsContentUtils.cpp @@ -1518,16 +1518,21 @@ nsContentUtils::GetWindowFromCaller() nsIDOMDocument * nsContentUtils::GetDocumentFromCaller() { JSContext *cx = nsnull; JSObject *obj = nsnull; sXPConnect->GetCaller(&cx, &obj); NS_ASSERTION(cx && obj, "Caller ensures something is running"); + JSAutoEnterCompartment ac; + if (!ac.enter(cx, obj)) { + return nsnull; + } + nsCOMPtr<nsPIDOMWindow> win = do_QueryInterface(nsJSUtils::GetStaticScriptGlobal(cx, obj)); if (!win) { return nsnull; } return win->GetExtantDocument(); }
--- a/js/src/xpconnect/src/xpccomponents.cpp +++ b/js/src/xpconnect/src/xpccomponents.cpp @@ -2817,43 +2817,28 @@ nsXPCComponents_Utils::LookupMethod() // it would a be a big surprise if there is a member without an interface :) XPCNativeInterface* iface = inner_cc.GetInterface(); if(!iface) return NS_ERROR_XPC_BAD_CONVERT_JS; jsval funval; JSFunction *oldfunction; - { - JSAutoEnterCompartment ac; - - if (!ac.enter(inner_cc, wrapper->GetFlatJSObjectAndMark())) { - return NS_ERROR_UNEXPECTED; - } - - // get (and perhaps lazily create) the member's cloned function - if(!member->NewFunctionObject(inner_cc, iface, - wrapper->GetFlatJSObjectAndMark(), - &funval)) - return NS_ERROR_XPC_BAD_CONVERT_JS; - - oldfunction = JS_ValueToFunction(inner_cc, funval); - NS_ASSERTION(oldfunction, "Function is not a function"); - } + // get (and perhaps lazily create) the member's cloned function + if(!member->NewFunctionObject(inner_cc, iface, + JSVAL_TO_OBJECT(argv[0]), + &funval)) + return NS_ERROR_XPC_BAD_CONVERT_JS; + + oldfunction = JS_ValueToFunction(inner_cc, funval); + NS_ASSERTION(oldfunction, "Function is not a function"); // Stick the function in the return value. This roots it. *retval = funval; - // Callers of this method are implicitly buying into - // XPCNativeWrapper-like protection. The easiest way to enforce - // this is to let the JS engine wrap the function. - if (!JS_WrapValue(inner_cc, retval)) { - return NS_ERROR_UNEXPECTED; - } - // Tell XPConnect that we returned the function through the call context. cc->SetReturnValueWasSet(PR_TRUE); return NS_OK; } /* void reportError (); */ NS_IMETHODIMP nsXPCComponents_Utils::ReportError()
--- a/js/src/xpconnect/src/xpcwrappednative.cpp +++ b/js/src/xpconnect/src/xpcwrappednative.cpp @@ -1684,17 +1684,18 @@ XPCWrappedNative::GetWrappedNativeOfJSOb XPCWrappedNativeProto* proto = nsnull; nsIClassInfo* protoClassInfo = nsnull; // If we were passed a function object then we need to find the correct // wrapper out of those that might be in the callee obj's proto chain. if(funobj) { - JSObject* funObjParent = funobj->getParent(); + JSObject* funObjParent = funobj->getParent()->unwrap(); + OBJ_TO_INNER_OBJECT(cx, funObjParent); NS_ASSERTION(funObjParent, "funobj has no parent"); js::Class* funObjParentClass = funObjParent->getClass(); if(IS_PROTO_CLASS(funObjParentClass)) { NS_ASSERTION(funObjParent->getParent(), "funobj's parent (proto) is global"); proto = (XPCWrappedNativeProto*) xpc_GetJSPrivate(funObjParent);
--- a/js/src/xpconnect/src/xpcwrappednativeinfo.cpp +++ b/js/src/xpconnect/src/xpcwrappednativeinfo.cpp @@ -88,26 +88,19 @@ xpc_CloneJSFunction(XPCCallContext &ccx, // static JSBool XPCNativeMember::GetCallInfo(XPCCallContext& ccx, JSObject* funobj, XPCNativeInterface** pInterface, XPCNativeMember** pMember) { - jsval ifaceVal; - jsval memberVal; - - if(!JS_GetReservedSlot(ccx, funobj, 0, &ifaceVal) || - JSVAL_IS_VOID(ifaceVal) || - !JS_GetReservedSlot(ccx, funobj, 1, &memberVal) || - JSVAL_IS_VOID(memberVal)) - { - return JS_FALSE; - } + funobj = funobj->unwrap(); + jsval ifaceVal = js::Jsvalify(funobj->getSlot(0)); + jsval memberVal = js::Jsvalify(funobj->getSlot(1)); *pInterface = (XPCNativeInterface*) JSVAL_TO_PRIVATE(ifaceVal); *pMember = (XPCNativeMember*) JSVAL_TO_PRIVATE(memberVal); return JS_TRUE; } JSBool
--- a/js/src/xpconnect/tests/chrome/test_bug448587.xul +++ b/js/src/xpconnect/tests/chrome/test_bug448587.xul @@ -20,12 +20,13 @@ https://bugzilla.mozilla.org/show_bug.cg <!-- test code goes here --> <script type="application/javascript"> <![CDATA[ /** Test for Bug 448587 **/ const Cu = Components.utils; var sandbox = new Cu.Sandbox("about:blank"); var fwrapper = Cu.evalInSandbox("function f() {} f", sandbox); - ok(fwrapper.prototype == Cu.evalInSandbox("f.prototype", sandbox)); + is(fwrapper.prototype, Cu.evalInSandbox("f.prototype", sandbox), + "we don't censor .prototype through .wrappedJSObject"); ]]> </script> </window>
--- a/js/src/xpconnect/wrappers/CrossOriginWrapper.cpp +++ b/js/src/xpconnect/wrappers/CrossOriginWrapper.cpp @@ -41,17 +41,25 @@ #include "XPCWrapper.h" #include "CrossOriginWrapper.h" #include "WrapperFactory.h" namespace xpc { -CrossOriginWrapper::CrossOriginWrapper(uintN flags) : JSCrossCompartmentWrapper(flags) +NoWaiverWrapper::NoWaiverWrapper(uintN flags) : JSCrossCompartmentWrapper(flags) +{ +} + +NoWaiverWrapper::~NoWaiverWrapper() +{ +} + +CrossOriginWrapper::CrossOriginWrapper(uintN flags) : NoWaiverWrapper(flags) { } CrossOriginWrapper::~CrossOriginWrapper() { } static nsIPrincipal * @@ -95,17 +103,17 @@ bool CrossOriginWrapper::construct(JSContext *cx, JSObject *wrapper, uintN argc, js::Value *argv, js::Value *rval) { return JSCrossCompartmentWrapper::construct(cx, wrapper, argc, argv, rval) && WrapperFactory::WaiveXrayAndWrap(cx, js::Jsvalify(rval)); } bool -CrossOriginWrapper::enter(JSContext *cx, JSObject *wrapper, jsid id, Action act) +NoWaiverWrapper::enter(JSContext *cx, JSObject *wrapper, jsid id, Action act) { nsIScriptSecurityManager *ssm = XPCWrapper::GetSecurityManager(); if (!ssm) { return true; } JSStackFrame *fp = NULL; nsIPrincipal *principal = GetCompartmentPrincipal(wrappedObject(wrapper)->compartment()); nsresult rv = ssm->PushContextPrincipal(cx, JS_FrameIterator(cx, &fp), principal); @@ -113,17 +121,17 @@ CrossOriginWrapper::enter(JSContext *cx, 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) +NoWaiverWrapper::leave(JSContext *cx, JSObject *wrapper) { nsIScriptSecurityManager *ssm = XPCWrapper::GetSecurityManager(); if (ssm) { ssm->PopContextPrincipal(cx); } } }
--- a/js/src/xpconnect/wrappers/CrossOriginWrapper.h +++ b/js/src/xpconnect/wrappers/CrossOriginWrapper.h @@ -40,33 +40,41 @@ #ifndef __CrossOriginWrapper_h__ #define __CrossOriginWrapper_h__ #include "jsapi.h" #include "jswrapper.h" namespace xpc { -class CrossOriginWrapper : public JSCrossCompartmentWrapper { +class NoWaiverWrapper : public JSCrossCompartmentWrapper { + public: + NoWaiverWrapper(uintN flags); + virtual ~NoWaiverWrapper(); + + virtual bool enter(JSContext *cx, JSObject *wrapper, jsid id, Action act); + virtual void leave(JSContext *cx, JSObject *wrapper); + + static NoWaiverWrapper singleton; +}; + +class CrossOriginWrapper : public NoWaiverWrapper { public: CrossOriginWrapper(uintN flags); virtual ~CrossOriginWrapper(); virtual bool getPropertyDescriptor(JSContext *cx, JSObject *wrapper, jsid id, bool set, js::PropertyDescriptor *desc); virtual bool getOwnPropertyDescriptor(JSContext *cx, JSObject *wrapper, jsid id, bool set, js::PropertyDescriptor *desc); virtual bool get(JSContext *cx, JSObject *wrapper, JSObject *receiver, jsid id, js::Value *vp); virtual bool call(JSContext *cx, JSObject *wrapper, uintN argc, js::Value *vp); virtual bool construct(JSContext *cx, JSObject *wrapper, uintN argc, js::Value *argv, js::Value *rval); - virtual bool enter(JSContext *cx, JSObject *wrapper, jsid id, Action act); - virtual void leave(JSContext *cx, JSObject *wrapper); - static CrossOriginWrapper singleton; }; } #endif
--- a/js/src/xpconnect/wrappers/FilteringWrapper.cpp +++ b/js/src/xpconnect/wrappers/FilteringWrapper.cpp @@ -147,22 +147,22 @@ FilteringWrapper<Base, Policy>::enter(JS Permission perm; return CheckAndReport<Policy>(cx, wrapper, id, act, perm) && Base::enter(cx, wrapper, id, act); } #define SOW FilteringWrapper<JSCrossCompartmentWrapper, OnlyIfSubjectIsSystem> #define SCSOW FilteringWrapper<JSWrapper, OnlyIfSubjectIsSystem> #define COW FilteringWrapper<JSCrossCompartmentWrapper, ExposedPropertiesOnly> -#define XOW FilteringWrapper<XrayWrapper<JSCrossCompartmentWrapper, CrossCompartmentXray>, \ +#define XOW FilteringWrapper<XrayWrapper<JSCrossCompartmentWrapper>, \ CrossOriginAccessiblePropertiesOnly> #define NNXOW FilteringWrapper<JSCrossCompartmentWrapper, CrossOriginAccessiblePropertiesOnly> -#define LW FilteringWrapper<XrayWrapper<JSWrapper, SameCompartmentXray>, \ +#define LW FilteringWrapper<XrayWrapper<JSWrapper>, \ SameOriginOrCrossOriginAccessiblePropertiesOnly> -#define XLW FilteringWrapper<XrayWrapper<JSCrossCompartmentWrapper, CrossCompartmentXray>, \ +#define XLW FilteringWrapper<XrayWrapper<JSCrossCompartmentWrapper>, \ SameOriginOrCrossOriginAccessiblePropertiesOnly> template<> SOW SOW::singleton(WrapperFactory::SCRIPT_ACCESS_ONLY_FLAG | WrapperFactory::SOW_FLAG); template<> SCSOW SCSOW::singleton(WrapperFactory::SCRIPT_ACCESS_ONLY_FLAG | WrapperFactory::SOW_FLAG); template<> COW COW::singleton(0); template<> XOW XOW::singleton(WrapperFactory::SCRIPT_ACCESS_ONLY_FLAG |
--- a/js/src/xpconnect/wrappers/WrapperFactory.cpp +++ b/js/src/xpconnect/wrappers/WrapperFactory.cpp @@ -56,16 +56,23 @@ namespace xpc { // .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); +// Objects that haven't been explicitly waived, but have been exposed +// to chrome don't want a CrossOriginWrapper, since that deeply-waives +// but need the transparent behavior of a CrossOriginWrapper. The +// NoWaiverWrapper is like a CrossOriginWrapper that can also hand out +// XrayWrappers as return values. +NoWaiverWrapper NoWaiverWrapper::singleton(0); + // 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. CrossOriginWrapper CrossOriginWrapper::singleton(0); static JSObject * GetCurrentOuter(JSContext *cx, JSObject *obj) @@ -239,33 +246,32 @@ WrapperFactory::Rewrap(JSContext *cx, JS JSCompartment *origin = obj->compartment(); JSCompartment *target = cx->compartment; JSObject *xrayHolder = nsnull; JSWrapper *wrapper; CompartmentPrivate *targetdata = static_cast<CompartmentPrivate *>(target->data); if (AccessCheck::isChrome(target)) { - if (AccessCheck::isChrome(origin)) { + if (AccessCheck::isChrome(origin) || obj->getGlobal()->isSystem()) { wrapper = &JSCrossCompartmentWrapper::singleton; } else if (flags & WAIVE_XRAY_WRAPPER_FLAG) { // If we waived the X-ray wrapper for this object, wrap it into a // special wrapper to transitively maintain the X-ray waiver. wrapper = &CrossOriginWrapper::singleton; } else { // Native objects must be wrapped into an X-ray wrapper. - if (!obj->getGlobal()->isSystem() && - (IS_WN_WRAPPER(obj) || obj->getClass()->ext.innerObject)) { - typedef XrayWrapper<JSCrossCompartmentWrapper, CrossCompartmentXray> Xray; + if (IS_WN_WRAPPER(obj) || obj->getClass()->ext.innerObject) { + typedef XrayWrapper<JSCrossCompartmentWrapper> Xray; wrapper = &Xray::singleton; xrayHolder = Xray::createHolder(cx, obj, parent); if (!xrayHolder) return nsnull; } else { - wrapper = &JSCrossCompartmentWrapper::singleton; + wrapper = &NoWaiverWrapper::singleton; } } } else if (AccessCheck::isChrome(origin)) { if (obj->isFunction()) { JSFunction *fun = obj->getFunctionPrivate(); if (js::IsBuiltinEvalFunction(fun) || js::IsBuiltinFunctionConstructor(fun)) { JS_ReportError(cx, "Not allowed to access chrome eval or Function from content"); return nsnull; @@ -276,17 +282,17 @@ WrapperFactory::Rewrap(JSContext *cx, JS } else if (AccessCheck::isSameOrigin(origin, target)) { // Same origin we use a transparent wrapper, unless the compartment asks // for an Xray or the wrapper needs a SOW. if (AccessCheck::needsSystemOnlyWrapper(obj)) { wrapper = &FilteringWrapper<JSCrossCompartmentWrapper, OnlyIfSubjectIsSystem>::singleton; } else if (targetdata && targetdata->wantXrays && (IS_WN_WRAPPER(obj) || obj->getClass()->ext.innerObject)) { - typedef XrayWrapper<JSCrossCompartmentWrapper, CrossCompartmentXray> Xray; + typedef XrayWrapper<JSCrossCompartmentWrapper> Xray; wrapper = &Xray::singleton; xrayHolder = Xray::createHolder(cx, obj, parent); if (!xrayHolder) return nsnull; } else { wrapper = &JSCrossCompartmentWrapper::singleton; } } else { @@ -296,17 +302,17 @@ WrapperFactory::Rewrap(JSContext *cx, JS // 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. if (!IS_WN_WRAPPER(obj) && !obj->getClass()->ext.innerObject) { wrapper = &FilteringWrapper<JSCrossCompartmentWrapper, CrossOriginAccessiblePropertiesOnly>::singleton; } else { - typedef XrayWrapper<JSCrossCompartmentWrapper, CrossCompartmentXray> Xray; + typedef XrayWrapper<JSCrossCompartmentWrapper> Xray; // Location objects can become same origin after navigation, so we might // have to grant transparent access later on. if (IsLocationObject(obj)) { wrapper = &FilteringWrapper<Xray, SameOriginOrCrossOriginAccessiblePropertiesOnly>::singleton; } else { wrapper= &FilteringWrapper<Xray, @@ -324,17 +330,17 @@ WrapperFactory::Rewrap(JSContext *cx, JS return wrapperObj; // NB: The fact that the only wrappers to use ProxyExtra are XrayWrappers // is relied on by XPCNativeWrapper.unwrap. wrapperObj->setProxyExtra(js::ObjectValue(*xrayHolder)); return wrapperObj; } -typedef FilteringWrapper<XrayWrapper<JSWrapper, SameCompartmentXray>, +typedef FilteringWrapper<XrayWrapper<JSWrapper>, SameOriginOrCrossOriginAccessiblePropertiesOnly> LW; bool WrapperFactory::IsLocationObject(JSObject *obj) { const char *name = obj->getClass()->name; return name[0] == 'L' && !strcmp(name, "Location"); }
--- a/js/src/xpconnect/wrappers/XrayWrapper.cpp +++ b/js/src/xpconnect/wrappers/XrayWrapper.cpp @@ -268,55 +268,42 @@ ResolveNativeProperty(JSContext *cx, JSO jsval fval = 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. - - JSAutoEnterCompartment ac; - if (!ac.enter(cx, wnObject)) - return false; - - if (!member->NewFunctionObject(ccx, iface, wnObject, &fval)) { + if (!member->NewFunctionObject(ccx, iface, wrapper, &fval)) { JS_ReportError(cx, "Failed to clone function object for native getter/setter"); return false; } desc->attrs |= JSPROP_GETTER; if (member->IsWritableAttribute()) 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 { - JSAutoEnterCompartment ac; - if (!ac.enter(cx, wnObject)) - return false; - // This is a method. Clone a function for it. - if (!member->NewFunctionObject(ccx, iface, wnObject, &desc->value)) { + if (!member->NewFunctionObject(ccx, iface, wrapper, &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; } - JSAutoEnterCompartment ac; - if (!ac.enter(cx, holder)) - return false; - if (!JS_WrapValue(cx, &desc->value) || !JS_WrapValue(cx, &fval)) return false; if (desc->attrs & JSPROP_GETTER) desc->getter = CastAsJSPropertyOp(JSVAL_TO_OBJECT(fval)); if (desc->attrs & JSPROP_SETTER) desc->setter = desc->getter; @@ -361,42 +348,42 @@ XrayToString(JSContext *cx, uintN argc, result.Length()); if (!str) return false; *vp = STRING_TO_JSVAL(str); return true; } -template <typename Base, typename Policy> -XrayWrapper<Base, Policy>::XrayWrapper(uintN flags) +template <typename Base> +XrayWrapper<Base>::XrayWrapper(uintN flags) : Base(flags | WrapperFactory::IS_XRAY_WRAPPER_FLAG) { } -template <typename Base, typename Policy> -XrayWrapper<Base, Policy>::~XrayWrapper() +template <typename Base> +XrayWrapper<Base>::~XrayWrapper() { } -template <typename Base, typename Policy> +template <typename Base> class AutoLeaveHelper { public: - AutoLeaveHelper(XrayWrapper<Base, Policy> &xray, JSContext *cx, JSObject *wrapper) + AutoLeaveHelper(XrayWrapper<Base> &xray, JSContext *cx, JSObject *wrapper) : xray(xray), cx(cx), wrapper(wrapper) { } ~AutoLeaveHelper() { xray.leave(cx, wrapper); } private: - XrayWrapper<Base, Policy> &xray; + XrayWrapper<Base> &xray; JSContext *cx; JSObject *wrapper; }; static bool Transparent(JSContext *cx, JSObject *wrapper) { if (WrapperFactory::HasWaiveXrayFlag(wrapper)) @@ -421,28 +408,28 @@ namespace XrayUtils { bool IsTransparent(JSContext *cx, JSObject *wrapper) { return Transparent(cx, wrapper); } } -template <typename Base, typename Policy> +template <typename Base> bool -XrayWrapper<Base, Policy>::resolveOwnProperty(JSContext *cx, JSObject *wrapper, jsid id, bool set, - PropertyDescriptor *desc_in) +XrayWrapper<Base>::resolveOwnProperty(JSContext *cx, JSObject *wrapper, jsid id, bool set, + PropertyDescriptor *desc_in) { JSPropertyDescriptor *desc = Jsvalify(desc_in); if (id == nsXPConnect::GetRuntimeInstance()->GetStringID(XPCJSRuntime::IDX_WRAPPED_JSOBJECT)) { if (!this->enter(cx, wrapper, id, set ? JSWrapper::SET : JSWrapper::GET)) return false; - AutoLeaveHelper<Base, Policy> helper(*this, cx, wrapper); + AutoLeaveHelper<Base> helper(*this, cx, wrapper); desc->obj = wrapper; desc->attrs = JSPROP_ENUMERATE|JSPROP_SHARED; desc->getter = wrappedJSObject_getter; desc->setter = NULL; desc->shortid = 0; desc->value = JSVAL_VOID; return true; @@ -489,32 +476,32 @@ XrayWrapper<Base, Policy>::resolveOwnPro return true; } } desc->obj = nsnull; return true; } -template <typename Base, typename Policy> +template <typename Base> bool -XrayWrapper<Base, Policy>::getPropertyDescriptor(JSContext *cx, JSObject *wrapper, jsid id, - bool set, PropertyDescriptor *desc_in) +XrayWrapper<Base>::getPropertyDescriptor(JSContext *cx, JSObject *wrapper, jsid id, + bool set, PropertyDescriptor *desc_in) { JSPropertyDescriptor *desc = Jsvalify(desc_in); JSObject *holder = GetHolder(wrapper); if (IsResolving(holder, id)) { desc->obj = NULL; return true; } if (!this->enter(cx, wrapper, id, set ? JSWrapper::SET : JSWrapper::GET)) return false; - AutoLeaveHelper<Base, Policy> helper(*this, cx, wrapper); + AutoLeaveHelper<Base> helper(*this, cx, wrapper); ResolvingId resolving(holder, id); // Redirect access straight to the wrapper if we should be transparent. if (Transparent(cx, wrapper)) { JSObject *wnObject = GetWrappedNativeObjectFromHolder(cx, holder); { @@ -533,22 +520,17 @@ XrayWrapper<Base, Policy>::getPropertyDe } if (!this->resolveOwnProperty(cx, wrapper, id, set, desc_in)) return false; if (desc->obj) return true; - void *priv; - if (!Policy::enter(cx, wrapper, &id, set ? JSWrapper::SET : JSWrapper::GET, &priv)) - return false; - bool ok = ResolveNativeProperty(cx, wrapper, holder, id, set, desc); - Policy::leave(cx, wrapper, priv); if (!ok || desc->obj) return ok; if (id == nsXPConnect::GetRuntimeInstance()->GetStringID(XPCJSRuntime::IDX_TO_STRING)) { desc->obj = wrapper; desc->attrs = 0; desc->getter = NULL; desc->setter = NULL; @@ -559,32 +541,32 @@ XrayWrapper<Base, Policy>::getPropertyDe return false; desc->value = OBJECT_TO_JSVAL(toString); return true; } return true; } -template <typename Base, typename Policy> +template <typename Base> bool -XrayWrapper<Base, Policy>::getOwnPropertyDescriptor(JSContext *cx, JSObject *wrapper, jsid id, - bool set, PropertyDescriptor *desc_in) +XrayWrapper<Base>::getOwnPropertyDescriptor(JSContext *cx, JSObject *wrapper, jsid id, + bool set, PropertyDescriptor *desc_in) { JSPropertyDescriptor *desc = Jsvalify(desc_in); JSObject *holder = GetHolder(wrapper); if (IsResolving(holder, id)) { desc->obj = NULL; return true; } if (!this->enter(cx, wrapper, id, set ? JSWrapper::SET : JSWrapper::GET)) return false; - AutoLeaveHelper<Base, Policy> helper(*this, cx, wrapper); + AutoLeaveHelper<Base> helper(*this, cx, wrapper); ResolvingId resolving(holder, id); // NB: Nothing we do here acts on the wrapped native itself, so we don't // enter our policy. // Redirect access straight to the wrapper if we should be transparent. if (Transparent(cx, wrapper)) { JSObject *wnObject = GetWrappedNativeObjectFromHolder(cx, holder); @@ -603,20 +585,20 @@ XrayWrapper<Base, Policy>::getOwnPropert desc->obj = (desc->obj == wnObject) ? wrapper : nsnull; return cx->compartment->wrap(cx, desc_in); } return this->resolveOwnProperty(cx, wrapper, id, set, desc_in); } -template <typename Base, typename Policy> +template <typename Base> bool -XrayWrapper<Base, Policy>::defineProperty(JSContext *cx, JSObject *wrapper, jsid id, - js::PropertyDescriptor *desc) +XrayWrapper<Base>::defineProperty(JSContext *cx, JSObject *wrapper, jsid id, + js::PropertyDescriptor *desc) { JSObject *holder = GetHolder(wrapper); JSPropertyDescriptor *jsdesc = Jsvalify(desc); // Redirect access straight to the wrapper if we should be transparent. if (Transparent(cx, wrapper)) { JSObject *wnObject = GetWrappedNativeObjectFromHolder(cx, holder); @@ -701,27 +683,27 @@ EnumerateNames(JSContext *cx, JSObject * if (!JS_HasPropertyById(cx, wrapper, id, &hasProp)) return false; if (hasProp) props.append(id); } return true; } -template <typename Base, typename Policy> +template <typename Base> bool -XrayWrapper<Base, Policy>::getOwnPropertyNames(JSContext *cx, JSObject *wrapper, - js::AutoIdVector &props) +XrayWrapper<Base>::getOwnPropertyNames(JSContext *cx, JSObject *wrapper, + js::AutoIdVector &props) { return EnumerateNames(cx, wrapper, JSITER_OWNONLY | JSITER_HIDDEN, props); } -template <typename Base, typename Policy> +template <typename Base> bool -XrayWrapper<Base, Policy>::delete_(JSContext *cx, JSObject *wrapper, jsid id, bool *bp) +XrayWrapper<Base>::delete_(JSContext *cx, JSObject *wrapper, jsid id, bool *bp) { JSObject *holder = GetHolder(wrapper); jsval v; JSBool b; // Redirect access straight to the wrapper if we should be transparent. if (Transparent(cx, wrapper)) { JSObject *wnObject = GetWrappedNativeObjectFromHolder(cx, holder); @@ -743,88 +725,147 @@ XrayWrapper<Base, Policy>::delete_(JSCon !JS_ValueToBoolean(cx, v, &b))) { return false; } *bp = !!b; return true; } -template <typename Base, typename Policy> +template <typename Base> bool -XrayWrapper<Base, Policy>::enumerate(JSContext *cx, JSObject *wrapper, js::AutoIdVector &props) +XrayWrapper<Base>::enumerate(JSContext *cx, JSObject *wrapper, js::AutoIdVector &props) { return EnumerateNames(cx, wrapper, 0, props); } -template <typename Base, typename Policy> +template <typename Base> bool -XrayWrapper<Base, Policy>::fix(JSContext *cx, JSObject *proxy, js::Value *vp) +XrayWrapper<Base>::fix(JSContext *cx, JSObject *proxy, js::Value *vp) { vp->setUndefined(); return true; } -template <typename Base, typename Policy> +template <typename Base> bool -XrayWrapper<Base, Policy>::get(JSContext *cx, JSObject *wrapper, JSObject *receiver, jsid id, - js::Value *vp) +XrayWrapper<Base>::get(JSContext *cx, JSObject *wrapper, JSObject *receiver, jsid id, + js::Value *vp) { // Skip our Base if it isn't already JSProxyHandler. // NB: None of the functions we call are prepared for the receiver not // being the wrapper, so ignore the receiver here. return JSProxyHandler::get(cx, wrapper, wrapper, id, vp); } -template <typename Base, typename Policy> +template <typename Base> bool -XrayWrapper<Base, Policy>::set(JSContext *cx, JSObject *wrapper, JSObject *receiver, jsid id, - js::Value *vp) +XrayWrapper<Base>::set(JSContext *cx, JSObject *wrapper, JSObject *receiver, jsid id, + js::Value *vp) { // Skip our Base if it isn't already JSProxyHandler. // NB: None of the functions we call are prepared for the receiver not // being the wrapper, so ignore the receiver here. return JSProxyHandler::set(cx, wrapper, wrapper, id, vp); } -template <typename Base, typename Policy> +template <typename Base> bool -XrayWrapper<Base, Policy>::has(JSContext *cx, JSObject *wrapper, jsid id, bool *bp) +XrayWrapper<Base>::has(JSContext *cx, JSObject *wrapper, jsid id, bool *bp) { // Skip our Base if it isn't already JSProxyHandler. return JSProxyHandler::has(cx, wrapper, id, bp); } -template <typename Base, typename Policy> +template <typename Base> bool -XrayWrapper<Base, Policy>::hasOwn(JSContext *cx, JSObject *wrapper, jsid id, bool *bp) +XrayWrapper<Base>::hasOwn(JSContext *cx, JSObject *wrapper, jsid id, bool *bp) { // Skip our Base if it isn't already JSProxyHandler. return JSProxyHandler::hasOwn(cx, wrapper, id, bp); } -template <typename Base, typename Policy> +template <typename Base> bool -XrayWrapper<Base, Policy>::keys(JSContext *cx, JSObject *wrapper, js::AutoIdVector &props) +XrayWrapper<Base>::keys(JSContext *cx, JSObject *wrapper, js::AutoIdVector &props) { // Skip our Base if it isn't already JSProxyHandler. return JSProxyHandler::keys(cx, wrapper, props); } -template <typename Base, typename Policy> +template <typename Base> bool -XrayWrapper<Base, Policy>::iterate(JSContext *cx, JSObject *wrapper, uintN flags, js::Value *vp) +XrayWrapper<Base>::iterate(JSContext *cx, JSObject *wrapper, uintN flags, js::Value *vp) { // Skip our Base if it isn't already JSProxyHandler. return JSProxyHandler::iterate(cx, wrapper, flags, vp); } -template <typename Base, typename Policy> +template <typename Base> +bool +XrayWrapper<Base>::call(JSContext *cx, JSObject *wrapper, uintN argc, js::Value *vp) +{ + JSObject *holder = GetHolder(wrapper); + JSObject *wnObject = GetWrappedNativeObjectFromHolder(cx, holder); + XPCWrappedNative *wn = GetWrappedNative(wnObject); + + // Run the resolve hook of the wrapped native. + if (NATIVE_HAS_FLAG(wn, WantCall)) { + XPCCallContext ccx(JS_CALLER, cx, wrapper, nsnull, JSID_VOID, argc, + Jsvalify(vp + 2), Jsvalify(vp)); + if (!ccx.IsValid()) + return false; + PRBool ok = PR_TRUE; + nsresult rv = wn->GetScriptableInfo()->GetCallback()->Call(wn, cx, wrapper, + argc, Jsvalify(vp + 2), + Jsvalify(vp), &ok); + if (NS_FAILED(rv)) { + if (ok) + XPCThrower::Throw(rv, cx); + return false; + } + } + + return true; +} + +template <typename Base> +bool +XrayWrapper<Base>::construct(JSContext *cx, JSObject *wrapper, uintN argc, + js::Value *argv, js::Value *rval) +{ + JSObject *holder = GetHolder(wrapper); + JSObject *wnObject = GetWrappedNativeObjectFromHolder(cx, holder); + XPCWrappedNative *wn = GetWrappedNative(wnObject); + + // Run the resolve hook of the wrapped native. + if (NATIVE_HAS_FLAG(wn, WantConstruct)) { + XPCCallContext ccx(JS_CALLER, cx, wrapper, nsnull, JSID_VOID, argc, + Jsvalify(argv), Jsvalify(rval)); + if (!ccx.IsValid()) + return false; + PRBool ok = PR_TRUE; + nsresult rv = wn->GetScriptableInfo()->GetCallback()->Construct(wn, cx, wrapper, + argc, + Jsvalify(argv), + Jsvalify(rval), + &ok); + if (NS_FAILED(rv)) { + if (ok) + XPCThrower::Throw(rv, cx); + return false; + } + } + + return true; +} + +template <typename Base> JSObject * -XrayWrapper<Base, Policy>::createHolder(JSContext *cx, JSObject *wrappedNative, JSObject *parent) +XrayWrapper<Base>::createHolder(JSContext *cx, JSObject *wrappedNative, JSObject *parent) { JSObject *holder = JS_NewObjectWithGivenProto(cx, &HolderClass, nsnull, parent); if (!holder) return nsnull; CompartmentPrivate *priv = (CompartmentPrivate *)JS_GetCompartmentPrivate(cx, holder->compartment()); JSObject *inner = wrappedNative; @@ -835,37 +876,18 @@ XrayWrapper<Base, Policy>::createHolder( JS_ASSERT(IS_WN_WRAPPER(wrappedNative) || wrappedNative->getClass()->ext.innerObject); holder->setSlot(JSSLOT_WN_OBJ, ObjectValue(*wrappedNative)); holder->setSlot(JSSLOT_RESOLVING, PrivateValue(NULL)); holder->setSlot(JSSLOT_EXPANDO, expando); return holder; } -bool -CrossCompartmentXray::enter(JSContext *cx, JSObject *wrapper, jsid *idp, - JSWrapper::Action act, void **priv) -{ - JSObject *target = wrapper->unwrap(); - JSCrossCompartmentCall *call = JS_EnterCrossCompartmentCall(cx, target); - if (!call) - return false; - - *priv = call; - return true; -} - -void -CrossCompartmentXray::leave(JSContext *cx, JSObject *wrapper, void *priv) -{ - JS_LeaveCrossCompartmentCall(static_cast<JSCrossCompartmentCall *>(priv)); -} - -#define XPCNW XrayWrapper<JSCrossCompartmentWrapper, CrossCompartmentXray> -#define SCNW XrayWrapper<JSWrapper, SameCompartmentXray> +#define XPCNW XrayWrapper<JSCrossCompartmentWrapper> +#define SCNW XrayWrapper<JSWrapper> template <> XPCNW XPCNW::singleton(0); template <> SCNW SCNW::singleton(0); template class XPCNW; template class SCNW; }
--- a/js/src/xpconnect/wrappers/XrayWrapper.h +++ b/js/src/xpconnect/wrappers/XrayWrapper.h @@ -53,17 +53,17 @@ namespace XrayUtils { extern JSClass HolderClass; bool IsTransparent(JSContext *cx, JSObject *wrapper); } // NB: Base *must* derive from JSProxyHandler -template <typename Base, typename Policy> +template <typename Base> class XrayWrapper : public Base { public: XrayWrapper(uintN flags); virtual ~XrayWrapper(); bool resolveWrappedJSObject(JSContext *cx, JSObject *wrapper, jsid id, bool set, js::PropertyDescriptor *desc); @@ -85,34 +85,22 @@ class XrayWrapper : public Base { js::Value *vp); virtual bool set(JSContext *cx, JSObject *wrapper, JSObject *receiver, jsid id, js::Value *vp); virtual bool has(JSContext *cx, JSObject *wrapper, jsid id, bool *bp); virtual bool hasOwn(JSContext *cx, JSObject *wrapper, jsid id, bool *bp); virtual bool keys(JSContext *cx, JSObject *wrapper, js::AutoIdVector &props); virtual bool iterate(JSContext *cx, JSObject *wrapper, uintN flags, js::Value *vp); + virtual bool call(JSContext *cx, JSObject *wrapper, uintN argc, js::Value *vp); + virtual bool construct(JSContext *cx, JSObject *wrapper, + uintN argc, js::Value *argv, js::Value *rval); + static JSObject *createHolder(JSContext *cx, JSObject *wrappedNative, JSObject *parent); static XrayWrapper singleton; private: bool resolveOwnProperty(JSContext *cx, JSObject *wrapper, jsid id, bool set, js::PropertyDescriptor *desc); }; -class CrossCompartmentXray { - public: - static bool enter(JSContext *cx, JSObject *wrapper, jsid *idp, - JSWrapper::Action act, void **priv); - static void leave(JSContext *cx, JSObject *wrapper, void *priv); -}; - -class SameCompartmentXray { - public: - static bool enter(JSContext *, JSObject *, jsid *, JSWrapper::Action, void **) { - return true; - } - static void leave(JSContext *cx, JSObject *wrapper, void *priv) { - } -}; - }