From 3d1a1af69783cba9731afc76bb3a1cb6c6e366fc Mon Sep 17 00:00:00 2001 From: Bobby Holley Date: Fri, 6 Sep 2013 11:35:11 -0700 Subject: [PATCH] Bug 905364 - Don't call into AllowXULXBLForPrincipal during SafeJSContext initialization. r=bz In the old world, we'd be saved by initializing the SafeJSContext early enough that we'd short-circuit in the nsContentUtils::IsInitialized() check. That's not the case anymore, so let's hande this explicitly. --- js/xpconnect/src/XPCJSContextStack.cpp | 4 ++-- js/xpconnect/src/XPCWrappedNativeScope.cpp | 22 +++++++++++++++------- js/xpconnect/src/xpcprivate.h | 2 ++ 3 files changed, 19 insertions(+), 9 deletions(-) diff --git a/js/xpconnect/src/XPCJSContextStack.cpp b/js/xpconnect/src/XPCJSContextStack.cpp index 798938b1709..913fcdd6871 100644 --- a/js/xpconnect/src/XPCJSContextStack.cpp +++ b/js/xpconnect/src/XPCJSContextStack.cpp @@ -125,7 +125,7 @@ SafeFinalize(JSFreeOp *fop, JSObject* obj) DestroyProtoAndIfaceCache(obj); } -static JSClass global_class = { +JSClass xpc::SafeJSContextGlobalClass = { "global_for_XPCJSContextStack_SafeJSContext", XPCONNECT_GLOBAL_FLAGS, JS_PropertyStub, JS_DeletePropertyStub, JS_PropertyStub, JS_StrictPropertyStub, @@ -161,7 +161,7 @@ XPCJSContextStack::GetSafeJSContext() JS::CompartmentOptions options; options.setZone(JS::SystemZone); - glob = xpc::CreateGlobalObject(mSafeJSContext, &global_class, principal, options); + glob = xpc::CreateGlobalObject(mSafeJSContext, &SafeJSContextGlobalClass, principal, options); if (!glob) MOZ_CRASH(); diff --git a/js/xpconnect/src/XPCWrappedNativeScope.cpp b/js/xpconnect/src/XPCWrappedNativeScope.cpp index c2b71876c8f..8255061cedc 100644 --- a/js/xpconnect/src/XPCWrappedNativeScope.cpp +++ b/js/xpconnect/src/XPCWrappedNativeScope.cpp @@ -18,6 +18,7 @@ using namespace mozilla; using namespace xpc; +using namespace JS; /***************************************************************************/ @@ -97,17 +98,24 @@ XPCWrappedNativeScope::GetNewOrUsed(JSContext *cx, JS::HandleObject aGlobal) } static bool -RemoteXULForbidsXBLScope(nsIPrincipal *aPrincipal) +RemoteXULForbidsXBLScope(nsIPrincipal *aPrincipal, HandleObject aGlobal) { - // We end up getting called during SSM bootstrapping to create the - // SafeJSContext. In that case, nsContentUtils isn't ready for us. - // - // Also check for random JSD scopes that don't have a principal. - if (!nsContentUtils::IsInitialized() || !aPrincipal) + // Check for random JSD scopes that don't have a principal. + if (!aPrincipal) + return false; + + // The SafeJSContext is lazily created, and tends to be created at really + // weird times, at least for xpcshell (often very early in startup or late + // in shutdown). Its scope isn't system principal, so if we proceeded we'd + // end up calling into AllowXULXBLForPrincipal, which depends on all kinds + // of persistent storage and permission machinery that may or not be running. + // We know the answer to the question here, so just short-circuit. + if (JS_GetClass(aGlobal) == &SafeJSContextGlobalClass) return false; // AllowXULXBLForPrincipal will return true for system principal, but we // don't want that here. + MOZ_ASSERT(nsContentUtils::IsInitialized()); if (nsContentUtils::IsSystemPrincipal(aPrincipal)) return false; @@ -161,7 +169,7 @@ XPCWrappedNativeScope::XPCWrappedNativeScope(JSContext *cx, // In addition to being pref-controlled, we also disable XBL scopes for // remote XUL domains, _except_ if we have an additional pref override set. nsIPrincipal *principal = GetPrincipal(); - mAllowXBLScope = !RemoteXULForbidsXBLScope(principal); + mAllowXBLScope = !RemoteXULForbidsXBLScope(principal, aGlobal); // Determine whether to use an XBL scope. mUseXBLScope = mAllowXBLScope; diff --git a/js/xpconnect/src/xpcprivate.h b/js/xpconnect/src/xpcprivate.h index 0558a0806b9..623aec19477 100644 --- a/js/xpconnect/src/xpcprivate.h +++ b/js/xpconnect/src/xpcprivate.h @@ -3857,6 +3857,8 @@ GetObjectScope(JSObject *obj) extern bool gDebugMode; extern bool gDesiredDebugMode; +extern JSClass SafeJSContextGlobalClass; + JSObject* NewOutObject(JSContext* cx, JSObject* scope); bool IsOutObject(JSContext* cx, JSObject* obj);