void nsJSUtils::ReportPendingException(JSContext *aContext) { if (JS_IsExceptionPending(aContext)) { bool saved = JS_SaveFrameChain(aContext); { // JS_SaveFrameChain set the compartment of aContext to null, so we need // to enter a compartment. The question is, which one? We don't want to // enter the original compartment of aContext (or the compartment of the // current exception on aContext, for that matter) because when we // JS_ReportPendingException the JS engine can try to duck-type the // exception and produce a JSErrorReport. It will then pass that // JSErrorReport to the error reporter on aContext, which might expose // information from it to script via onerror handlers. So it's very // important that the duck typing happen in the same compartment as the // onerror handler. In practice, that's the compartment of the window (or // otherwise default global) of aContext, so use that here. nsIScriptContext* scx = GetScriptContextFromJSContext(aContext); JS::Rooted<JSObject*> scope(aContext); scope = scx ? scx->GetWindowProxy() : js::DefaultObjectForContextOrNull(aContext); if (!scope) { // The SafeJSContext has no default object associated with it. MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(aContext == nsContentUtils::GetSafeJSContext()); scope = xpc::UnprivilegedJunkScope(); // Usage approved by bholley } JSAutoCompartment ac(aContext, scope); JS_ReportPendingException(aContext); } if (saved) { JS_RestoreFrameChain(aContext); } } }
void nsJSUtils::ReportPendingException(JSContext *aContext) { if (JS_IsExceptionPending(aContext)) { bool saved = JS_SaveFrameChain(aContext); { JSAutoCompartment ac(aContext, js::DefaultObjectForContextOrNull(aContext)); JS_ReportPendingException(aContext); } if (saved) { JS_RestoreFrameChain(aContext); } } }
bool CallTrusted(JSContext *cx, unsigned argc, jsval *vp) { if (!JS_SaveFrameChain(cx)) return false; bool ok = false; { JSAutoCompartment ac(cx, trusted_glob); ok = JS_CallFunctionValue(cx, nullptr, JS::ObjectValue(*trusted_fun), 0, nullptr, vp); } JS_RestoreFrameChain(cx); return ok; }
static bool CallTrusted(JSContext *cx, unsigned argc, jsval *vp) { JS::CallArgs args = JS::CallArgsFromVp(argc, vp); if (!JS_SaveFrameChain(cx)) return false; bool ok = false; { JSAutoCompartment ac(cx, trusted_glob); JS::RootedValue funVal(cx, JS::ObjectValue(*trusted_fun)); ok = JS_CallFunctionValue(cx, JS::NullPtr(), funVal, JS::HandleValueArray::empty(), args.rval()); } JS_RestoreFrameChain(cx); return ok; }
void nsJSUtils::ReportPendingException(JSContext *aContext) { if (JS_IsExceptionPending(aContext)) { bool saved = JS_SaveFrameChain(aContext); { nsIScriptContext* scx = GetScriptContextFromJSContext(aContext); JS::Rooted<JSObject*> scope(aContext); scope = scx ? scx->GetWindowProxy() : js::DefaultObjectForContextOrNull(aContext); JSAutoCompartment ac(aContext, scope); JS_ReportPendingException(aContext); } if (saved) { JS_RestoreFrameChain(aContext); } } }
/* void push (in JSContext cx); */ NS_IMETHODIMP XPCJSContextStack::Push(JSContext * cx) { JS_ASSERT_IF(cx, JS_GetContextThread(cx)); if(!mStack.AppendElement(cx)) return NS_ERROR_OUT_OF_MEMORY; if(mStack.Length() > 1) { XPCJSContextInfo & e = mStack[mStack.Length() - 2]; if(e.cx) { if(e.cx == cx) { nsIScriptSecurityManager* ssm = XPCWrapper::GetSecurityManager(); if(ssm) { nsIPrincipal* globalObjectPrincipal = GetPrincipalFromCx(cx); if(globalObjectPrincipal) { nsIPrincipal* subjectPrincipal = ssm->GetCxSubjectPrincipal(cx); PRBool equals = PR_FALSE; globalObjectPrincipal->Equals(subjectPrincipal, &equals); if(equals) { return NS_OK; } } } } { // Push() can be called outside any request for e.cx. JSAutoRequest ar(e.cx); e.frame = JS_SaveFrameChain(e.cx); } if(!cx) e.suspendDepth = JS_SuspendRequest(e.cx); } } return NS_OK; }
JSBool CallTrusted(JSContext *cx, unsigned argc, jsval *vp) { if (!JS_SaveFrameChain(cx)) return JS_FALSE; JSBool ok = JS_FALSE; { JSAutoEnterCompartment ac; ok = ac.enter(cx, trusted_glob.get()); if (!ok) goto out; ok = JS_CallFunctionValue(cx, NULL, OBJECT_TO_JSVAL(trusted_fun.get()), 0, NULL, vp); } out: JS_RestoreFrameChain(cx); return ok; }
SafeCallGuard(JSContext *cx, nsIPrincipal *principal) : cx(cx) { nsIScriptSecurityManager_1_9_2 *ssm = XPCWrapper::GetSecurityManager(); if (ssm) { // Note: We pass null as the target frame pointer because we know that // we're about to set aside the frame chain. nsresult rv = ssm->PushContextPrincipal(cx, nsnull, principal); if (NS_FAILED(rv)) { NS_WARNING("Not allowing call because we're out of memory"); JS_ReportOutOfMemory(cx); this->cx = nsnull; return; } } js_SaveAndClearRegExpStatics(cx, &statics, &tvr, &tvr2); fp = JS_SaveFrameChain(cx); options = JS_SetOptions(cx, JS_GetOptions(cx) | JSOPTION_DONT_REPORT_UNCAUGHT); }
nsresult nsXBLProtoImplAnonymousMethod::Execute(nsIContent* aBoundElement) { NS_PRECONDITION(IsCompiled(), "Can't execute uncompiled method"); if (!mJSMethodObject) { // Nothing to do here return NS_OK; } // Get the script context the same way // nsXBLProtoImpl::InstallImplementation does. nsIDocument* document = aBoundElement->OwnerDoc(); nsIScriptGlobalObject* global = document->GetScriptGlobalObject(); if (!global) { return NS_OK; } nsCOMPtr<nsIScriptContext> context = global->GetContext(); if (!context) { return NS_OK; } JSContext* cx = context->GetNativeContext(); JSObject* globalObject = global->GetGlobalJSObject(); nsCOMPtr<nsIXPConnectJSObjectHolder> wrapper; jsval v; nsresult rv = nsContentUtils::WrapNative(cx, globalObject, aBoundElement, &v, getter_AddRefs(wrapper)); NS_ENSURE_SUCCESS(rv, rv); JSObject* thisObject = JSVAL_TO_OBJECT(v); JSAutoRequest ar(cx); JSAutoEnterCompartment ac; if (!ac.enter(cx, thisObject)) return NS_ERROR_UNEXPECTED; // Clone the function object, using thisObject as the parent so "this" is in // the scope chain of the resulting function (for backwards compat to the // days when this was an event handler). JSObject* method = ::JS_CloneFunctionObject(cx, mJSMethodObject, thisObject); if (!method) return NS_ERROR_OUT_OF_MEMORY; // Now call the method // Use nsCxPusher to make sure we call ScriptEvaluated when we're done. nsCxPusher pusher; NS_ENSURE_STATE(pusher.Push(aBoundElement)); // Check whether it's OK to call the method. rv = nsContentUtils::GetSecurityManager()->CheckFunctionAccess(cx, method, thisObject); JSBool ok = JS_TRUE; if (NS_SUCCEEDED(rv)) { jsval retval; ok = ::JS_CallFunctionValue(cx, thisObject, OBJECT_TO_JSVAL(method), 0 /* argc */, nsnull /* argv */, &retval); } if (!ok) { // If a constructor or destructor threw an exception, it doesn't stop // anything else. We just report it. Note that we need to set aside the // frame chain here, since the constructor invocation is not related to // whatever is on the stack right now, really. JSBool saved = JS_SaveFrameChain(cx); JS_ReportPendingException(cx); if (saved) JS_RestoreFrameChain(cx); return NS_ERROR_FAILURE; } return NS_OK; }