Bug 451731 - "Update caps, dom, xpconnect for Bug 451729 (checkObjectAccess moving to the JSContext)". r+sr=jst.
authorBen Turner <bent.mozilla@gmail.com>
Fri, 05 Sep 2008 16:26:04 -0700
changeset 18871 825b049918201d06b80d89f7f47b583b7b19cb90
parent 18870 7da53f4cd7129da668b69c3ac0238713800a960c
child 18872 1799243b908953cfef4cc2610ffae1e8c90a0680
push idunknown
push userunknown
push dateunknown
bugs451731, 451729
milestone1.9.1b1pre
Bug 451731 - "Update caps, dom, xpconnect for Bug 451729 (checkObjectAccess moving to the JSContext)". r+sr=jst.
caps/src/nsJSPrincipals.cpp
caps/src/nsScriptSecurityManager.cpp
dom/src/base/nsJSEnvironment.cpp
js/src/xpconnect/src/XPCNativeWrapper.cpp
js/src/xpconnect/src/XPCSafeJSObjectWrapper.cpp
--- a/caps/src/nsJSPrincipals.cpp
+++ b/caps/src/nsJSPrincipals.cpp
@@ -174,20 +174,23 @@ nsJSPrincipals::Startup()
     nsCOMPtr<nsIJSRuntimeService> rtsvc(do_GetService(rtsvc_id));
     if (!rtsvc)
         return NS_ERROR_FAILURE;
 
     JSRuntime *rt;
     rtsvc->GetRuntime(&rt);
     NS_ASSERTION(rt != nsnull, "no JSRuntime?!");
 
-    JSPrincipalsTranscoder oldpx;
-    oldpx = ::JS_SetPrincipalsTranscoder(rt, nsTranscodeJSPrincipals);
-    NS_ASSERTION(oldpx == nsnull, "oops, JS_SetPrincipalsTranscoder wars!");
+    JSSecurityCallbacks *callbacks = JS_GetRuntimeSecurityCallbacks(rt);
+    NS_ASSERTION(callbacks, "Need a callbacks struct by now!");
 
+    NS_ASSERTION(!callbacks->principalsTranscoder,
+                 "oops, JS_SetPrincipalsTranscoder wars!");
+
+    callbacks->principalsTranscoder = nsTranscodeJSPrincipals;
     return NS_OK;
 }
 
 nsJSPrincipals::nsJSPrincipals()
 {
     codebase = nsnull;
     getPrincipalArray = nsGetPrincipalArray;
     globalPrivilegesEnabled = nsGlobalPrivilegesEnabled;
--- a/caps/src/nsScriptSecurityManager.cpp
+++ b/caps/src/nsScriptSecurityManager.cpp
@@ -3220,27 +3220,31 @@ nsresult nsScriptSecurityManager::Init()
     //   Currently this is used to control access to function.caller
     nsCOMPtr<nsIJSRuntimeService> runtimeService =
         do_GetService("@mozilla.org/js/xpc/RuntimeService;1", &rv);
     NS_ENSURE_SUCCESS(rv, rv);
 
     rv = runtimeService->GetRuntime(&sRuntime);
     NS_ENSURE_SUCCESS(rv, rv);
 
+    static JSSecurityCallbacks securityCallbacks = {
+      CheckObjectAccess,
+      NULL,
+      NULL
+    };
+
 #ifdef DEBUG
-    JSCheckAccessOp oldCallback =
+    JSSecurityCallbacks *oldcallbacks =
 #endif
-        JS_SetCheckObjectAccessCallback(sRuntime, CheckObjectAccess);
+    JS_SetRuntimeSecurityCallbacks(sRuntime, &securityCallbacks);
+    NS_ASSERTION(!oldcallbacks, "Someone else set security callbacks!");
 
     sXPConnect->GetXPCWrappedNativeJSClassInfo(&sXPCWrappedNativeJSClass,
                                                &sXPCWrappedNativeGetObjOps1,
                                                &sXPCWrappedNativeGetObjOps2);
-
-    // For now, assert that no callback was set previously
-    NS_ASSERTION(!oldCallback, "Someone already set a JS CheckObjectAccess callback");
     return NS_OK;
 }
 
 static nsScriptSecurityManager *gScriptSecMan = nsnull;
 
 jsval nsScriptSecurityManager::sEnabledID   = JSVAL_VOID;
 
 nsScriptSecurityManager::~nsScriptSecurityManager(void)
