NS_IMETHODIMP nsXPConnect::MarkErrorUnreported(JSContext *cx) { XPCContext *xpcc = XPCContext::GetXPCContext(cx); xpcc->MarkErrorUnreported(); return NS_OK; }
SweepContextsCB(JSDHashTable *table, JSDHashEntryHdr *hdr, uint32 number, void *arg) { XPCContext* xpcc = ((JSContext2XPCContextMap::Entry*)hdr)->value; if(xpcc->IsMarked()) { xpcc->Unmark(); return JS_DHASH_NEXT; } // this XPCContext represents a dead JSContext - delete it delete xpcc; return JS_DHASH_REMOVE; }
XPCContext* XPCJSRuntime::SyncXPCContextList(JSContext* cx /* = nsnull */) { // hold the map lock through this whole thing XPCAutoLock lock(GetMapLock()); XPCContext* found = nsnull; // add XPCContexts that represent any JSContexts we have not seen before JSContext *cur, *iter = nsnull; while(nsnull != (cur = JS_ContextIterator(mJSRuntime, &iter))) { XPCContext* xpcc = mContextMap->Find(cur); if(!xpcc) { xpcc = XPCContext::newXPCContext(this, cur); if(xpcc) mContextMap->Add(xpcc); } if(xpcc) { xpcc->Mark(); } // if it is our first context then we need to generate our string ids if(!mStrIDs[0]) { JSAutoRequest ar(cur); GenerateStringIDs(cur); } if(cx && cx == cur) found = xpcc; } // get rid of any XPCContexts that represent dead JSContexts mContextMap->Enumerate(SweepContextsCB, 0); XPCPerThreadData* tls = XPCPerThreadData::GetData(cx); if(tls) { if(found) tls->SetRecentContext(cx, found); else tls->ClearRecentContext(); } return found; }
/* nsISupports getService (); */ NS_IMETHODIMP nsJSCID::GetService(const JS::Value& iidval, JSContext* cx, PRUint8 optionalArgc, JS::Value* retval) { if (!mDetails.IsValid()) return NS_ERROR_XPC_BAD_CID; JSObject* obj = GetWrapperObject(); if (!obj) { return NS_ERROR_UNEXPECTED; } // Do the security check if necessary XPCContext* xpcc = XPCContext::GetXPCContext(cx); nsIXPCSecurityManager* sm; sm = xpcc->GetAppropriateSecurityManager(nsIXPCSecurityManager::HOOK_GET_SERVICE); if (sm && NS_FAILED(sm->CanCreateInstance(cx, mDetails.ID()))) { NS_ASSERTION(JS_IsExceptionPending(cx), "security manager vetoed GetService without setting exception"); return NS_OK; } // If an IID was passed in then use it const nsID* iid = GetIIDArg(optionalArgc, iidval, cx); if (!iid) return NS_ERROR_XPC_BAD_IID; nsCOMPtr<nsIServiceManager> svcMgr; nsresult rv = NS_GetServiceManager(getter_AddRefs(svcMgr)); if (NS_FAILED(rv)) return rv; nsCOMPtr<nsISupports> srvc; rv = svcMgr->GetService(mDetails.ID(), *iid, getter_AddRefs(srvc)); NS_ASSERTION(NS_FAILED(rv) || srvc, "service manager returned success, but service is null!"); if (NS_FAILED(rv) || !srvc) return NS_ERROR_XPC_GS_RETURNED_FAILURE; JSObject* instJSObj; nsCOMPtr<nsIXPConnectJSObjectHolder> holder; rv = nsXPConnect::GetXPConnect()->WrapNative(cx, obj, srvc, *iid, getter_AddRefs(holder)); if (NS_FAILED(rv) || !holder || NS_FAILED(holder->GetJSObject(&instJSObj))) return NS_ERROR_XPC_CANT_CREATE_WN; *retval = OBJECT_TO_JSVAL(instJSObj); return NS_OK; }
/* nsISupports createInstance (); */ NS_IMETHODIMP nsJSCID::CreateInstance(const JS::Value& iidval, JSContext* cx, PRUint8 optionalArgc, JS::Value* retval) { if (!mDetails.IsValid()) return NS_ERROR_XPC_BAD_CID; JSObject* obj = GetWrapperObject(); if (!obj) { return NS_ERROR_UNEXPECTED; } // Do the security check if necessary XPCContext* xpcc = XPCContext::GetXPCContext(cx); nsIXPCSecurityManager* sm; sm = xpcc->GetAppropriateSecurityManager(nsIXPCSecurityManager::HOOK_CREATE_INSTANCE); if (sm && NS_FAILED(sm->CanCreateInstance(cx, mDetails.ID()))) { NS_ERROR("how are we not being called from chrome here?"); return NS_OK; } // If an IID was passed in then use it const nsID* iid = GetIIDArg(optionalArgc, iidval, cx); if (!iid) return NS_ERROR_XPC_BAD_IID; nsCOMPtr<nsIComponentManager> compMgr; nsresult rv = NS_GetComponentManager(getter_AddRefs(compMgr)); if (NS_FAILED(rv)) return NS_ERROR_UNEXPECTED; nsCOMPtr<nsISupports> inst; rv = compMgr->CreateInstance(mDetails.ID(), nsnull, *iid, getter_AddRefs(inst)); NS_ASSERTION(NS_FAILED(rv) || inst, "component manager returned success, but instance is null!"); if (NS_FAILED(rv) || !inst) return NS_ERROR_XPC_CI_RETURNED_FAILURE; rv = nsXPConnect::GetXPConnect()->WrapNativeToJSVal(cx, obj, inst, nsnull, iid, true, retval, nsnull); if (NS_FAILED(rv) || JSVAL_IS_PRIMITIVE(*retval)) return NS_ERROR_XPC_CANT_CREATE_WN; return NS_OK; }
/* nsISupports getService (); */ NS_IMETHODIMP nsJSCID::GetService(nsISupports **_retval) { if(!mDetails.IsValid()) return NS_ERROR_XPC_BAD_CID; nsXPConnect* xpc = nsXPConnect::GetXPConnect(); if(!xpc) return NS_ERROR_UNEXPECTED; nsAXPCNativeCallContext *ccxp = nsnull; xpc->GetCurrentNativeCallContext(&ccxp); if(!ccxp) return NS_ERROR_UNEXPECTED; PRUint32 argc; jsval * argv; jsval * vp; JSContext* cx; JSObject* obj; ccxp->GetJSContext(&cx); ccxp->GetArgc(&argc); ccxp->GetArgvPtr(&argv); ccxp->GetRetValPtr(&vp); nsCOMPtr<nsIXPConnectWrappedNative> wrapper; ccxp->GetCalleeWrapper(getter_AddRefs(wrapper)); wrapper->GetJSObject(&obj); // Do the security check if necessary XPCContext* xpcc = XPCContext::GetXPCContext(cx); nsIXPCSecurityManager* sm; sm = xpcc->GetAppropriateSecurityManager( nsIXPCSecurityManager::HOOK_GET_SERVICE); if(sm && NS_FAILED(sm->CanCreateInstance(cx, mDetails.ID()))) { NS_ASSERTION(JS_IsExceptionPending(cx), "security manager vetoed GetService without setting exception"); return NS_OK; } // If an IID was passed in then use it const nsID* iid = GetIIDArg(argc, argv, cx); if (!iid) return NS_ERROR_XPC_BAD_IID; nsCOMPtr<nsIServiceManager> svcMgr; nsresult rv = NS_GetServiceManager(getter_AddRefs(svcMgr)); if (NS_FAILED(rv)) return rv; nsCOMPtr<nsISupports> srvc; rv = svcMgr->GetService(mDetails.ID(), *iid, getter_AddRefs(srvc)); NS_ASSERTION(NS_FAILED(rv) || srvc, "service manager returned success, but service is null!"); if(NS_FAILED(rv) || !srvc) return NS_ERROR_XPC_GS_RETURNED_FAILURE; JSObject* instJSObj; nsCOMPtr<nsIXPConnectJSObjectHolder> holder; rv = xpc->WrapNative(cx, obj, srvc, *iid, getter_AddRefs(holder)); if(NS_FAILED(rv) || !holder || NS_FAILED(holder->GetJSObject(&instJSObj))) return NS_ERROR_XPC_CANT_CREATE_WN; *vp = OBJECT_TO_JSVAL(instJSObj); ccxp->SetReturnValueWasSet(JS_TRUE); return NS_OK; }
void XPCJSRuntime::DebugDump(PRInt16 depth) { #ifdef DEBUG depth--; XPC_LOG_ALWAYS(("XPCJSRuntime @ %x", this)); XPC_LOG_INDENT(); XPC_LOG_ALWAYS(("mXPConnect @ %x", mXPConnect)); XPC_LOG_ALWAYS(("mJSRuntime @ %x", mJSRuntime)); XPC_LOG_ALWAYS(("mMapLock @ %x", mMapLock)); XPC_LOG_ALWAYS(("mWrappedJSToReleaseArray @ %x with %d wrappers(s)", \ &mWrappedJSToReleaseArray, mWrappedJSToReleaseArray.Length())); int cxCount = 0; JSContext* iter = nsnull; while(JS_ContextIterator(mJSRuntime, &iter)) ++cxCount; XPC_LOG_ALWAYS(("%d JS context(s)", cxCount)); iter = nsnull; while(JS_ContextIterator(mJSRuntime, &iter)) { XPCContext *xpc = XPCContext::GetXPCContext(iter); XPC_LOG_INDENT(); xpc->DebugDump(depth); XPC_LOG_OUTDENT(); } XPC_LOG_ALWAYS(("mWrappedJSClassMap @ %x with %d wrapperclasses(s)", \ mWrappedJSClassMap, mWrappedJSClassMap ? \ mWrappedJSClassMap->Count() : 0)); // iterate wrappersclasses... if(depth && mWrappedJSClassMap && mWrappedJSClassMap->Count()) { XPC_LOG_INDENT(); mWrappedJSClassMap->Enumerate(WrappedJSClassMapDumpEnumerator, &depth); XPC_LOG_OUTDENT(); } XPC_LOG_ALWAYS(("mWrappedJSMap @ %x with %d wrappers(s)", \ mWrappedJSMap, mWrappedJSMap ? \ mWrappedJSMap->Count() : 0)); // iterate wrappers... if(depth && mWrappedJSMap && mWrappedJSMap->Count()) { XPC_LOG_INDENT(); mWrappedJSMap->Enumerate(WrappedJSMapDumpEnumerator, &depth); XPC_LOG_OUTDENT(); } XPC_LOG_ALWAYS(("mIID2NativeInterfaceMap @ %x with %d interface(s)", \ mIID2NativeInterfaceMap, mIID2NativeInterfaceMap ? \ mIID2NativeInterfaceMap->Count() : 0)); XPC_LOG_ALWAYS(("mClassInfo2NativeSetMap @ %x with %d sets(s)", \ mClassInfo2NativeSetMap, mClassInfo2NativeSetMap ? \ mClassInfo2NativeSetMap->Count() : 0)); XPC_LOG_ALWAYS(("mThisTranslatorMap @ %x with %d translator(s)", \ mThisTranslatorMap, mThisTranslatorMap ? \ mThisTranslatorMap->Count() : 0)); XPC_LOG_ALWAYS(("mNativeSetMap @ %x with %d sets(s)", \ mNativeSetMap, mNativeSetMap ? \ mNativeSetMap->Count() : 0)); // iterate sets... if(depth && mNativeSetMap && mNativeSetMap->Count()) { XPC_LOG_INDENT(); mNativeSetMap->Enumerate(NativeSetDumpEnumerator, &depth); XPC_LOG_OUTDENT(); } XPC_LOG_OUTDENT(); #endif }
/* nsISupports createInstance (); */ NS_IMETHODIMP nsJSCID::CreateInstance(nsISupports **_retval) { if(!mDetails.IsValid()) return NS_ERROR_XPC_BAD_CID; nsXPConnect* xpc = nsXPConnect::GetXPConnect(); if(!xpc) return NS_ERROR_UNEXPECTED; nsAXPCNativeCallContext *ccxp = nsnull; xpc->GetCurrentNativeCallContext(&ccxp); if(!ccxp) return NS_ERROR_UNEXPECTED; PRUint32 argc; jsval * argv; jsval * vp; JSContext* cx; JSObject* obj; ccxp->GetJSContext(&cx); ccxp->GetArgc(&argc); ccxp->GetArgvPtr(&argv); ccxp->GetRetValPtr(&vp); nsCOMPtr<nsIXPConnectWrappedNative> wrapper; ccxp->GetCalleeWrapper(getter_AddRefs(wrapper)); wrapper->GetJSObject(&obj); // Do the security check if necessary XPCContext* xpcc = XPCContext::GetXPCContext(cx); nsIXPCSecurityManager* sm; sm = xpcc->GetAppropriateSecurityManager( nsIXPCSecurityManager::HOOK_CREATE_INSTANCE); if(sm && NS_FAILED(sm->CanCreateInstance(cx, mDetails.ID()))) { NS_ERROR("how are we not being called from chrome here?"); return NS_OK; } // If an IID was passed in then use it const nsID* iid = GetIIDArg(argc, argv, cx); if (!iid) return NS_ERROR_XPC_BAD_IID; nsCOMPtr<nsIComponentManager> compMgr; nsresult rv = NS_GetComponentManager(getter_AddRefs(compMgr)); if (NS_FAILED(rv)) return NS_ERROR_UNEXPECTED; nsCOMPtr<nsISupports> inst; rv = compMgr->CreateInstance(mDetails.ID(), nsnull, *iid, getter_AddRefs(inst)); NS_ASSERTION(NS_FAILED(rv) || inst, "component manager returned success, but instance is null!"); if(NS_FAILED(rv) || !inst) return NS_ERROR_XPC_CI_RETURNED_FAILURE; rv = xpc->WrapNativeToJSVal(cx, obj, inst, nsnull, iid, PR_TRUE, vp, nsnull); if(NS_FAILED(rv) || JSVAL_IS_PRIMITIVE(*vp)) return NS_ERROR_XPC_CANT_CREATE_WN; ccxp->SetReturnValueWasSet(JS_TRUE); return NS_OK; }
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; }