static JSBool delegateToResolver(JSContext *cx, JSObject *obj, const char *name, uintN argc, jsval *argv, jsval *rval) { jsval resolver; if (!JS_GetReservedSlot(cx, obj, SLOT_RESOLVER, &resolver)) return JS_FALSE; JSObject *resolverObj = JSVAL_TO_OBJECT(resolver); jsval *allArgv; uintN allArgc = argc + 2; allArgv = (jsval *)PR_Malloc(allArgc * sizeof(jsval)); if (!JS_GetReservedSlot(cx, obj, SLOT_WRAPPEE, allArgv)) { PR_Free(allArgv); return JS_FALSE; } allArgv[1] = OBJECT_TO_JSVAL(obj); for (unsigned int i = 0; i < argc; i++) allArgv[i + 2] = argv[i]; if (!JS_CallFunctionName(cx, resolverObj, name, allArgc, allArgv, rval)) { PR_Free(allArgv); return JS_FALSE; } PR_Free(allArgv); return JS_TRUE; }
int JavaObject::getObjectId(JSContext* ctx, JSObject* obj) { jsval val; const JSClass* jsClass = JS_GET_CLASS(ctx, obj); if (jsClass != &JavaObjectClass) { Debug::log(Debug::Error) << "JavaObject::getObjectId called on non-JavaObject: " << jsClass->name << Debug::flush; return -1; } if (JSCLASS_RESERVED_SLOTS(jsClass) < 1) { Debug::log(Debug::Error) << "JavaObject::getObjectId -- " << static_cast<void*>(obj) << " has only " << (JSCLASS_RESERVED_SLOTS(jsClass)) << " reserved slots, no objectId present" << Debug::flush; return -1; } #if GECKO_VERSION >= 13000 val = JS_GetReservedSlot(obj, 0); #else if (!JS_GetReservedSlot(ctx, obj, 0, &val)) { Debug::log(Debug::Error) << "Error getting reserved slot" << Debug::flush; return -1; } #endif // TODO: assert JSVAL_IS_INT(val) return JSVAL_TO_INT(val); }
JSObject * xpc_CloneJSFunction(XPCCallContext &ccx, JSObject *funobj, JSObject *parent) { JSObject *clone = JS_CloneFunctionObject(ccx, funobj, parent); if(!clone) return nsnull; AUTO_MARK_JSVAL(ccx, OBJECT_TO_JSVAL(clone)); XPCWrappedNativeScope *scope = XPCWrappedNativeScope::FindInJSObjectScope(ccx, parent); if (!scope) { return nsnull; } // Make sure to break the prototype chain to the function object // we cloned to prevent its scope from leaking into the clones // scope. JS_SetPrototype(ccx, clone, scope->GetPrototypeJSFunction()); // Copy the reserved slots to the clone. jsval ifaceVal, memberVal; if(!JS_GetReservedSlot(ccx, funobj, 0, &ifaceVal) || !JS_GetReservedSlot(ccx, funobj, 1, &memberVal)) return nsnull; if(!JS_SetReservedSlot(ccx, clone, 0, ifaceVal) || !JS_SetReservedSlot(ccx, clone, 1, memberVal)) return nsnull; return clone; }
// Because of the drastically different ways that same- and cross-origin XOWs // work, we have to call JS_ClearScope when a XOW changes from being same- // origin to cross-origin. Normally, there are defined places in Gecko where // this happens and they notify us. However, UniversalXPConnect causes the // same transition without any notifications. We could try to detect when this // happens, but doing so would require calling JS_ClearScope from random // hooks, which is bad. // // The compromise is the UXPCObject. When resolving a property on a XOW as // same-origin because of UniversalXPConnect, we actually resolve it on the // UXPCObject (which is just a XOW for the same object). This causes the JS // engine to do all of its work on another object, not polluting the main // object. However, if the get results in calling a setter, the engine still // uses the regular object as 'this', ensuring that the UXPCObject doesn't // leak to script. static JSObject * GetUXPCObject(JSContext *cx, JSObject *obj) { NS_ASSERTION(STOBJ_GET_CLASS(obj) == &sXPC_XOW_JSClass.base, "wrong object"); jsval v; if (!JS_GetReservedSlot(cx, obj, XPCWrapper::sFlagsSlot, &v)) { return nsnull; } if (HAS_FLAGS(v, FLAG_IS_UXPC_OBJECT)) { return obj; } if (!JS_GetReservedSlot(cx, obj, sUXPCObjectSlot, &v)) { return nsnull; } if (JSVAL_IS_OBJECT(v)) { return JSVAL_TO_OBJECT(v); } JSObject *uxpco = JS_NewObjectWithGivenProto(cx, &sXPC_XOW_JSClass.base, nsnull, STOBJ_GET_PARENT(obj)); if (!uxpco) { return nsnull; } JSAutoTempValueRooter tvr(cx, uxpco); jsval wrappedObj, parentScope; if (!JS_GetReservedSlot(cx, obj, XPCWrapper::sWrappedObjSlot, &wrappedObj) || !JS_GetReservedSlot(cx, obj, XPC_XOW_ScopeSlot, &parentScope)) { return nsnull; } if (!JS_SetReservedSlot(cx, uxpco, XPCWrapper::sWrappedObjSlot, wrappedObj) || !JS_SetReservedSlot(cx, uxpco, XPCWrapper::sFlagsSlot, INT_TO_JSVAL(FLAG_IS_UXPC_OBJECT)) || !JS_SetReservedSlot(cx, uxpco, XPC_XOW_ScopeSlot, parentScope)) { return nsnull; } if (!JS_SetReservedSlot(cx, obj, sUXPCObjectSlot, OBJECT_TO_JSVAL(uxpco))) { return nsnull; } return uxpco; }
static void executeJSFunctionFromReservedSpot(JSContext *cx, JSObject *obj, jsval &dataVal, jsval &retval) { jsval func = JS_GetReservedSlot(obj, 0); if(func == JSVAL_VOID) { return; } jsval thisObj = JS_GetReservedSlot(obj, 1); JSAutoCompartment ac(cx, obj); if(thisObj == JSVAL_VOID) { JS_CallFunctionValue(cx, obj, func, 1, &dataVal, &retval); } else { assert(!JSVAL_IS_PRIMITIVE(thisObj)); JS_CallFunctionValue(cx, JSVAL_TO_OBJECT(thisObj), func, 1, &dataVal, &retval); } }
static void executeJSFunctionFromReservedSpot(JSContext *cx, JSObject *obj, jsval &dataVal, jsval &retval) { // if(p->jsclass->JSCLASS_HAS_RESERVED_SLOTS(1)) { jsval func = JS_GetReservedSlot(obj, 0); if(func == JSVAL_VOID) { return; } jsval thisObj = JS_GetReservedSlot(obj, 1); if(thisObj == JSVAL_VOID) { JS_CallFunctionValue(cx, obj, func, 1, &dataVal, &retval); } else { assert(!JSVAL_IS_PRIMITIVE(thisObj)); JS_CallFunctionValue(cx, JSVAL_TO_OBJECT(thisObj), func, 1, &dataVal, &retval); } // } }
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; }
JSBool http_uri(JSContext* cx, JSObject* req, couch_args* args, jsval* uri_val) { FILE* uri_fp = NULL; JSString* uri_str; // Default is http://localhost:5984/ when no uri file is specified if (!args->uri_file) { uri_str = JS_InternString(cx, "http://localhost:5984/"); *uri_val = STRING_TO_JSVAL(uri_str); return JS_TRUE; } // Else check to see if the base url is cached in a reserved slot if (JS_GetReservedSlot(cx, req, 0, uri_val) && !JSVAL_IS_VOID(*uri_val)) { return JS_TRUE; } // Read the first line of the couch.uri file. if(!((uri_fp = fopen(args->uri_file, "r")) && (uri_str = couch_readline(cx, uri_fp)))) { JS_ReportError(cx, "Failed to read couch.uri file."); goto error; } fclose(uri_fp); *uri_val = STRING_TO_JSVAL(uri_str); JS_SetReservedSlot(cx, req, 0, *uri_val); return JS_TRUE; error: if(uri_fp) fclose(uri_fp); return JS_FALSE; }
static JSBool GetMember(XPCCallContext& ccx, JSObject* funobj, XPCNativeInterface*& iface, XPCDispInterface::Member*& member) { jsval val; if(!JS_GetReservedSlot(ccx, funobj, 1, &val)) return JS_FALSE; if(!JSVAL_IS_INT(val)) return JS_FALSE; iface = reinterpret_cast<XPCNativeInterface*>(JSVAL_TO_PRIVATE(val)); if(!JS_GetReservedSlot(ccx, funobj, 0, &val)) return JS_FALSE; if(!JSVAL_IS_INT(val)) return JS_FALSE; member = reinterpret_cast<XPCDispInterface::Member*>(JSVAL_TO_PRIVATE(val)); return JS_TRUE; }
static void XPC_XOW_Finalize(JSContext *cx, JSObject *obj) { JSObject *wrappedObj = GetWrappedObject(cx, obj); if (!wrappedObj) { return; } // Get our scope. jsval scopeVal; if (!JS_GetReservedSlot(cx, obj, XPC_XOW_ScopeSlot, &scopeVal)) { return; } // Now that we have our scope, see if it's going away. If it is, // then our work here is going to be done when we destroy the scope // entirely. Scope can be null if we're an enumerating XOW. XPCWrappedNativeScope *scope = reinterpret_cast<XPCWrappedNativeScope *> (JSVAL_TO_PRIVATE(scopeVal)); if (!scope) { return; } // Remove ourselves from the map. scope->GetWrapperMap()->Remove(wrappedObj); }
// Returns a weak reference. static nsIPrincipal * FindObjectPrincipals(JSContext *cx, JSObject *safeObj, JSObject *innerObj) { // Check if we have a cached principal first. jsval v; if (!JS_GetReservedSlot(cx, safeObj, XPC_SJOW_SLOT_PRINCIPAL, &v)) { return nsnull; } if (!JSVAL_IS_VOID(v)) { // Found one! No need to do any more refcounting. return static_cast<nsIPrincipal *>(JSVAL_TO_PRIVATE(v)); } nsCOMPtr<nsIPrincipal> objPrincipal; nsresult rv = FindPrincipals(cx, innerObj, getter_AddRefs(objPrincipal), nsnull, nsnull); if (NS_FAILED(rv)) { return nsnull; } if (!JS_SetReservedSlot(cx, safeObj, XPC_SJOW_SLOT_PRINCIPAL, PRIVATE_TO_JSVAL(objPrincipal.get()))) { return nsnull; } // The wrapper owns the principal now. return objPrincipal.forget().get(); }
PRLibrary* Library::GetLibrary(JSObject* obj) { JS_ASSERT(IsLibrary(obj)); jsval slot = JS_GetReservedSlot(obj, SLOT_LIBRARY); return static_cast<PRLibrary*>(JSVAL_TO_PRIVATE(slot)); }
PRLibrary* Library::GetLibrary(JSObject* obj) { MOZ_ASSERT(IsLibrary(obj)); Value slot = JS_GetReservedSlot(obj, SLOT_LIBRARY); return static_cast<PRLibrary*>(slot.toPrivate()); }
PRLibrary* Library::GetLibrary(JSContext* cx, JSObject* obj) { JS_ASSERT(IsLibrary(cx, obj)); jsval slot; JS_GetReservedSlot(cx, obj, SLOT_LIBRARY, &slot); return static_cast<PRLibrary*>(JSVAL_TO_PRIVATE(slot)); }
static JSBool XPC_XOW_FunctionWrapper(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) { JSObject *wrappedObj, *outerObj = obj; // Allow 'this' to be either an XOW, in which case we unwrap it. // We disallow invalid XOWs that have no wrapped object. Otherwise, // if it isn't an XOW, then pass it through as-is. wrappedObj = GetWrapper(obj); if (wrappedObj) { wrappedObj = GetWrappedObject(cx, wrappedObj); if (!wrappedObj) { return ThrowException(NS_ERROR_ILLEGAL_VALUE, cx); } } else { wrappedObj = obj; } JSObject *funObj = JSVAL_TO_OBJECT(argv[-2]); jsval funToCall; if (!JS_GetReservedSlot(cx, funObj, XPCWrapper::eWrappedFunctionSlot, &funToCall)) { return JS_FALSE; } JSFunction *fun = JS_ValueToFunction(cx, funToCall); if (!fun) { return ThrowException(NS_ERROR_ILLEGAL_VALUE, cx); } XPCCallContext ccx(JS_CALLER, cx); if (!ccx.IsValid()) { return ThrowException(NS_ERROR_FAILURE, cx); } nsresult rv = CanAccessWrapper(cx, JSVAL_TO_OBJECT(funToCall), nsnull); if (NS_FAILED(rv) && rv != NS_ERROR_DOM_PROP_ACCESS_DENIED) { return ThrowException(rv, cx); } #ifdef DEBUG JSNative native = JS_GetFunctionNative(cx, fun); NS_ASSERTION(native, "How'd we get here with a scripted function?"); #endif if (!JS_CallFunctionValue(cx, wrappedObj, funToCall, argc, argv, rval)) { return JS_FALSE; } if (NS_SUCCEEDED(rv)) { return WrapSameOriginProp(cx, outerObj, rval); } return XPC_XOW_RewrapIfNeeded(cx, obj, rval); }
static JSObject * wrappedObject(JSContext *cx, JSObject *obj) { jsval wrappee; // TODO: This function will be setting an error if it fails; // not sure if wrappedObject() handlers are allowed to raise // exceptions or not. if (!JS_GetReservedSlot(cx, obj, SLOT_WRAPPEE, &wrappee)) return obj; return JSVAL_TO_OBJECT(wrappee); }
// static JSBool XPCNativeMember::GetCallInfo(XPCCallContext& ccx, JSObject* funobj, XPCNativeInterface** pInterface, XPCNativeMember** pMember) { jsval ifaceVal; jsval memberVal; if(!JS_GetReservedSlot(ccx, funobj, 0, &ifaceVal) || !JS_GetReservedSlot(ccx, funobj, 1, &memberVal) || !JSVAL_IS_INT(ifaceVal) || !JSVAL_IS_INT(memberVal)) { return JS_FALSE; } *pInterface = (XPCNativeInterface*) JSVAL_TO_PRIVATE(ifaceVal); *pMember = (XPCNativeMember*) JSVAL_TO_PRIVATE(memberVal); return JS_TRUE; }
/** * Extract the FinalizationEvent from an instance of FinalizationWitness * and clear the slot containing the FinalizationEvent. */ already_AddRefed<FinalizationEvent> ExtractFinalizationEvent(JSObject *objSelf) { JS::Value slotEvent = JS_GetReservedSlot(objSelf, WITNESS_SLOT_EVENT); if (slotEvent.isUndefined()) { // Forget() has been called return nullptr; } JS_SetReservedSlot(objSelf, WITNESS_SLOT_EVENT, JS::UndefinedValue()); return dont_AddRef(static_cast<FinalizationEvent*>(slotEvent.toPrivate())); }
void JavaObject::finalize(JSFreeOp* fop, JSObject* obj) { // In general use of JS_GetPrivate is not safe but it is OK in the finalizer // according to: // https://developer.mozilla.org/en/SpiderMonkey/JSAPI_Reference/JS_GetPrivate // We will not be using getSession for that reason. SessionData * data = static_cast<SessionData*>(JS_GetPrivate(obj)); if (data) { jsval val = JS_GetReservedSlot(obj, 0); int objectId = JSVAL_TO_INT(val); data->freeJavaObject(objectId); MOZ_JS_SetPrivate(/** Post-FF13 requires no ctx anyways*/ NULL, obj, NULL); } }
static JSBool PropertyOpForwarder(JSContext *cx, uintN argc, jsval *vp) { // Layout: // this = our this // property op to call = callee reserved slot 0 // name of the property = callee reserved slot 1 JSObject *callee = JSVAL_TO_OBJECT(JS_CALLEE(cx, vp)); JSObject *obj = JS_THIS_OBJECT(cx, vp); jsval v; if(!JS_GetReservedSlot(cx, callee, 0, &v)) return JS_FALSE; JSObject *ptrobj = JSVAL_TO_OBJECT(v); JSPropertyOp *popp = static_cast<JSPropertyOp *>(JS_GetPrivate(cx, ptrobj)); if(!JS_GetReservedSlot(cx, callee, 1, &v)) return JS_FALSE; jsval argval = (argc > 0) ? JS_ARGV(cx, vp)[0] : JSVAL_VOID; JS_SET_RVAL(cx, vp, argval); return (*popp)(cx, obj, v, vp); }
static JSBool getWrappedComponent(JSContext *cx, uintN argc, jsval *argv, jsval *rval, uint32 slotIndex) { JSObject *wrapped; if (!JS_ConvertArguments(cx, argc, argv, "o", &wrapped)) return JS_FALSE; if (JS_GetClass(cx, wrapped) == &sFlexibleWrapper_JSClass.base) { if (!JS_GetReservedSlot(cx, wrapped, slotIndex, rval)) return JS_FALSE; return JS_TRUE; } *rval = JSVAL_NULL; return JS_TRUE; }
JSObject * GetUnsafeObject(JSContext *cx, JSObject *obj) { obj = FindSafeObject(obj); if (!obj) { return nsnull; } jsval v; if (!JS_GetReservedSlot(cx, obj, XPCWrapper::sWrappedObjSlot, &v)) { JS_ClearPendingException(cx); return nsnull; } return JSVAL_IS_OBJECT(v) ? JSVAL_TO_OBJECT(v) : nsnull; }
JSBool MakeSOW(JSContext *cx, JSObject *obj) { #ifdef DEBUG { js::Class *clasp = obj->getClass(); NS_ASSERTION(clasp != &SystemOnlyWrapper::SOWClass && clasp != &XPCCrossOriginWrapper::XOWClass, "bad call"); } #endif jsval flags; return JS_GetReservedSlot(cx, obj, sFlagsSlot, &flags) && JS_SetReservedSlot(cx, obj, sFlagsSlot, INT_TO_JSVAL(JSVAL_TO_INT(flags) | FLAG_SOW)); }
static JSBool XPC_COW_AddProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp) { obj = GetWrapper(obj); jsval resolving; if (!JS_GetReservedSlot(cx, obj, XPCWrapper::sFlagsSlot, &resolving)) { return JS_FALSE; } if (HAS_FLAGS(resolving, FLAG_RESOLVING)) { // Allow us to define a property on ourselves. return JS_TRUE; } // Someone's adding a property to us. We need to protect ourselves from // getters and setters. JSObject *wrappedObj = GetWrappedObject(cx, obj); if (!wrappedObj) { return ThrowException(NS_ERROR_ILLEGAL_VALUE, cx); } jsid interned_id; JSPropertyDescriptor desc; if (!JS_ValueToId(cx, id, &interned_id) || !XPCWrapper::GetPropertyAttrs(cx, obj, interned_id, JSRESOLVE_QUALIFIED, JS_TRUE, &desc)) { return JS_FALSE; } NS_ASSERTION(desc.obj == obj, "The JS engine lies!"); if (desc.attrs & (JSPROP_GETTER | JSPROP_SETTER)) { // Only chrome is allowed to add getters or setters to our object. if (!AllowedToAct(cx, id)) { return JS_FALSE; } } return XPC_COW_RewrapForChrome(cx, obj, vp) && JS_DefinePropertyById(cx, wrappedObj, interned_id, *vp, desc.getter, desc.setter, desc.attrs); }
static JSBool XPC_XOW_Equality(JSContext *cx, JSObject *obj, jsval v, JSBool *bp) { // Convert both sides to XPCWrappedNative and see if they match. if (JSVAL_IS_PRIMITIVE(v)) { *bp = JS_FALSE; return JS_TRUE; } JSObject *test = JSVAL_TO_OBJECT(v); if (STOBJ_GET_CLASS(test) == &sXPC_XOW_JSClass.base) { if (!JS_GetReservedSlot(cx, test, XPCWrapper::sWrappedObjSlot, &v)) { return JS_FALSE; } if (JSVAL_IS_PRIMITIVE(v)) { *bp = JS_FALSE; return JS_TRUE; } test = JSVAL_TO_OBJECT(v); } obj = GetWrappedObject(cx, obj); if (!obj) { return ThrowException(NS_ERROR_ILLEGAL_VALUE, cx); } XPCWrappedNative *other = XPCWrappedNative::GetWrappedNativeOfJSObject(cx, test); if (!other) { *bp = JS_FALSE; return JS_TRUE; } XPCWrappedNative *me = XPCWrappedNative::GetWrappedNativeOfJSObject(cx, obj); obj = me->GetFlatJSObject(); test = other->GetFlatJSObject(); return ((JSExtendedClass *)STOBJ_GET_CLASS(obj))-> equality(cx, obj, OBJECT_TO_JSVAL(test), bp); }
static JSBool XPC_XOW_AddProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp) { // All AddProperty needs to do is pass on addProperty requests to // same-origin objects, and throw for all else. obj = GetWrapper(obj); jsval resolving; if (!JS_GetReservedSlot(cx, obj, XPCWrapper::sFlagsSlot, &resolving)) { return JS_FALSE; } if (HAS_FLAGS(resolving, FLAG_RESOLVING)) { // Allow us to define a property on ourselves. return JS_TRUE; } JSObject *wrappedObj = GetWrappedObject(cx, obj); if (!wrappedObj) { return ThrowException(NS_ERROR_ILLEGAL_VALUE, cx); } XPCCallContext ccx(JS_CALLER, cx); if (!ccx.IsValid()) { return ThrowException(NS_ERROR_FAILURE, cx); } JSBool privilegeEnabled = JS_FALSE; nsresult rv = CanAccessWrapper(cx, wrappedObj, &privilegeEnabled); if (NS_FAILED(rv)) { if (rv == NS_ERROR_DOM_PROP_ACCESS_DENIED) { // Can't override properties on foreign objects. return ThrowException(rv, cx); } return JS_FALSE; } // Same origin, pass this request along. return XPCWrapper::AddProperty(cx, obj, JS_TRUE, wrappedObj, id, vp); }
static JSBool resolverHasMethod(JSContext *cx, JSObject *obj, const char *name) { // If we're the prototype of some other object, then obj won't be of // the JSClass we need it to be, so just deny that our membrane has // the method we're looking for. JSClass *klass = JS_GET_CLASS(cx, obj); if (klass != &sFlexibleWrapper_JSClass.base) return JS_FALSE; jsval resolver; if (!JS_GetReservedSlot(cx, obj, SLOT_RESOLVER, &resolver)) return JS_FALSE; JSObject *resolverObj = JSVAL_TO_OBJECT(resolver); JSBool hasProperty; if (!JS_HasProperty(cx, resolverObj, name, &hasProperty)) return JS_FALSE; return hasProperty; // TODO: Check to make sure the property is a function? }
static JSBool XPC_COW_FunctionWrapper(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) { JSObject *wrappedObj; // Allow 'this' to be either a COW, in which case we unwrap it or something // that isn't a COW. We disallow invalid COWs that have no wrapped object. wrappedObj = GetWrapper(obj); if (wrappedObj) { wrappedObj = GetWrappedObject(cx, wrappedObj); if (!wrappedObj) { return ThrowException(NS_ERROR_ILLEGAL_VALUE, cx); } } else { wrappedObj = obj; } jsval funToCall; if (!JS_GetReservedSlot(cx, JSVAL_TO_OBJECT(argv[-2]), XPCWrapper::eWrappedFunctionSlot, &funToCall)) { return JS_FALSE; } for (uintN i = 0; i < argc; ++i) { if (!XPC_COW_RewrapForChrome(cx, obj, &argv[i])) { return JS_FALSE; } } if (!JS_CallFunctionValue(cx, wrappedObj, funToCall, argc, argv, rval)) { return JS_FALSE; } return XPC_COW_RewrapForContent(cx, obj, rval); }
static JSBool XPC_XOW_NewResolve(JSContext *cx, JSObject *obj, jsval id, uintN flags, JSObject **objp) { obj = GetWrapper(obj); JSObject *wrappedObj = GetWrappedObject(cx, obj); if (!wrappedObj) { // No wrappedObj means that this is probably the prototype. *objp = nsnull; return JS_TRUE; } XPCCallContext ccx(JS_CALLER, cx); if (!ccx.IsValid()) { return ThrowException(NS_ERROR_FAILURE, cx); } JSBool privilegeEnabled; nsresult rv = CanAccessWrapper(cx, wrappedObj, &privilegeEnabled); if (NS_FAILED(rv)) { if (rv != NS_ERROR_DOM_PROP_ACCESS_DENIED) { return JS_FALSE; } // We're dealing with a cross-origin lookup. Ensure that we're allowed to // resolve this property and resolve it if so. Otherwise, we deny access // and throw a security error. Note that this code does not actually check // to see if the property exists, that's dealt with below. XPCWrappedNative *wn = XPCWrappedNative::GetWrappedNativeOfJSObject(cx, wrappedObj); NS_ASSERTION(wn, "How did we wrap a non-WrappedNative?"); if (!IsValFrame(wrappedObj, id, wn)) { nsIScriptSecurityManager *ssm = XPCWrapper::GetSecurityManager(); if (!ssm) { return ThrowException(NS_ERROR_NOT_INITIALIZED, cx); } PRUint32 action = (flags & JSRESOLVE_ASSIGNING) ? XPCWrapper::sSecMgrSetProp : XPCWrapper::sSecMgrGetProp; rv = ssm->CheckPropertyAccess(cx, wrappedObj, STOBJ_GET_CLASS(wrappedObj)->name, id, action); if (NS_FAILED(rv)) { // The security manager threw an exception for us. return JS_FALSE; } } // We're out! We're allowed to resolve this property. return XPCWrapper::ResolveNativeProperty(cx, obj, wrappedObj, wn, id, flags, objp, JS_FALSE); } if (privilegeEnabled && !(obj = GetUXPCObject(cx, obj))) { return JS_FALSE; } if (id == GetRTStringByIndex(cx, XPCJSRuntime::IDX_TO_STRING)) { jsval oldSlotVal; if (!JS_GetReservedSlot(cx, obj, XPCWrapper::sFlagsSlot, &oldSlotVal) || !JS_SetReservedSlot(cx, obj, XPCWrapper::sFlagsSlot, INT_TO_JSVAL(JSVAL_TO_INT(oldSlotVal) | FLAG_RESOLVING))) { return JS_FALSE; } JSBool ok = JS_DefineFunction(cx, obj, "toString", XPC_XOW_toString, 0, 0) != nsnull; JS_SetReservedSlot(cx, obj, XPCWrapper::sFlagsSlot, oldSlotVal); if (ok) { *objp = obj; } return ok; } return XPCWrapper::NewResolve(cx, obj, JS_TRUE, wrappedObj, id, flags, objp); }
static JSBool go(JSContext* cx, JSObject* obj, HTTPData* http, char* body, size_t bodylen) { CurlState state; char* referer; JSString* jsbody; JSBool ret = JS_FALSE; jsval tmp; state.cx = cx; state.http = http; state.sendbuf = body; state.sendlen = bodylen; state.sent = 0; state.sent_once = 0; state.recvbuf = NULL; state.recvlen = 0; state.read = 0; if(HTTP_HANDLE == NULL) { HTTP_HANDLE = curl_easy_init(); curl_easy_setopt(HTTP_HANDLE, CURLOPT_READFUNCTION, send_body); curl_easy_setopt(HTTP_HANDLE, CURLOPT_SEEKFUNCTION, (curl_seek_callback) seek_body); curl_easy_setopt(HTTP_HANDLE, CURLOPT_HEADERFUNCTION, recv_header); curl_easy_setopt(HTTP_HANDLE, CURLOPT_WRITEFUNCTION, recv_body); curl_easy_setopt(HTTP_HANDLE, CURLOPT_NOPROGRESS, 1); curl_easy_setopt(HTTP_HANDLE, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4); curl_easy_setopt(HTTP_HANDLE, CURLOPT_ERRORBUFFER, ERRBUF); curl_easy_setopt(HTTP_HANDLE, CURLOPT_COOKIEFILE, ""); curl_easy_setopt(HTTP_HANDLE, CURLOPT_USERAGENT, "CouchHTTP Client - Relax"); } if(!HTTP_HANDLE) { JS_ReportError(cx, "Failed to initialize cURL handle."); goto done; } if(!JS_GetReservedSlot(cx, obj, 0, &tmp)) { JS_ReportError(cx, "Failed to readreserved slot."); goto done; } if(!(referer = enc_string(cx, tmp, NULL))) { JS_ReportError(cx, "Failed to encode referer."); goto done; } curl_easy_setopt(HTTP_HANDLE, CURLOPT_REFERER, referer); free(referer); if(http->method < 0 || http->method > OPTIONS) { JS_ReportError(cx, "INTERNAL: Unknown method."); goto done; } curl_easy_setopt(HTTP_HANDLE, CURLOPT_CUSTOMREQUEST, METHODS[http->method]); curl_easy_setopt(HTTP_HANDLE, CURLOPT_NOBODY, 0); curl_easy_setopt(HTTP_HANDLE, CURLOPT_FOLLOWLOCATION, 1); curl_easy_setopt(HTTP_HANDLE, CURLOPT_UPLOAD, 0); if(http->method == HEAD) { curl_easy_setopt(HTTP_HANDLE, CURLOPT_NOBODY, 1); curl_easy_setopt(HTTP_HANDLE, CURLOPT_FOLLOWLOCATION, 0); } else if(http->method == POST || http->method == PUT) { curl_easy_setopt(HTTP_HANDLE, CURLOPT_UPLOAD, 1); curl_easy_setopt(HTTP_HANDLE, CURLOPT_FOLLOWLOCATION, 0); } if(body && bodylen) { curl_easy_setopt(HTTP_HANDLE, CURLOPT_INFILESIZE, bodylen); } else { curl_easy_setopt(HTTP_HANDLE, CURLOPT_INFILESIZE, 0); } // curl_easy_setopt(HTTP_HANDLE, CURLOPT_VERBOSE, 1); curl_easy_setopt(HTTP_HANDLE, CURLOPT_URL, http->url); curl_easy_setopt(HTTP_HANDLE, CURLOPT_HTTPHEADER, http->req_headers); curl_easy_setopt(HTTP_HANDLE, CURLOPT_READDATA, &state); curl_easy_setopt(HTTP_HANDLE, CURLOPT_SEEKDATA, &state); curl_easy_setopt(HTTP_HANDLE, CURLOPT_WRITEHEADER, &state); curl_easy_setopt(HTTP_HANDLE, CURLOPT_WRITEDATA, &state); if(curl_easy_perform(HTTP_HANDLE) != 0) { JS_ReportError(cx, "Failed to execute HTTP request: %s", ERRBUF); goto done; } if(!state.resp_headers) { JS_ReportError(cx, "Failed to recieve HTTP headers."); goto done; } tmp = OBJECT_TO_JSVAL(state.resp_headers); if(!JS_DefineProperty( cx, obj, "_headers", tmp, NULL, NULL, JSPROP_READONLY )) { JS_ReportError(cx, "INTERNAL: Failed to set response headers."); goto done; } if(state.recvbuf) { state.recvbuf[state.read] = '\0'; jsbody = dec_string(cx, state.recvbuf, state.read+1); if(!jsbody) { // If we can't decode the body as UTF-8 we forcefully // convert it to a string by just forcing each byte // to a jschar. jsbody = str_from_binary(cx, state.recvbuf, state.read); if(!jsbody) { if(!JS_IsExceptionPending(cx)) { JS_ReportError(cx, "INTERNAL: Failed to decode body."); } goto done; } } tmp = STRING_TO_JSVAL(jsbody); } else { tmp = JS_GetEmptyStringValue(cx); } if(!JS_DefineProperty( cx, obj, "responseText", tmp, NULL, NULL, JSPROP_READONLY )) { JS_ReportError(cx, "INTERNAL: Failed to set responseText."); goto done; } ret = JS_TRUE; done: if(state.recvbuf) JS_free(cx, state.recvbuf); return ret; }