@@ -3251,21 +3255,17 @@ nsScriptSecurityManager::~nsScriptSecuri
     delete mCapabilities;
     gScriptSecMan = nsnull;
 }
 
 void
 nsScriptSecurityManager::Shutdown()
 {
     if (sRuntime) {
-#ifdef DEBUG
-        JSCheckAccessOp oldCallback =
-#endif
-            JS_SetCheckObjectAccessCallback(sRuntime, nsnull);
-        NS_ASSERTION(oldCallback == CheckObjectAccess, "Oops, we just clobbered someone else, oh well.");
+        JS_SetRuntimeSecurityCallbacks(sRuntime, NULL);
         sRuntime = nsnull;
     }
     sEnabledID = JSVAL_VOID;
 
     NS_IF_RELEASE(sIOService);
     NS_IF_RELEASE(sXPConnect);
     NS_IF_RELEASE(sStrBundle);
 }
--- a/dom/src/base/nsJSEnvironment.cpp
+++ b/dom/src/base/nsJSEnvironment.cpp
@@ -3763,38 +3763,40 @@ nsJSRuntime::Init()
 {
   if (sIsInitialized) {
     if (!nsContentUtils::XPConnect())
       return NS_ERROR_NOT_AVAILABLE;
 
     return NS_OK;
   }
 
-  nsresult rv = CallGetService(kJSRuntimeServiceContractID, &sRuntimeService);
+  nsresult rv = CallGetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID,
+                               &sSecurityManager);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  rv = CallGetService(kJSRuntimeServiceContractID, &sRuntimeService);
   // get the JSRuntime from the runtime svc, if possible
   NS_ENSURE_SUCCESS(rv, rv);
 
   rv = sRuntimeService->GetRuntime(&sRuntime);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // Let's make sure that our main thread is the same as the xpcom main thread.
   NS_ASSERTION(NS_IsMainThread(), "bad");
 
   NS_ASSERTION(!gOldJSGCCallback,
                "nsJSRuntime initialized more than once");
 
   // Save the old GC callback to chain to it, for GC-observing generality.
   gOldJSGCCallback = ::JS_SetGCCallbackRT(sRuntime, DOMGCCallback);
 
