mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-07 07:04:09 +00:00
Bug 593742 - nsDOMWorker has to set the right compartment. r=bent.
--HG-- extra : rebase_source : 1f309d333686fdad21a7b6940873994ccc64157d
This commit is contained in:
parent
1773e67db8
commit
04c9fcd6a0
@ -395,35 +395,41 @@ public:
|
||||
JS_TriggerOperationCallback(cx);
|
||||
|
||||
PRBool killWorkerWhenDone;
|
||||
{
|
||||
nsLazyAutoRequest ar;
|
||||
JSAutoCrossCompartmentCall axcc;
|
||||
|
||||
// Tell the worker which context it will be using
|
||||
if (mWorker->SetGlobalForContext(cx)) {
|
||||
RunQueue(cx, &killWorkerWhenDone);
|
||||
// Tell the worker which context it will be using
|
||||
if (mWorker->SetGlobalForContext(cx, &ar, &axcc)) {
|
||||
NS_ASSERTION(ar.entered(), "SetGlobalForContext must enter request on success");
|
||||
NS_ASSERTION(axcc.entered(), "SetGlobalForContext must enter xcc on success");
|
||||
|
||||
// Code in XPConnect assumes that the context's global object won't be
|
||||
// replaced outside of a request.
|
||||
JSAutoRequest ar(cx);
|
||||
RunQueue(cx, &killWorkerWhenDone);
|
||||
|
||||
// Remove the global object from the context so that it might be garbage
|
||||
// collected.
|
||||
JS_SetGlobalObject(cx, NULL);
|
||||
JS_SetContextPrivate(cx, NULL);
|
||||
}
|
||||
else {
|
||||
{
|
||||
// Code in XPConnect assumes that the context's global object won't be
|
||||
// replaced outside of a request.
|
||||
JSAutoRequest ar(cx);
|
||||
|
||||
// This is usually due to a parse error in the worker script...
|
||||
// Remove the global object from the context so that it might be garbage
|
||||
// collected.
|
||||
JS_SetGlobalObject(cx, NULL);
|
||||
JS_SetContextPrivate(cx, NULL);
|
||||
}
|
||||
else {
|
||||
NS_ASSERTION(!ar.entered(), "SetGlobalForContext must not enter request on failure");
|
||||
NS_ASSERTION(!axcc.entered(), "SetGlobalForContext must not enter xcc on failure");
|
||||
|
||||
nsAutoMonitor mon(gDOMThreadService->mMonitor);
|
||||
killWorkerWhenDone = mKillWorkerWhenDone;
|
||||
gDOMThreadService->WorkerComplete(this);
|
||||
mon.NotifyAll();
|
||||
{
|
||||
// Code in XPConnect assumes that the context's global object won't be
|
||||
// replaced outside of a request.
|
||||
JSAutoRequest ar2(cx);
|
||||
|
||||
// This is usually due to a parse error in the worker script...
|
||||
JS_SetGlobalObject(cx, NULL);
|
||||
JS_SetContextPrivate(cx, NULL);
|
||||
}
|
||||
|
||||
nsAutoMonitor mon(gDOMThreadService->mMonitor);
|
||||
killWorkerWhenDone = mKillWorkerWhenDone;
|
||||
gDOMThreadService->WorkerComplete(this);
|
||||
mon.NotifyAll();
|
||||
}
|
||||
}
|
||||
|
||||
if (killWorkerWhenDone) {
|
||||
|
@ -1560,26 +1560,41 @@ nsDOMWorker::PostMessageInternal(PRBool aToInner)
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsDOMWorker::SetGlobalForContext(JSContext* aCx)
|
||||
nsDOMWorker::SetGlobalForContext(JSContext* aCx, nsLazyAutoRequest *aRequest,
|
||||
JSAutoCrossCompartmentCall *aCall)
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
if (!CompileGlobalObject(aCx)) {
|
||||
if (!CompileGlobalObject(aCx, aRequest, aCall)) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
JSAutoRequest ar(aCx);
|
||||
|
||||
JS_SetGlobalObject(aCx, mGlobal);
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsDOMWorker::CompileGlobalObject(JSContext* aCx)
|
||||
nsDOMWorker::CompileGlobalObject(JSContext* aCx, nsLazyAutoRequest *aRequest,
|
||||
JSAutoCrossCompartmentCall *aCall)
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
// On success, we enter a request and a cross-compartment call that both
|
||||
// belong to the caller. But on failure, we must not remain in a request or
|
||||
// cross-compartment call. So we enter both only locally at first. On
|
||||
// failure, the local request and call will automatically get cleaned
|
||||
// up. Once success is certain, we swap them into *aRequest and *aCall.
|
||||
nsLazyAutoRequest localRequest;
|
||||
JSAutoCrossCompartmentCall localCall;
|
||||
localRequest.enter(aCx);
|
||||
|
||||
PRBool success;
|
||||
if (mGlobal) {
|
||||
success = localCall.enter(aCx, mGlobal);
|
||||
NS_ENSURE_TRUE(success, PR_FALSE);
|
||||
|
||||
aRequest->swap(localRequest);
|
||||
aCall->swap(localCall);
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
@ -1591,8 +1606,6 @@ nsDOMWorker::CompileGlobalObject(JSContext* aCx)
|
||||
|
||||
NS_ASSERTION(!mScriptURL.IsEmpty(), "Must have a url here!");
|
||||
|
||||
JSAutoRequest ar(aCx);
|
||||
|
||||
NS_ASSERTION(!JS_GetGlobalObject(aCx), "Global object should be unset!");
|
||||
|
||||
nsRefPtr<nsDOMWorkerScope> scope = new nsDOMWorkerScope(this);
|
||||
@ -1622,6 +1635,9 @@ nsDOMWorker::CompileGlobalObject(JSContext* aCx)
|
||||
|
||||
NS_ASSERTION(JS_GetGlobalObject(aCx) == global, "Global object mismatch!");
|
||||
|
||||
success = localCall.enter(aCx, global);
|
||||
NS_ENSURE_TRUE(success, PR_FALSE);
|
||||
|
||||
#ifdef DEBUG
|
||||
{
|
||||
jsval components;
|
||||
@ -1633,7 +1649,7 @@ nsDOMWorker::CompileGlobalObject(JSContext* aCx)
|
||||
#endif
|
||||
|
||||
// Set up worker thread functions.
|
||||
PRBool success = JS_DefineFunctions(aCx, global, gDOMWorkerFunctions);
|
||||
success = JS_DefineFunctions(aCx, global, gDOMWorkerFunctions);
|
||||
NS_ENSURE_TRUE(success, PR_FALSE);
|
||||
|
||||
if (mPrivilegeModel == CHROME) {
|
||||
@ -1690,6 +1706,8 @@ nsDOMWorker::CompileGlobalObject(JSContext* aCx)
|
||||
|
||||
NS_ASSERTION(mPrincipal && mURI, "Script loader didn't set our principal!");
|
||||
|
||||
aRequest->swap(localRequest);
|
||||
aCall->swap(localCall);
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
|
@ -105,6 +105,33 @@ private:
|
||||
PRPackedBool mHasOnerror;
|
||||
};
|
||||
|
||||
class nsLazyAutoRequest
|
||||
{
|
||||
public:
|
||||
nsLazyAutoRequest() : mCx(nsnull) {}
|
||||
|
||||
~nsLazyAutoRequest() {
|
||||
if (mCx)
|
||||
JS_EndRequest(mCx);
|
||||
}
|
||||
|
||||
void enter(JSContext *aCx) {
|
||||
JS_BeginRequest(aCx);
|
||||
mCx = aCx;
|
||||
}
|
||||
|
||||
bool entered() const { return mCx != nsnull; }
|
||||
|
||||
void swap(nsLazyAutoRequest &other) {
|
||||
JSContext *tmp = mCx;
|
||||
mCx = other.mCx;
|
||||
other.mCx = tmp;
|
||||
}
|
||||
|
||||
private:
|
||||
JSContext *mCx;
|
||||
};
|
||||
|
||||
class nsDOMWorker : public nsDOMWorkerMessageHandler,
|
||||
public nsIChromeWorker,
|
||||
public nsITimerCallback,
|
||||
@ -174,7 +201,7 @@ public:
|
||||
PRBool IsClosing();
|
||||
PRBool IsSuspended();
|
||||
|
||||
PRBool SetGlobalForContext(JSContext* aCx);
|
||||
PRBool SetGlobalForContext(JSContext* aCx, nsLazyAutoRequest *aRequest, JSAutoCrossCompartmentCall *aCall);
|
||||
|
||||
void SetPool(nsDOMWorkerPool* aPool);
|
||||
|
||||
@ -258,7 +285,7 @@ private:
|
||||
|
||||
nsresult PostMessageInternal(PRBool aToInner);
|
||||
|
||||
PRBool CompileGlobalObject(JSContext* aCx);
|
||||
PRBool CompileGlobalObject(JSContext* aCx, nsLazyAutoRequest *aRequest, JSAutoCrossCompartmentCall *aCall);
|
||||
|
||||
PRUint32 NextTimeoutId() {
|
||||
return ++mNextTimeoutId;
|
||||
|
@ -968,10 +968,18 @@ class JS_PUBLIC_API(JSAutoCrossCompartmentCall)
|
||||
|
||||
bool enter(JSContext *cx, JSObject *target);
|
||||
|
||||
bool entered() const { return call != NULL; }
|
||||
|
||||
~JSAutoCrossCompartmentCall() {
|
||||
if (call)
|
||||
JS_LeaveCrossCompartmentCall(call);
|
||||
}
|
||||
|
||||
void swap(JSAutoCrossCompartmentCall &other) {
|
||||
JSCrossCompartmentCall *tmp = call;
|
||||
call = other.call;
|
||||
other.call = tmp;
|
||||
}
|
||||
};
|
||||
|
||||
class JS_FRIEND_API(JSAutoEnterCompartment)
|
||||
|
Loading…
x
Reference in New Issue
Block a user