XPCVariant::XPCVariant(XPCCallContext& ccx, jsval aJSVal) : mJSVal(aJSVal) { nsVariant::Initialize(&mData); if(!JSVAL_IS_PRIMITIVE(mJSVal)) { JSObject *obj = JSVAL_TO_OBJECT(mJSVal); OBJ_TO_INNER_OBJECT(ccx, obj); mJSVal = OBJECT_TO_JSVAL(obj); // If the incoming object is an XPCWrappedNative, then it could be a // double-wrapped object, and we should return the double-wrapped // object back out to script. JSObject* proto; XPCWrappedNative* wn = XPCWrappedNative::GetWrappedNativeOfJSObject(ccx, JSVAL_TO_OBJECT(mJSVal), nsnull, &proto); mReturnRawObject = !wn && !proto; } else mReturnRawObject = JS_FALSE; }
static JSObject * GetScopeFunction(JSContext *cx, JSObject *outerObj) { jsval v; if (!JS_GetReservedSlot(cx, outerObj, sScopeFunSlot, &v)) { return nsnull; } JSObject *unsafeObj = GetUnsafeObject(outerObj); JSObject *scopeobj = JS_GetGlobalForObject(cx, unsafeObj); OBJ_TO_INNER_OBJECT(cx, scopeobj); if (!scopeobj) { return nsnull; } if (JSVAL_IS_OBJECT(v)) { JSObject *funobj = JSVAL_TO_OBJECT(v); if (JS_GetGlobalForObject(cx, funobj) == scopeobj) { return funobj; } } JSFunction *fun = JS_NewFunction(cx, DummyNative, 0, 0, scopeobj, "SJOWContentBoundary"); if (!fun) { return nsnull; } JSObject *funobj = JS_GetFunctionObject(fun); if (!JS_SetReservedSlot(cx, outerObj, sScopeFunSlot, OBJECT_TO_JSVAL(funobj))) { return nsnull; } return funobj; }
static XPCWrappedNative * GetWrappedNative(JSContext *cx, JSObject *obj) { OBJ_TO_INNER_OBJECT(cx, obj); return IS_WN_WRAPPER(obj) ? static_cast<XPCWrappedNative *>(obj->getPrivate()) : nsnull; }
JSBool WrapObject(JSContext *cx, JSObject *parent, jsval *vp, XPCWrappedNative* wn) { NS_ASSERTION(XPCPerThreadData::IsMainThread(cx), "Can't do this off the main thread!"); // Our argument should be a wrapped native object, but the caller may have // passed it in as an optimization. JSObject *wrappedObj; if (JSVAL_IS_PRIMITIVE(*vp) || !(wrappedObj = JSVAL_TO_OBJECT(*vp)) || wrappedObj->getClass() == &XOWClass) { return JS_TRUE; } if (!wn && !(wn = XPCWrappedNative::GetAndMorphWrappedNativeOfJSObject(cx, wrappedObj))) { return JS_TRUE; } CheckWindow(wn); // The parent must be the inner global object for its scope. parent = JS_GetGlobalForObject(cx, parent); OBJ_TO_INNER_OBJECT(cx, parent); if (!parent) { return JS_FALSE; } XPCWrappedNativeWithXOW *wnxow = nsnull; if (wn->NeedsXOW()) { JSObject *innerWrappedObj = wrappedObj; OBJ_TO_INNER_OBJECT(cx, innerWrappedObj); if (!innerWrappedObj) { return JS_FALSE; } if (innerWrappedObj == parent) { wnxow = static_cast<XPCWrappedNativeWithXOW *>(wn); JSObject *xow = wnxow->GetXOW(); if (xow) { *vp = OBJECT_TO_JSVAL(xow); return JS_TRUE; } } } XPCWrappedNative *parentwn = XPCWrappedNative::GetWrappedNativeOfJSObject(cx, parent); XPCWrappedNativeScope *parentScope; if (NS_LIKELY(parentwn)) { parentScope = parentwn->GetScope(); } else { parentScope = XPCWrappedNativeScope::FindInJSObjectScope(cx, parent); } JSObject *outerObj = nsnull; WrappedNative2WrapperMap *map = parentScope->GetWrapperMap(); outerObj = map->Find(wrappedObj); if (outerObj) { NS_ASSERTION(outerObj->getClass() == &XOWClass, "What crazy object are we getting here?"); *vp = OBJECT_TO_JSVAL(outerObj); if (wnxow) { // NB: wnxow->GetXOW() must have returned false. SetFlags(cx, outerObj, AddFlags(GetFlags(cx, outerObj), FLAG_IS_CACHED)); wnxow->SetXOW(outerObj); } return JS_TRUE; } outerObj = JS_NewObjectWithGivenProto(cx, js::Jsvalify(&XOWClass), nsnull, parent); if (!outerObj) { return JS_FALSE; } jsval flags = INT_TO_JSVAL(wnxow ? FLAG_IS_CACHED : 0); if (!JS_SetReservedSlot(cx, outerObj, sWrappedObjSlot, *vp) || !JS_SetReservedSlot(cx, outerObj, sFlagsSlot, flags) || !JS_SetReservedSlot(cx, outerObj, XPC_XOW_ScopeSlot, PRIVATE_TO_JSVAL(parentScope))) { return JS_FALSE; } *vp = OBJECT_TO_JSVAL(outerObj); map->Add(wn->GetScope()->GetWrapperMap(), wrappedObj, outerObj); if(wnxow) { wnxow->SetXOW(outerObj); } return JS_TRUE; }
// Returns whether the currently executing code is allowed to access // the wrapper. Uses nsIPrincipal::Subsumes. // |cx| must be the top context on the context stack. // If the subject is allowed to access the object returns NS_OK. If not, // returns NS_ERROR_DOM_PROP_ACCESS_DENIED, returns another error code on // failure. nsresult CanAccessWrapper(JSContext *cx, JSObject *outerObj, JSObject *wrappedObj, JSBool *privilegeEnabled) { // Fast path: If the wrapper and the wrapped object have the same global // object (or if the wrapped object is a outer for the same inner that // the wrapper is parented to), then we don't need to do any more work. if (privilegeEnabled) { *privilegeEnabled = JS_FALSE; } if (outerObj) { JSObject *outerParent = outerObj->getParent(); JSObject *innerParent = wrappedObj->getParent(); if (!innerParent) { innerParent = wrappedObj; OBJ_TO_INNER_OBJECT(cx, innerParent); if (!innerParent) { return NS_ERROR_FAILURE; } } else { innerParent = JS_GetGlobalForObject(cx, innerParent); } if (outerParent == innerParent) { return NS_OK; } } // TODO bug 508928: Refactor this with the XOW security checking code. // Get the subject principal from the execution stack. nsIScriptSecurityManager *ssm = XPCWrapper::GetSecurityManager(); if (!ssm) { ThrowException(NS_ERROR_NOT_INITIALIZED, cx); return NS_ERROR_NOT_INITIALIZED; } JSStackFrame *fp = nsnull; nsIPrincipal *subjectPrin = ssm->GetCxSubjectPrincipalAndFrame(cx, &fp); if (!subjectPrin) { ThrowException(NS_ERROR_FAILURE, cx); return NS_ERROR_FAILURE; } PRBool isSystem = PR_FALSE; nsresult rv = ssm->IsSystemPrincipal(subjectPrin, &isSystem); NS_ENSURE_SUCCESS(rv, rv); if (privilegeEnabled) { *privilegeEnabled = JS_FALSE; } nsCOMPtr<nsIPrincipal> objectPrin; rv = ssm->GetObjectPrincipal(cx, wrappedObj, getter_AddRefs(objectPrin)); if (NS_FAILED(rv)) { return rv; } NS_ASSERTION(objectPrin, "Object didn't have principals?"); // Micro-optimization: don't call into caps if we know the answer. if (subjectPrin == objectPrin) { return NS_OK; } // Now, we have our two principals, compare them! PRBool subsumes; rv = subjectPrin->Subsumes(objectPrin, &subsumes); if (NS_SUCCEEDED(rv) && !subsumes) { // We're about to fail, but make a last effort to see if // UniversalXPConnect was enabled anywhere else on the stack. rv = ssm->IsCapabilityEnabled("UniversalXPConnect", &isSystem); if (NS_SUCCEEDED(rv) && isSystem) { rv = NS_OK; if (privilegeEnabled) { *privilegeEnabled = JS_TRUE; } } else { rv = NS_ERROR_DOM_PROP_ACCESS_DENIED; } } return rv; }