Fix for bug 778152 (Content window does not have an XMLHttpRequest property when accessed via an Xray wrapper in a subscript) - followup to fix problem pointed out by reviewer. r=bz.
authorPeter Van der Beken <peterv@propagandism.org>
Mon, 29 Oct 2012 21:55:13 +0100
changeset 111832 acc131324855c36a695d5fa94f4adca66544eed9
parent 111831 42b38e4e9068ac3d0af266f83ccdf0be97e52fd3
child 111833 387a5f8b5e4f331b1f92921965acaf35cc0bda61
push id93
push usernmatsakis@mozilla.com
push dateWed, 31 Oct 2012 21:26:57 +0000
reviewersbz
bugs778152
milestone19.0a1
Fix for bug 778152 (Content window does not have an XMLHttpRequest property when accessed via an Xray wrapper in a subscript) - followup to fix problem pointed out by reviewer. r=bz.
dom/bindings/BindingUtils.cpp
dom/tests/mochitest/chrome/test_sandbox_bindings.xul
--- a/dom/bindings/BindingUtils.cpp
+++ b/dom/bindings/BindingUtils.cpp
@@ -682,30 +682,30 @@ XrayResolveProperty(JSContext* cx, JSObj
     }
   }
 
   return true;
 }
 
 static bool
 ResolvePrototypeOrConstructor(JSContext* cx, JSObject* wrapper, JSObject* obj,
-                              size_t protoAndIfaceArrayIndex,
+                              size_t protoAndIfaceArrayIndex, unsigned attrs,
                               JSPropertyDescriptor* desc)
 {
   JSObject* global = js::GetGlobalForObjectCrossCompartment(obj);
   {
     JSAutoCompartment ac(cx, global);
     JSObject** protoAndIfaceArray = GetProtoAndIfaceArray(global);
     JSObject* protoOrIface = protoAndIfaceArray[protoAndIfaceArrayIndex];
     if (!protoOrIface) {
       return false;
     }
     desc->obj = wrapper;
     desc->shortid = 0;
-    desc->attrs = JSPROP_PERMANENT | JSPROP_READONLY;
+    desc->attrs = attrs;
     desc->getter = JS_PropertyStub;
     desc->setter = JS_StrictPropertyStub;
     desc->value = JS::ObjectValue(*protoOrIface);
   }
   return JS_WrapPropertyDescriptor(cx, desc);
 }
 
 bool
@@ -713,24 +713,25 @@ XrayResolveNativeProperty(JSContext* cx,
                           const NativePropertyHooks* nativePropertyHooks,
                           DOMObjectType type, JSObject* obj, jsid id,
                           JSPropertyDescriptor* desc)
 {
   if (type == eInterface && IdEquals(id, "prototype")) {
     return nativePropertyHooks->mPrototypeID == prototypes::id::_ID_Count ||
            ResolvePrototypeOrConstructor(cx, wrapper, obj,
                                          nativePropertyHooks->mPrototypeID,
+                                         JSPROP_PERMANENT | JSPROP_READONLY,
                                          desc);
   }
 
   if (type == eInterfacePrototype && IdEquals(id, "constructor")) {
     return nativePropertyHooks->mConstructorID == constructors::id::_ID_Count ||
            ResolvePrototypeOrConstructor(cx, wrapper, obj,
                                          nativePropertyHooks->mConstructorID,
-                                         desc);
+                                         0, desc);
   }
 
   const NativePropertiesHolder& nativeProperties =
     nativePropertyHooks->mNativeProperties;
 
   if (nativeProperties.regular &&
       !XrayResolveProperty(cx, wrapper, id, desc, type,
                            nativeProperties.regular)) {
--- a/dom/tests/mochitest/chrome/test_sandbox_bindings.xul
+++ b/dom/tests/mochitest/chrome/test_sandbox_bindings.xul
@@ -46,16 +46,40 @@ https://bugzilla.mozilla.org/show_bug.cg
         ok(xhr, "'XMLHttpRequest.prototype' in a sandbox should return the XMLHttpRequest interface prototype object");
         ok(isXrayWrapper(xhr), "Getting an interface prototype object on an Xray wrapper should return an Xray wrapper");
         ok(isXrayWrapper(xhr.constructor), "Getting the constructor property on an Xray wrapper of an interface prototype object should return an Xray wrapper");
       } catch (e) {
         ok(false, "'XMLHttpRequest.prototype' shouldn't throw in a sandbox");
       }
       try {
         var xhr = Components.utils.evalInSandbox("XMLHttpRequest", sandbox);
+        xhr.prototype = false;
+      } catch (e) {
+        ok(true, "'XMLHttpRequest.prototype' should be readonly");
+      }
+      try {
+        var xhr = Components.utils.evalInSandbox("XMLHttpRequest", sandbox);
+        delete xhr.prototype;
+      } catch (e) {
+        ok(true, "'XMLHttpRequest.prototype' should be permanent");
+      }
+      try {
+        var xhr = Components.utils.evalInSandbox("XMLHttpRequest.prototype", sandbox);
+        xhr.constructor = "ok";
+      } catch (e) {
+        is(xhr.constructor, "ok", "'XMLHttpRequest.prototype.constructor' should be writeable");
+      }
+      try {
+        var xhr = Components.utils.evalInSandbox("XMLHttpRequest.prototype", sandbox);
+        delete xhr.constructor;
+      } catch (e) {
+        is(xhr.constructor, undefined, "'XMLHttpRequest.prototype.constructor' should be permanent");
+      }
+      try {
+        var xhr = Components.utils.evalInSandbox("XMLHttpRequest", sandbox);
         is(xhr, "[object XrayWrapper " + XMLHttpRequest + "]", "'XMLHttpRequest' in a sandbox should return the XMLHttpRequest interface object");
         ok(isXrayWrapper(xhr.prototype), "Getting the prototype property on an Xray wrapper of an interface object should return an Xray wrapper");
       } catch (e) {
         ok(false, "'XMLHttpRequest' shouldn't throw in a sandbox");
       }
       try {
         var xhr = Components.utils.evalInSandbox("XMLHttpRequest()", sandbox);
         is("" + xhr, "" + XMLHttpRequest(), "'XMLHttpRequest()' in a sandbox should create an XMLHttpRequest object");