Bug 927765 - createObjectIn for exportHelpers. r=bholley
authorGabor Krizsanits <gkrizsanits@mozilla.com>
Tue, 22 Oct 2013 14:24:07 +0200
changeset 151675 9916cc731d15ebfdaf2714c51c40a402294044f1
parent 151674 595c7dc7a02a0645322728e980dc539f05bacc69
child 151676 77b72ea510d0b8bb05f1d039db6d85c9d103d225
push id25504
push userphilringnalda@gmail.com
push dateWed, 23 Oct 2013 02:50:41 +0000
treeherdermozilla-central@21d97baadc05 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbholley
bugs927765
milestone27.0a1
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 927765 - createObjectIn for exportHelpers. r=bholley
js/xpconnect/src/Sandbox.cpp
js/xpconnect/src/XPCComponents.cpp
js/xpconnect/src/xpcprivate.h
js/xpconnect/tests/unit/test_exportFunction.js
--- a/js/xpconnect/src/Sandbox.cpp
+++ b/js/xpconnect/src/Sandbox.cpp
@@ -552,16 +552,44 @@ EvalInWindow(JSContext *cx, unsigned arg
     if (!CloneNonReflectors(cx, args.rval())) {
         args.rval().set(UndefinedValue());
         return false;
     }
 
     return true;
 }
 
+namespace xpc {
+static bool
+CreateObjectIn(JSContext *cx, unsigned argc, jsval *vp)
+{
+    CallArgs args = CallArgsFromVp(argc, vp);
+    if (args.length() < 1) {
+        JS_ReportError(cx, "Function requires at least 1 argument");
+        return false;
+    }
+
+    RootedObject optionsObj(cx);
+    bool calledWithOptions = args.length() > 1;
+    if (calledWithOptions) {
+        if (!args[1].isObject()) {
+            JS_ReportError(cx, "Expected the 2nd argument (options) to be an object");
+            return false;
+        }
+        optionsObj = &args[1].toObject();
+    }
+
+    CreateObjectInOptions options(cx, optionsObj);
+    if (calledWithOptions && !options.Parse())
+        return false;
+
+    return xpc::CreateObjectIn(cx, args[0], options, args.rval());
+}
+} /* namespace xpc */
+
 static bool
 sandbox_enumerate(JSContext *cx, HandleObject obj)
 {
     return JS_EnumerateStandardClasses(cx, obj);
 }
 
 static bool
 sandbox_resolve(JSContext *cx, HandleObject obj, HandleId id)
@@ -1054,17 +1082,18 @@ xpc::CreateSandboxObject(JSContext *cx, 
         if (!XPCNativeWrapper::AttachNewConstructorObject(cx, sandbox))
             return NS_ERROR_XPC_UNEXPECTED;
 
         if (!JS_DefineFunctions(cx, sandbox, SandboxFunctions))
             return NS_ERROR_XPC_UNEXPECTED;
 
         if (options.wantExportHelpers &&
             (!JS_DefineFunction(cx, sandbox, "exportFunction", ExportFunction, 3, 0) ||
-             !JS_DefineFunction(cx, sandbox, "evalInWindow", EvalInWindow, 2, 0)))
+             !JS_DefineFunction(cx, sandbox, "evalInWindow", EvalInWindow, 2, 0) ||
+             !JS_DefineFunction(cx, sandbox, "createObjectIn", CreateObjectIn, 2, 0)))
             return NS_ERROR_XPC_UNEXPECTED;
 
         if (!options.globalProperties.Define(cx, sandbox))
             return NS_ERROR_XPC_UNEXPECTED;
     }
 
     if (vp) {
         // We have this crazy behavior where wantXrays=false also implies that the
--- a/js/xpconnect/src/XPCComponents.cpp
+++ b/js/xpconnect/src/XPCComponents.cpp
@@ -3007,17 +3007,17 @@ nsXPCComponents_Utils::GetGlobalForObjec
     if (JSObjectOp outerize = js::GetObjectClass(obj)->ext.outerObject)
       *retval = OBJECT_TO_JSVAL(outerize(cx, obj));
 
     return NS_OK;
 }
 
 /* jsval createObjectIn(in jsval vobj); */
 bool
