Bug 604430 - Make the wantXrays flag apply to values obtained off of the sandbox object itself. r=peterv
authorBlake Kaplan <mrbkap@gmail.com>
Mon, 25 Oct 2010 16:29:13 -0700
changeset 56473 1b0dcd03247911b2ee0167bd9ee69740cab92fde
parent 56472 9c6f0e66f38517de23f2aa84de67a9db40f8879e
child 56474 139dcd10518f1d22fa9e9ea75d975ca85cf0e6d1
push id16567
push usermrbkap@mozilla.com
push dateMon, 25 Oct 2010 23:41:30 +0000
treeherdermozilla-central@eaf6f9566f2e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerspeterv
bugs604430
milestone2.0b8pre
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 604430 - Make the wantXrays flag apply to values obtained off of the sandbox object itself. r=peterv
js/src/xpconnect/src/nsXPConnect.cpp
js/src/xpconnect/src/xpccomponents.cpp
js/src/xpconnect/src/xpcprivate.h
js/src/xpconnect/src/xpcpublic.h
js/src/xpconnect/tests/chrome/test_evalInSandbox.xul
js/src/xpconnect/wrappers/WrapperFactory.cpp
--- a/js/src/xpconnect/src/nsXPConnect.cpp
+++ b/js/src/xpconnect/src/nsXPConnect.cpp
@@ -937,17 +937,17 @@ static JSClass xpcTempGlobalClass = {
     JS_PropertyStub,  JS_PropertyStub,  JS_PropertyStub,  JS_PropertyStub,
     JS_EnumerateStub, TempGlobalResolve, JS_ConvertStub,   nsnull,
     JSCLASS_NO_OPTIONAL_MEMBERS
 };
 
 nsresult
 xpc_CreateGlobalObject(JSContext *cx, JSClass *clasp,
                        const nsACString &origin, nsIPrincipal *principal,
-                       bool preferXrays, JSObject **global,
+                       bool wantXrays, JSObject **global,
                        JSCompartment **compartment)
 {
     XPCCompartmentMap& map = nsXPConnect::GetRuntimeInstance()->GetCompartmentMap();
     nsCAutoString local_origin(origin);
     if(local_origin.EqualsLiteral("file://") && principal)
     {
         nsCOMPtr<nsIURI> uri;
         principal->GetURI(getter_AddRefs(uri));
@@ -968,17 +968,17 @@ xpc_CreateGlobalObject(JSContext *cx, JS
             return UnexpectedFailure(NS_ERROR_FAILURE);
 
         *global = tempGlobal;
         *compartment = tempGlobal->getCompartment();
 
         js::SwitchToCompartment sc(cx, *compartment);
 
         xpc::CompartmentPrivate *priv =
-            new xpc::CompartmentPrivate(ToNewCString(local_origin), preferXrays);
+            new xpc::CompartmentPrivate(ToNewCString(local_origin), wantXrays);
         JS_SetCompartmentPrivate(cx, *compartment, priv);
         map.Put(local_origin, *compartment);
     }
     else
     {
         js::SwitchToCompartment sc(cx, *compartment);
 
 #ifdef DEBUG
--- a/js/src/xpconnect/src/xpccomponents.cpp
+++ b/js/src/xpconnect/src/xpccomponents.cpp
@@ -3160,16 +3160,25 @@ NS_IMPL_THREADSAFE_RELEASE(nsXPCComponen
 #define XPC_MAP_CLASSNAME           nsXPCComponents_utils_Sandbox
 #define XPC_MAP_QUOTED_CLASSNAME   "nsXPCComponents_utils_Sandbox"
 #define                             XPC_MAP_WANT_CALL
 #define                             XPC_MAP_WANT_CONSTRUCT
 #define XPC_MAP_FLAGS               0
 #include "xpc_map_end.h" /* This #undef's the above. */
 
 #ifndef XPCONNECT_STANDALONE
+
+static bool
+WrapForSandbox(JSContext *cx, bool wantXrays, jsval *vp)
+{
+    return wantXrays
+           ? JS_WrapValue(cx, vp)
+           : xpc::WrapperFactory::WaiveXrayAndWrap(cx, vp);
+}
+
 nsresult
 xpc_CreateSandboxObject(JSContext * cx, jsval * vp, nsISupports *prinOrSop, JSObject *proto,
                         bool wantXrays)
 {
     // Create the sandbox global object
     nsresult rv;
     nsCOMPtr<nsIXPConnect> xpc(do_GetService(nsIXPConnect::GetCID(), &rv));
     if(NS_FAILED(rv))
@@ -3258,17 +3267,17 @@ xpc_CreateSandboxObject(JSContext * cx, 
             rv = NS_ERROR_FAILURE;
         }
         if (NS_FAILED(rv))
             return NS_ERROR_XPC_UNEXPECTED;
     }
 
     if (vp) {
         *vp = OBJECT_TO_JSVAL(sandbox);
-        if (!JS_WrapValue(cx, vp)) {
+        if (!WrapForSandbox(cx, wantXrays, vp)) {
             return NS_ERROR_UNEXPECTED;
         }
     }
 
     return NS_OK;
 }
 #endif /* !XPCONNECT_STANDALONE */
 
@@ -3727,17 +3736,21 @@ xpc_EvalInSandbox(JSContext *cx, JSObjec
         } else {
             // Convert the result into something safe for our caller.
             JSAutoRequest req(cx);
             JSAutoEnterCompartment ac;
             if (str) {
                 v = STRING_TO_JSVAL(str);
             }
 
-            if (!ac.enter(cx, callingScope) || !JS_WrapValue(cx, &v)) {
+            xpc::CompartmentPrivate *sandboxdata =
+                static_cast<xpc::CompartmentPrivate *>
+                           (JS_GetCompartmentPrivate(cx, sandbox->getCompartment()));
+            if (!ac.enter(cx, callingScope) ||
+                !WrapForSandbox(cx, sandboxdata->wantXrays, &v)) {
                 rv = NS_ERROR_FAILURE;
             }
 
             if (NS_SUCCEEDED(rv)) {
                 *rval = v;
             }
         }
     }
--- a/js/src/xpconnect/src/xpcprivate.h
+++ b/js/src/xpconnect/src/xpcprivate.h
@@ -4426,23 +4426,23 @@ xpc_SameScope(XPCWrappedNativeScope *obj
 
 nsISupports *
 XPC_GetIdentityObject(JSContext *cx, JSObject *obj);
 
 namespace xpc {
 
 struct CompartmentPrivate
 {
-  CompartmentPrivate(char *origin, bool preferXrays)
+  CompartmentPrivate(char *origin, bool wantXrays)
     : origin(origin),
-      preferXrays(preferXrays)
+      wantXrays(wantXrays)
   {
   }
   char *origin;
-  bool preferXrays;
+  bool wantXrays;
 };
 
 }
 
 #ifdef XPC_IDISPATCH_SUPPORT
 
 #ifdef WINCE
 /* defined static near the top here */
--- a/js/src/xpconnect/src/xpcpublic.h
+++ b/js/src/xpconnect/src/xpcpublic.h
@@ -42,12 +42,12 @@
 
 #include "jsapi.h"
 #include "nsAString.h"
 #include "nsIPrincipal.h"
 
 nsresult
 xpc_CreateGlobalObject(JSContext *cx, JSClass *clasp,
                        const nsACString &origin, nsIPrincipal *principal,
-                       bool preferXrays, JSObject **global,
+                       bool wantXrays, JSObject **global,
                        JSCompartment **compartment);
 
 #endif
--- a/js/src/xpconnect/tests/chrome/test_evalInSandbox.xul
+++ b/js/src/xpconnect/tests/chrome/test_evalInSandbox.xul
@@ -38,45 +38,60 @@ https://bugzilla.mozilla.org/show_bug.cg
              "Proxy",
              "sandbox was wrapped correctly");
 
           is(utils.getClassName(Cu.evalInSandbox("this.document", sandbox)),
              "Proxy",
              "return value was rewrapped correctly");
       }
 
+      function checkCrossOriginXrayedSandbox(sandbox)
+      {
+        ok(Cu.evalInSandbox("('wrappedJSObject' in this.document);", sandbox),
+           "wrappers inside eIS are Xrays");
+        ok(Cu.evalInSandbox("!('foo' in this.document);", sandbox),
+           "must not see expandos");
+        ok('wrappedJSObject' in Cu.evalInSandbox("this.document", sandbox),
+           "wrappers returned from the sandbox are Xrays");
+        ok(!("foo" in Cu.evalInSandbox("this.document", sandbox)),
+           "must not see expandos in wrappers returned from the sandbox");
+
+        ok('wrappedJSObject' in sandbox.document,
+           "values obtained from the sandbox are Xrays");
+        ok(!("foo" in sandbox.document),
+           "must not see expandos in wrappers obtained from the sandbox");
+
+      }
+
       function checkCrossOrigin(ifr) {
         var win = ifr.contentWindow;
         var sandbox =
           new Cu.Sandbox(win, { sandboxPrototype: win, wantXrays: true } );
 
         checkCrossOriginSandbox(sandbox);
-
-        ok(Cu.evalInSandbox("('wrappedJSObject' in this.document);", sandbox),
-           "wrappers inside eIS are XPCNativeWrappers");
-        ok(Cu.evalInSandbox("!('foo' in this.document);", sandbox),
-           "must not see expandos");
+        checkCrossOriginXrayedSandbox(sandbox);
 
         sandbox =
           new Cu.Sandbox(win, { sandboxPrototype: win } );
 
         checkCrossOriginSandbox(sandbox);
-
-        ok(Cu.evalInSandbox("('wrappedJSObject' in this.document);", sandbox),
-           "wrappers inside eIS are XPCNativeWrappers");
-        ok(Cu.evalInSandbox("!('foo' in this.document);", sandbox),
-           "must not see expandos");
+        checkCrossOriginXrayedSandbox(sandbox);
 
         sandbox =
           new Cu.Sandbox(win, { sandboxPrototype: win, wantXrays: false } );
 
         checkCrossOriginSandbox(sandbox);
 
         ok(Cu.evalInSandbox("('foo' in this.document);", sandbox),
            "can see expandos");
+        ok(("foo" in Cu.evalInSandbox("this.document", sandbox)),
+           "must see expandos in wrappers returned from the sandbox");
+
+        ok(("foo" in sandbox.document),
+           "must see expandos in wrappers obtained from the sandbox");
 
         testDone();
       }
 
       function checkSameOrigin(ifr) {
         var win = ifr.contentWindow;
         var sandbox =
           new Cu.Sandbox(win, { sandboxPrototype: win, wantXrays: true } );
--- a/js/src/xpconnect/wrappers/WrapperFactory.cpp
+++ b/js/src/xpconnect/wrappers/WrapperFactory.cpp
@@ -211,17 +211,17 @@ WrapperFactory::Rewrap(JSContext *cx, JS
         wrapper = &FilteringWrapper<JSCrossCompartmentWrapper,
                                     ExposedPropertiesOnly>::singleton;
     } else if (AccessCheck::isSameOrigin(origin, target)) {
         // Same origin we use a transparent wrapper, unless the compartment asks
         // for an Xray or the wrapper needs a SOW.
         if (AccessCheck::needsSystemOnlyWrapper(obj)) {
             wrapper = &FilteringWrapper<JSCrossCompartmentWrapper,
                                         OnlyIfSubjectIsSystem>::singleton;
-        } else if (targetdata && targetdata->preferXrays && IS_WN_WRAPPER(obj)) {
+        } else if (targetdata && targetdata->wantXrays && IS_WN_WRAPPER(obj)) {
             typedef XrayWrapper<JSCrossCompartmentWrapper, CrossCompartmentXray> Xray;
             wrapper = &Xray::singleton;
             xrayHolder = Xray::createHolder(cx, obj, parent);
             if (!xrayHolder)
                 return nsnull;
         } else {
             wrapper = &JSCrossCompartmentWrapper::singleton;
         }