-  // No chaining to a pre-existing callback here, we own this problem space.
-#ifdef NS_DEBUG
-  JSObjectPrincipalsFinder oldfop =
-#endif
-    ::JS_SetObjectPrincipalsFinder(sRuntime, ObjectPrincipalFinder);
-  NS_ASSERTION(!oldfop, " fighting over the findObjectPrincipals callback!");
+  JSSecurityCallbacks *callbacks = JS_GetRuntimeSecurityCallbacks(sRuntime);
+  NS_ASSERTION(callbacks, "SecMan should have set security callbacks!");
+
+  callbacks->findObjectPrincipals = ObjectPrincipalFinder;
 
   // Set these global xpconnect options...
   nsContentUtils::RegisterPrefCallback("dom.max_script_run_time",
                                        MaxScriptRunTimePrefChangedCallback,
                                        nsnull);
   MaxScriptRunTimePrefChangedCallback("dom.max_script_run_time", nsnull);
 
   nsContentUtils::RegisterPrefCallback("dom.max_chrome_script_run_time",
@@ -3817,19 +3819,17 @@ nsJSRuntime::Init()
   obs->AddObserver(activityObserver, "user-interaction-inactive", PR_FALSE);
   obs->AddObserver(activityObserver, "user-interaction-active", PR_FALSE);
   obs->AddObserver(activityObserver, "xpcom-shutdown", PR_FALSE);
 
   nsIObserver* ccMemPressureObserver = new nsCCMemoryPressureObserver();
   NS_ENSURE_TRUE(ccMemPressureObserver, NS_ERROR_OUT_OF_MEMORY);
   obs->AddObserver(ccMemPressureObserver, "memory-pressure", PR_FALSE);
 
-  rv = CallGetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &sSecurityManager);
-
-  sIsInitialized = NS_SUCCEEDED(rv);
+  sIsInitialized = PR_TRUE;
 
   return rv;
 }
 
 //static
 nsScriptNameSpaceManager*
 nsJSRuntime::GetNameSpaceManager()
 {
@@ -3863,22 +3863,22 @@ void nsJSRuntime::ShutDown()
   delete gNameSpaceManager;
   gNameSpaceManager = nsnull;
 
   if (!sContextCount) {
     // We're being shutdown, and there are no more contexts
     // alive, release the JS runtime service and the security manager.
 
     if (sRuntimeService && sSecurityManager) {
-      // No chaining to a pre-existing callback here, we own this problem space.
-#ifdef NS_DEBUG
-      JSObjectPrincipalsFinder oldfop =
-#endif
-        ::JS_SetObjectPrincipalsFinder(sRuntime, nsnull);
-      NS_ASSERTION(oldfop == ObjectPrincipalFinder, " fighting over the findObjectPrincipals callback!");
+      JSSecurityCallbacks *callbacks = JS_GetRuntimeSecurityCallbacks(sRuntime);
+      if (callbacks) {
+        NS_ASSERTION(callbacks->findObjectPrincipals == ObjectPrincipalFinder,
+                     "Fighting over the findObjectPrincipals callback!");
+        callbacks->findObjectPrincipals = NULL;
+      }
     }
     NS_IF_RELEASE(sRuntimeService);
     NS_IF_RELEASE(sSecurityManager);
     NS_IF_RELEASE(gCollation);
     NS_IF_RELEASE(gDecoder);
   }
 
   sDidShutdown = PR_TRUE;
--- a/js/src/xpconnect/src/XPCNativeWrapper.cpp
+++ b/js/src/xpconnect/src/XPCNativeWrapper.cpp
@@ -674,18 +674,19 @@ XPC_NW_CheckAccess(JSContext *cx, JSObje
                    JSAccessMode mode, jsval *vp)
 {
   // Prevent setting __proto__ on an XPCNativeWrapper
   if ((mode & JSACC_WATCH) == JSACC_PROTO && (mode & JSACC_WRITE)) {
     return ThrowException(NS_ERROR_XPC_SECURITY_MANAGER_VETO, cx);
   }
 
   // Forward to the checkObjectAccess hook in the JSContext, if any.
-  if (cx->runtime->checkObjectAccess &&
-      !cx->runtime->checkObjectAccess(cx, obj, id, mode, vp)) {
+  JSSecurityCallbacks *callbacks = JS_GetSecurityCallbacks(cx);
+  if (callbacks && callbacks->checkObjectAccess &&
+      !callbacks->checkObjectAccess(cx, obj, id, mode, vp)) {
     return JS_FALSE;
   }
 
   XPCWrappedNative *wrappedNative = XPCNativeWrapper::GetWrappedNative(obj);
   if (!wrappedNative) {
     return JS_TRUE;
   }
 
--- a/js/src/xpconnect/src/XPCSafeJSObjectWrapper.cpp
+++ b/js/src/xpconnect/src/XPCSafeJSObjectWrapper.cpp
@@ -686,30 +686,31 @@ XPC_SJOW_CheckAccess(JSContext *cx, JSOb
                      JSAccessMode mode, jsval *vp)
 {
   // Prevent setting __proto__ on an XPCSafeJSObjectWrapper
   if ((mode & JSACC_WATCH) == JSACC_PROTO && (mode & JSACC_WRITE)) {
     return ThrowException(NS_ERROR_XPC_SECURITY_MANAGER_VETO, cx);
   }
 
   // Forward to the checkObjectAccess hook in the runtime, if any.
-  if (cx->runtime->checkObjectAccess &&
-      !cx->runtime->checkObjectAccess(cx, obj, id, mode, vp)) {
+  JSSecurityCallbacks *callbacks = JS_GetSecurityCallbacks(cx);
+  if (callbacks && callbacks->checkObjectAccess &&
+      !callbacks->checkObjectAccess(cx, obj, id, mode, vp)) {
     return JS_FALSE;
   }
 
   JSObject *unsafeObj = GetUnsafeObject(obj);
   if (!unsafeObj) {
     return JS_TRUE;
   }
 
   // Forward the unsafe object to the checkObjectAccess hook in the
   // runtime too, if any.
-  if (cx->runtime->checkObjectAccess &&
-      !cx->runtime->checkObjectAccess(cx, unsafeObj, id, mode, vp)) {
+  if (callbacks && callbacks->checkObjectAccess &&
+      !callbacks->checkObjectAccess(cx, unsafeObj, id, mode, vp)) {
     return JS_FALSE;
   }
 
   JSClass *clazz = STOBJ_GET_CLASS(unsafeObj);
   return !clazz->checkAccess ||
     clazz->checkAccess(cx, unsafeObj, id, mode, vp);
 }