-xpc::CreateObjectIn(JSContext *cx, HandleValue vobj, CreateObjectOptions &options,
+xpc::CreateObjectIn(JSContext *cx, HandleValue vobj, CreateObjectInOptions &options,
                     MutableHandleValue rval)
 {
     if (!vobj.isObject()) {
         JS_ReportError(cx, "Expected an object as the target scope");
         return false;
     }
 
     RootedObject scope(cx, js::CheckedUnwrap(&vobj.toObject()));
@@ -3045,17 +3045,17 @@ xpc::CreateObjectIn(JSContext *cx, Handl
     rval.setObject(*obj);
     return true;
 }
 
 /* jsval createObjectIn(in jsval vobj); */
 NS_IMETHODIMP
 nsXPCComponents_Utils::CreateObjectIn(const Value &vobj, JSContext *cx, Value *rval)
 {
-    CreateObjectOptions options;
+    CreateObjectInOptions options;
     RootedValue rvobj(cx, vobj);
     RootedValue res(cx);
     if (!xpc::CreateObjectIn(cx, rvobj, options, &res))
         return NS_ERROR_FAILURE;
 
     *rval = res;
     return NS_OK;
 }
--- a/js/xpconnect/src/xpcprivate.h
+++ b/js/xpconnect/src/xpcprivate.h
@@ -3660,20 +3660,20 @@ public:
     JS::RootedObject sameZoneAs;
     GlobalProperties globalProperties;
     JS::RootedValue metadata;
 
 protected:
     bool ParseGlobalProperties();
 };
 
-class MOZ_STACK_CLASS CreateObjectOptions : public OptionsBase {
+class MOZ_STACK_CLASS CreateObjectInOptions : public OptionsBase {
 public:
-    CreateObjectOptions(JSContext *cx = xpc_GetSafeJSContext(),
-                        JS::HandleObject options = JS::NullPtr())
+    CreateObjectInOptions(JSContext *cx = xpc_GetSafeJSContext(),
+                          JS::HandleObject options = JS::NullPtr())
         : OptionsBase(cx, options)
         , defineAs(cx, JSID_VOID)
     { }
 
     virtual bool Parse() { return ParseId("defineAs", &defineAs); };
 
     JS::RootedId defineAs;
 };
@@ -3716,17 +3716,17 @@ nsresult
 GetSandboxMetadata(JSContext *cx, JS::HandleObject sandboxArg,
                    JS::MutableHandleValue rval);
 
 nsresult
 SetSandboxMetadata(JSContext *cx, JS::HandleObject sandboxArg,
                    JS::HandleValue metadata);
 
 bool
-CreateObjectIn(JSContext *cx, JS::HandleValue vobj, CreateObjectOptions &options,
+CreateObjectIn(JSContext *cx, JS::HandleValue vobj, CreateObjectInOptions &options,
                JS::MutableHandleValue rval);
 
 } /* namespace xpc */
 
 
 /***************************************************************************/
 // Inlined utilities.
 
--- a/js/xpconnect/tests/unit/test_exportFunction.js
+++ b/js/xpconnect/tests/unit/test_exportFunction.js
@@ -12,17 +12,17 @@ function run_test() {
   epsb.do_check_neq = do_check_neq;
 
   // Exporting should work if prinicipal of the source sandbox
   // subsumes the principal of the target sandbox.
   Cu.evalInSandbox("(" + function() {
     Object.prototype.protoProp = "common";
     var wasCalled = false;
     var _this = this;
-    var funToExport = function(a, obj, native, mixed) {
+    this.funToExport = function(a, obj, native, mixed) {
       do_check_eq(a, 42);
       do_check_neq(obj, subsb.tobecloned);
       do_check_eq(obj.cloned, "cloned");
       do_check_eq(obj.protoProp, "common");
       do_check_eq(native, subsb.native);
       do_check_eq(_this, this);
       do_check_eq(mixed.xrayed, subsb.xrayed);
       do_check_eq(mixed.xrayed2, subsb.xrayed2);
@@ -65,9 +65,24 @@ function run_test() {
   Cu.evalInSandbox("(" + function() {
     try{
       exportFunction(function(){}, this.xorigsb, "denied");
       do_check_true(false);
     } catch (e) {
       do_check_true(e.toString().indexOf('Permission denied') > -1);
     }
   }.toSource() + ")()", epsb);
+
+  // Let's create an object in the target scope and add privileged
+  // function to it as a property.
+  Cu.evalInSandbox("(" + function() {
+    var newContentObject = createObjectIn(subsb, {defineAs:"importedObject"});
+    exportFunction(funToExport, newContentObject, "privMethod");
+  }.toSource() + ")()", epsb);
+
+  Cu.evalInSandbox("(" + function () {
+    importedObject.privMethod(42, tobecloned, native, mixed);
+  }.toSource() + ")()", subsb);
+
+  Cu.evalInSandbox("(" + function() {
+    checkIfCalled();
+  }.toSource() + ")()", epsb);
 }