Keep a strong reference to the context that we're operating on. This involves

giving the sandbox context an nsISupports private data that controls its
lifetime. bug 337462, r+sr=jst
This commit is contained in:
mrbkap%gmail.com 2006-06-24 04:33:24 +00:00
parent 4324b7ee9a
commit 7b1e11248b
2 changed files with 49 additions and 11 deletions

View File

@ -2394,6 +2394,36 @@ nsXPCComponents_utils_Sandbox::CallOrConstruct(nsIXPConnectWrappedNative *wrappe
#endif
}
class ContextHolder : public nsISupports
{
public:
ContextHolder(JSContext *aOuterCx, JSObject *aSandbox);
JSContext * GetJSContext()
{
return mJSContext;
}
NS_DECL_ISUPPORTS
private:
XPCAutoJSContext mJSContext;
};
NS_IMPL_ISUPPORTS0(ContextHolder)
ContextHolder::ContextHolder(JSContext *aOuterCx, JSObject *aSandbox)
: mJSContext(JS_NewContext(JS_GetRuntime(aOuterCx), 1024), JS_FALSE)
{
if (mJSContext) {
JS_SetOptions(mJSContext,
JSOPTION_DONT_REPORT_UNCAUGHT |
JSOPTION_PRIVATE_IS_NSISUPPORTS);
JS_SetGlobalObject(mJSContext, aSandbox);
JS_SetContextPrivate(mJSContext, this);
}
}
/***************************************************************************/
/* void evalInSandbox(in AString source, in nativeobj sandbox); */
@ -2460,21 +2490,18 @@ nsXPCComponents_Utils::EvalInSandbox(const nsAString &source)
return NS_ERROR_FAILURE;
}
XPCAutoJSContext sandcx(JS_NewContext(JS_GetRuntime(cx), 1024), false);
if(!sandcx) {
nsRefPtr<ContextHolder> sandcx = new ContextHolder(cx, sandbox);
if(!sandcx || !sandcx->GetJSContext()) {
JS_ReportError(cx, "Can't prepare context for evalInSandbox");
JSPRINCIPALS_DROP(cx, jsPrincipals);
return NS_ERROR_OUT_OF_MEMORY;
}
JS_SetOptions(sandcx, JSOPTION_DONT_REPORT_UNCAUGHT);
JS_SetGlobalObject(sandcx, sandbox);
XPCPerThreadData *data = XPCPerThreadData::GetData();
XPCJSContextStack *stack;
PRBool popContext = PR_FALSE;
if (data && (stack = data->GetJSContextStack())) {
if (NS_FAILED(stack->Push(sandcx))) {
if (NS_FAILED(stack->Push(sandcx->GetJSContext()))) {
JS_ReportError(cx,
"Unable to initialize XPConnect with the sandbox context");
JSPRINCIPALS_DROP(cx, jsPrincipals);
@ -2500,15 +2527,16 @@ nsXPCComponents_Utils::EvalInSandbox(const nsAString &source)
}
}
AutoJSRequestWithNoCallContext req(sandcx);
if (!JS_EvaluateUCScriptForPrincipals(sandcx, sandbox, jsPrincipals,
AutoJSRequestWithNoCallContext req(sandcx->GetJSContext());
if (!JS_EvaluateUCScriptForPrincipals(sandcx->GetJSContext(), sandbox,
jsPrincipals,
NS_REINTERPRET_CAST(const jschar *,
PromiseFlatString(source).get()),
source.Length(), filename.get(),
lineNo, rval)) {
jsval exn;
if (JS_GetPendingException(sandcx, &exn)) {
AutoJSSuspendRequestWithNoCallContext sus(sandcx);
if (JS_GetPendingException(sandcx->GetJSContext(), &exn)) {
AutoJSSuspendRequestWithNoCallContext sus(sandcx->GetJSContext());
AutoJSRequestWithNoCallContext cxreq(cx);
JS_SetPendingException(cx, exn);

View File

@ -155,6 +155,7 @@ class nsCryptoRunArgs : public nsISupports {
public:
nsCryptoRunArgs();
virtual ~nsCryptoRunArgs();
nsCOMPtr<nsISupports> m_kungFuDeathGrip;
JSContext *m_cx;
JSObject *m_scope;
nsCOMPtr<nsIPrincipal> m_principals;
@ -1413,7 +1414,15 @@ loser:
return nsnull;;
}
static nsISupports *
GetISupportsFromContext(JSContext *cx)
{
if (JS_GetOptions(cx) & JSOPTION_PRIVATE_IS_NSISUPPORTS)
return NS_STATIC_CAST(nsISupports *, JS_GetContextPrivate(cx));
return nsnull;
}
//The top level method which is a member of nsIDOMCrypto
//for generate a base64 encoded CRMF request.
NS_IMETHODIMP
@ -1620,6 +1629,7 @@ nsCrypto::GenerateCRMFRequest(nsIDOMCRMFObject** aReturn)
return NS_ERROR_OUT_OF_MEMORY;
args->m_cx = cx;
args->m_kungFuDeathGrip = GetISupportsFromContext(cx);
args->m_scope = JS_GetParent(cx, script_obj);
args->m_jsCallback.Adopt(jsCallback ? nsCRT::strdup(jsCallback) : 0);
args->m_principals = principals;