NS_IMETHODIMP nsJSCID::Construct(nsIXPConnectWrappedNative* wrapper, JSContext* cx, JSObject* objArg, const CallArgs& args, bool* _retval) { RootedObject obj(cx, objArg); XPCJSRuntime* rt = nsXPConnect::GetRuntimeInstance(); if (!rt) return NS_ERROR_FAILURE; // 'push' a call context and call on it RootedId name(cx, rt->GetStringID(XPCJSRuntime::IDX_CREATE_INSTANCE)); XPCCallContext ccx(JS_CALLER, cx, obj, nullptr, name, args.length(), args.array(), args.rval().address()); *_retval = XPCWrappedNative::CallMethod(ccx); return NS_OK; }
/* PRBool construct (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in PRUint32 argc, in JSValPtr argv, in JSValPtr vp); */ NS_IMETHODIMP nsJSCID::Construct(nsIXPConnectWrappedNative *wrapper, JSContext * cx, JSObject * obj, PRUint32 argc, jsval * argv, jsval * vp, PRBool *_retval) { XPCJSRuntime* rt = nsXPConnect::GetRuntimeInstance(); if(!rt) return NS_ERROR_FAILURE; // 'push' a call context and call on it XPCCallContext ccx(JS_CALLER, cx, obj, nsnull, rt->GetStringID(XPCJSRuntime::IDX_CREATE_INSTANCE), argc, argv, vp); *_retval = XPCWrappedNative::CallMethod(ccx); return NS_OK; }
bool XrayWrapper<Base>::resolveOwnProperty(JSContext *cx, JSObject *wrapper, jsid id, bool set, PropertyDescriptor *desc) { // Partially transparent wrappers (which used to be known as XOWs) don't // have a .wrappedJSObject property. XPCJSRuntime* rt = nsXPConnect::GetRuntimeInstance(); if (!WrapperFactory::IsPartiallyTransparent(wrapper) && (id == rt->GetStringID(XPCJSRuntime::IDX_WRAPPED_JSOBJECT) || // Check for baseURIObject and nodePrincipal no nodes and // documentURIObject on documents, but only from privileged scripts. // Do the id checks before the QIs and IsPrivilegedScript() checks, // since they're cheaper and will tend to fail most of the time // anyway. (((id == rt->GetStringID(XPCJSRuntime::IDX_BASEURIOBJECT) || id == rt->GetStringID(XPCJSRuntime::IDX_NODEPRINCIPAL)) && Is<nsINode>(wrapper)) || (id == rt->GetStringID(XPCJSRuntime::IDX_DOCUMENTURIOBJECT) && Is<nsIDocument>(wrapper))) && IsPrivilegedScript())) { bool status; JSWrapper::Action action = set ? JSWrapper::SET : JSWrapper::GET; desc->obj = NULL; // default value if (!this->enter(cx, wrapper, id, action, &status)) return status; AutoLeaveHelper<Base> helper(*this, cx, wrapper); desc->obj = wrapper; desc->attrs = JSPROP_ENUMERATE|JSPROP_SHARED; if (id == rt->GetStringID(XPCJSRuntime::IDX_WRAPPED_JSOBJECT)) desc->getter = wrappedJSObject_getter; else if (id == rt->GetStringID(XPCJSRuntime::IDX_BASEURIOBJECT)) desc->getter = baseURIObject_getter; else if (id == rt->GetStringID(XPCJSRuntime::IDX_DOCUMENTURIOBJECT)) desc->getter = documentURIObject_getter; else desc->getter = nodePrincipal_getter; desc->setter = NULL; desc->shortid = 0; desc->value = JSVAL_VOID; return true; } desc->obj = NULL; uintN flags = (set ? JSRESOLVE_ASSIGNING : 0) | JSRESOLVE_QUALIFIED; JSObject *holder = GetHolder(wrapper); JSObject *expando = GetExpandoObject(holder); // Check for expando properties first. if (expando && !JS_GetPropertyDescriptorById(cx, expando, id, flags, desc)) { return false; } if (desc->obj) { // Pretend the property lives on the wrapper. desc->obj = wrapper; return true; } JSBool hasProp; if (!JS_HasPropertyById(cx, holder, id, &hasProp)) { return false; } if (!hasProp) { XPCWrappedNative *wn = GetWrappedNativeFromHolder(holder); // Run the resolve hook of the wrapped native. if (!NATIVE_HAS_FLAG(wn, WantNewResolve)) { desc->obj = nsnull; return true; } PRBool retval = true; JSObject *pobj = NULL; nsresult rv = wn->GetScriptableInfo()->GetCallback()->NewResolve(wn, cx, wrapper, id, flags, &pobj, &retval); if (NS_FAILED(rv)) { if (retval) XPCThrower::Throw(rv, cx); return false; } if (!pobj) { desc->obj = nsnull; return true; } #ifdef DEBUG NS_ASSERTION(JS_HasPropertyById(cx, holder, id, &hasProp) && hasProp, "id got defined somewhere else?"); #endif } if (!JS_GetPropertyDescriptorById(cx, holder, id, flags, desc)) return false; // Pretend we found the property on the wrapper, not the holder. desc->obj = wrapper; return true; }
JSBool XPCDispObject::Invoke(XPCCallContext & ccx, CallMode mode) { nsresult rv = ccx.CanCallNow(); if(NS_FAILED(rv)) { // If the security manager is complaining then this is not really an // internal error in xpconnect. So, no reason to botch the assertion. NS_ASSERTION(rv == NS_ERROR_XPC_SECURITY_MANAGER_VETO, "hmm? CanCallNow failed in XPCDispObject::Invoke. " "We are finding out about this late!"); XPCThrower::Throw(rv, ccx); return JS_FALSE; } // TODO: Remove type cast and change GetIDispatchMember to use the correct type XPCDispInterface::Member* member = reinterpret_cast<XPCDispInterface::Member*>(ccx.GetIDispatchMember()); XPCJSRuntime* rt = ccx.GetRuntime(); XPCContext* xpcc = ccx.GetXPCContext(); XPCPerThreadData* tls = ccx.GetThreadData(); jsval* argv = ccx.GetArgv(); uintN argc = ccx.GetArgc(); tls->SetException(nsnull); xpcc->SetLastResult(NS_ERROR_UNEXPECTED); // set up the method index and do the security check if needed PRUint32 secFlag; PRUint32 secAction; switch(mode) { case CALL_METHOD: secFlag = nsIXPCSecurityManager::HOOK_CALL_METHOD; secAction = nsIXPCSecurityManager::ACCESS_CALL_METHOD; break; case CALL_GETTER: secFlag = nsIXPCSecurityManager::HOOK_GET_PROPERTY; secAction = nsIXPCSecurityManager::ACCESS_GET_PROPERTY; break; case CALL_SETTER: secFlag = nsIXPCSecurityManager::HOOK_SET_PROPERTY; secAction = nsIXPCSecurityManager::ACCESS_SET_PROPERTY; break; default: NS_ASSERTION(0,"bad value"); return JS_FALSE; } jsval name = member->GetName(); nsIXPCSecurityManager* sm = xpcc->GetAppropriateSecurityManager(secFlag); XPCWrappedNative* wrapper = ccx.GetWrapper(); if(sm && NS_FAILED(sm->CanAccess(secAction, &ccx, ccx, ccx.GetFlattenedJSObject(), wrapper->GetIdentityObject(), wrapper->GetClassInfo(), name, wrapper->GetSecurityInfoAddr()))) { // the security manager vetoed. It should have set an exception. return JS_FALSE; } IDispatch * pObj = reinterpret_cast<IDispatch*> (ccx.GetTearOff()->GetNative()); PRUint32 args = member->GetParamCount(); uintN err; // Make sure setter has one argument if(mode == CALL_SETTER) args = 1; // Allow for optional parameters. We'll let COM handle the error if there // are not enough parameters if(argc < args) args = argc; XPCDispParams * params = new XPCDispParams(args); jsval val; // If this is a setter, we just need to convert the first parameter if(mode == CALL_SETTER) { params->SetNamedPropID(); if(!XPCDispConvert::JSToCOM(ccx, argv[0], params->GetParamRef(0), err)) { delete params; return ThrowBadParam(err, 0, ccx); } } else if(mode != CALL_GETTER) // This is a function { // Convert the arguments to the function for(PRUint32 index = 0; index < args; ++index) { const XPCDispInterface::Member::ParamInfo & paramInfo = member->GetParamInfo(index); if(paramInfo.IsIn()) { val = argv[index]; if(paramInfo.IsOut()) { if(JSVAL_IS_PRIMITIVE(val) || !OBJ_GET_PROPERTY(ccx, JSVAL_TO_OBJECT(val), rt->GetStringID(XPCJSRuntime::IDX_VALUE), &val)) { delete params; return ThrowBadParam(NS_ERROR_XPC_NEED_OUT_OBJECT, index, ccx); } paramInfo.InitializeOutputParam(params->GetOutputBuffer(index), params->GetParamRef(index)); } if(!XPCDispConvert::JSToCOM(ccx, val, params->GetParamRef(index), err, paramInfo.IsOut())) { delete params; return ThrowBadParam(err, index, ccx); } } else { paramInfo.InitializeOutputParam(params->GetOutputBuffer(index), params->GetParamRef(index)); } } } // If this is a parameterized property if(member->IsParameterizedProperty()) { // We need to get a parameterized property object to return to JS // NewInstance takes ownership of params if(XPCDispParamPropJSClass::NewInstance(ccx, wrapper, member->GetDispID(), params, &val)) { ccx.SetRetVal(val); if(!JS_IdToValue(ccx, 1, &val)) { // This shouldn't fail NS_ERROR("JS_IdToValue failed in XPCDispParamPropJSClass::NewInstance"); return JS_FALSE; } JS_SetCallReturnValue2(ccx, val); return JS_TRUE; } // NewInstance would only fail if there was an out of memory problem JS_ReportOutOfMemory(ccx); delete params; return JS_FALSE; } JSBool retval = Dispatch(ccx, pObj, member->GetDispID(), mode, params, &val, member, rt); if(retval && mode == CALL_SETTER) { ccx.SetRetVal(argv[0]); } else { ccx.SetRetVal(val); } delete params; return retval; }