From c338f2025d12a5b0490a422f69f27f45e0478059 Mon Sep 17 00:00:00 2001 From: Bobby Holley Date: Thu, 6 Mar 2014 08:55:00 -0800 Subject: [PATCH] Bug 979481 - Separate the lifetime of the SafeJSContext global from that of the SafeJSContext itself. r=bz --- js/xpconnect/src/XPCJSContextStack.cpp | 33 +++++++++++++++++--------- js/xpconnect/src/XPCJSRuntime.cpp | 6 +++++ js/xpconnect/src/xpcprivate.h | 3 +++ js/xpconnect/src/xpcpublic.h | 7 ++++++ 4 files changed, 38 insertions(+), 11 deletions(-) diff --git a/js/xpconnect/src/XPCJSContextStack.cpp b/js/xpconnect/src/XPCJSContextStack.cpp index 822ad9e9dca..1506a151cc6 100644 --- a/js/xpconnect/src/XPCJSContextStack.cpp +++ b/js/xpconnect/src/XPCJSContextStack.cpp @@ -23,6 +23,11 @@ using mozilla::dom::DestroyProtoAndIfaceCache; XPCJSContextStack::~XPCJSContextStack() { if (mSafeJSContext) { + { + JSAutoRequest ar(mSafeJSContext); + JS_RemoveObjectRoot(mSafeJSContext, &mSafeJSContextGlobal); + } + mSafeJSContextGlobal = nullptr; JS_DestroyContextNoGC(mSafeJSContext); mSafeJSContext = nullptr; } @@ -142,6 +147,13 @@ XPCJSContextStack::GetSafeJSContext() return mSafeJSContext; } +JSObject* +XPCJSContextStack::GetSafeJSContextGlobal() +{ + MOZ_ASSERT(mSafeJSContextGlobal); + return mSafeJSContextGlobal; +} + JSContext* XPCJSContextStack::InitSafeJSContext() { @@ -164,31 +176,30 @@ XPCJSContextStack::InitSafeJSContext() MOZ_CRASH(); JSAutoRequest req(mSafeJSContext); - JS::RootedObject glob(mSafeJSContext); JS_SetErrorReporter(mSafeJSContext, xpc::SystemErrorReporter); JS::CompartmentOptions options; options.setZone(JS::SystemZone); - glob = xpc::CreateGlobalObject(mSafeJSContext, &SafeJSContextGlobalClass, principal, options); - if (!glob) + mSafeJSContextGlobal = CreateGlobalObject(mSafeJSContext, + &SafeJSContextGlobalClass, + principal, options); + if (!mSafeJSContextGlobal) MOZ_CRASH(); + JS_AddNamedObjectRoot(mSafeJSContext, &mSafeJSContextGlobal, "SafeJSContext global"); // Make sure the context is associated with a proper compartment // and not the default compartment. - js::SetDefaultObjectForContext(mSafeJSContext, glob); + js::SetDefaultObjectForContext(mSafeJSContext, mSafeJSContextGlobal); // Note: make sure to set the private before calling // InitClasses - nsRefPtr sp = new SandboxPrivate(principal, glob); - JS_SetPrivate(glob, sp.forget().get()); + nsRefPtr sp = new SandboxPrivate(principal, mSafeJSContextGlobal); + JS_SetPrivate(mSafeJSContextGlobal, sp.forget().get()); - // After this point either glob is null and the - // nsIScriptObjectPrincipal ownership is either handled by the - // nsCOMPtr or dealt with, or we'll release in the finalize - // hook. - if (NS_FAILED(xpc->InitClasses(mSafeJSContext, glob))) + if (NS_FAILED(xpc->InitClasses(mSafeJSContext, mSafeJSContextGlobal))) MOZ_CRASH(); + JS::RootedObject glob(mSafeJSContext, mSafeJSContextGlobal); JS_FireOnNewGlobalObject(mSafeJSContext, glob); return mSafeJSContext; diff --git a/js/xpconnect/src/XPCJSRuntime.cpp b/js/xpconnect/src/XPCJSRuntime.cpp index 680871cc7f8..cd55894acbe 100644 --- a/js/xpconnect/src/XPCJSRuntime.cpp +++ b/js/xpconnect/src/XPCJSRuntime.cpp @@ -586,6 +586,12 @@ GetJunkScopeGlobal() return GetNativeForGlobal(junkScope); } +JSObject * +GetSafeJSContextGlobal() +{ + return XPCJSRuntime::Get()->GetJSContextStack()->GetSafeJSContextGlobal(); +} + nsGlobalWindow* WindowGlobalOrNull(JSObject *aObj) { diff --git a/js/xpconnect/src/xpcprivate.h b/js/xpconnect/src/xpcprivate.h index 0c7ebd87d12..76c31a8f3f5 100644 --- a/js/xpconnect/src/xpcprivate.h +++ b/js/xpconnect/src/xpcprivate.h @@ -2777,6 +2777,7 @@ public: XPCJSContextStack(XPCJSRuntime *aRuntime) : mRuntime(aRuntime) , mSafeJSContext(nullptr) + , mSafeJSContextGlobal(nullptr) { } virtual ~XPCJSContextStack(); @@ -2793,6 +2794,7 @@ public: JSContext *InitSafeJSContext(); JSContext *GetSafeJSContext(); + JSObject *GetSafeJSContextGlobal(); bool HasJSContext(JSContext *cx); const InfallibleTArray* GetStack() @@ -2811,6 +2813,7 @@ private: AutoInfallibleTArray mStack; XPCJSRuntime* mRuntime; JSContext* mSafeJSContext; + JSObject* mSafeJSContextGlobal; }; /***************************************************************************/ diff --git a/js/xpconnect/src/xpcpublic.h b/js/xpconnect/src/xpcpublic.h index cc7eb7bc135..82a1fae6c83 100644 --- a/js/xpconnect/src/xpcpublic.h +++ b/js/xpconnect/src/xpcpublic.h @@ -424,6 +424,13 @@ GetJunkScope(); nsIGlobalObject * GetJunkScopeGlobal(); +/** + * Returns the dummy global associated with the SafeJSContext. Callers MUST + * consult with the XPConnect module owner before using this function. + */ +JSObject * +GetSafeJSContextGlobal(); + /** * If |aObj| has a window for a global, returns the associated nsGlobalWindow. * Otherwise, returns null.