From a220e3d04bc6c84c93a37b7fad42c123e6e24d28 Mon Sep 17 00:00:00 2001 From: Gabor Krizsanits Date: Tue, 22 Oct 2013 14:23:41 +0200 Subject: [PATCH] Bug 927765 - Options for createObjectIn. r=bholley --- js/xpconnect/src/Sandbox.cpp | 31 ++++++++++++++++---- js/xpconnect/src/XPCComponents.cpp | 45 ++++++++++++++++++++++-------- js/xpconnect/src/xpcprivate.h | 20 ++++++++++++- 3 files changed, 78 insertions(+), 18 deletions(-) diff --git a/js/xpconnect/src/Sandbox.cpp b/js/xpconnect/src/Sandbox.cpp index fc667ce3accf..98c62736bcf8 100644 --- a/js/xpconnect/src/Sandbox.cpp +++ b/js/xpconnect/src/Sandbox.cpp @@ -1253,13 +1253,16 @@ GetExpandedPrincipal(JSContext *cx, HandleObject arrayObj, nsIExpandedPrincipal * Helper that tries to get a property form the options object. */ bool -OptionsBase::ParseValue(const char *name, MutableHandleValue prop, bool *found) +OptionsBase::ParseValue(const char *name, MutableHandleValue prop, bool *aFound) { - MOZ_ASSERT(found); - bool ok = JS_HasProperty(mCx, mObject, name, found); + bool found; + bool ok = JS_HasProperty(mCx, mObject, name, &found); NS_ENSURE_TRUE(ok, false); - if (!*found) + if (aFound) + *aFound = found; + + if (!found) return true; return JS_GetProperty(mCx, mObject, name, prop); @@ -1336,6 +1339,23 @@ OptionsBase::ParseString(const char *name, nsCString &prop) return true; } +/* + * Helper that tries to get jsid property form the options object. + */ +bool +OptionsBase::ParseId(const char *name, MutableHandleId prop) +{ + RootedValue value(mCx); + bool found; + bool ok = ParseValue(name, &value, &found); + NS_ENSURE_TRUE(ok, false); + + if (!found) + return true; + + return JS_ValueToId(mCx, value, prop.address()); +} + /* * Helper that tries to get a list of DOM constructors and other helpers from the options object. */ @@ -1369,7 +1389,6 @@ SandboxOptions::ParseGlobalProperties() bool SandboxOptions::Parse() { - bool found; return ParseObject("sandboxPrototype", &proto) && ParseBoolean("wantXrays", &wantXrays) && ParseBoolean("wantComponents", &wantComponents) && @@ -1377,7 +1396,7 @@ SandboxOptions::Parse() ParseString("sandboxName", sandboxName) && ParseObject("sameZoneAs", &sameZoneAs) && ParseGlobalProperties() && - ParseValue("metadata", &metadata, &found); + ParseValue("metadata", &metadata); } static nsresult diff --git a/js/xpconnect/src/XPCComponents.cpp b/js/xpconnect/src/XPCComponents.cpp index ec1acae390bb..c374e91ea469 100644 --- a/js/xpconnect/src/XPCComponents.cpp +++ b/js/xpconnect/src/XPCComponents.cpp @@ -3011,29 +3011,52 @@ nsXPCComponents_Utils::GetGlobalForObject(const Value& object, } /* jsval createObjectIn(in jsval vobj); */ -NS_IMETHODIMP -nsXPCComponents_Utils::CreateObjectIn(const Value &vobj, JSContext *cx, Value *rval) +bool +xpc::CreateObjectIn(JSContext *cx, HandleValue vobj, CreateObjectOptions &options, + MutableHandleValue rval) { - if (!cx) - return NS_ERROR_FAILURE; + if (!vobj.isObject()) { + JS_ReportError(cx, "Expected an object as the target scope"); + return false; + } - // first argument must be an object - if (vobj.isPrimitive()) - return NS_ERROR_XPC_BAD_CONVERT_JS; - - RootedObject scope(cx, js::UncheckedUnwrap(&vobj.toObject())); + RootedObject scope(cx, js::CheckedUnwrap(&vobj.toObject())); + if (!scope) { + JS_ReportError(cx, "Permission denied to create object in the target scope"); + return false; + } RootedObject obj(cx); { JSAutoCompartment ac(cx, scope); obj = JS_NewObject(cx, nullptr, nullptr, scope); if (!obj) - return NS_ERROR_FAILURE; + return false; + + if (!JSID_IS_VOID(options.defineAs) && + !JS_DefinePropertyById(cx, scope, options.defineAs, ObjectValue(*obj), + JS_PropertyStub, JS_StrictPropertyStub, + JSPROP_ENUMERATE)) + return false; } if (!JS_WrapObject(cx, &obj)) + return false; + + rval.setObject(*obj); + return true; +} + +/* jsval createObjectIn(in jsval vobj); */ +NS_IMETHODIMP +nsXPCComponents_Utils::CreateObjectIn(const Value &vobj, JSContext *cx, Value *rval) +{ + CreateObjectOptions options; + RootedValue rvobj(cx, vobj); + RootedValue res(cx); + if (!xpc::CreateObjectIn(cx, rvobj, options, &res)) return NS_ERROR_FAILURE; - *rval = ObjectValue(*obj); + *rval = res; return NS_OK; } diff --git a/js/xpconnect/src/xpcprivate.h b/js/xpconnect/src/xpcprivate.h index 25a4c95124be..35f66815655c 100644 --- a/js/xpconnect/src/xpcprivate.h +++ b/js/xpconnect/src/xpcprivate.h @@ -3627,10 +3627,11 @@ public: virtual bool Parse() = 0; protected: - bool ParseValue(const char *name, JS::MutableHandleValue prop, bool *found); + bool ParseValue(const char *name, JS::MutableHandleValue prop, bool *found = nullptr); bool ParseBoolean(const char *name, bool *prop); bool ParseObject(const char *name, JS::MutableHandleObject prop); bool ParseString(const char *name, nsCString &prop); + bool ParseId(const char* name, JS::MutableHandleId id); JSContext *mCx; JS::RootedObject mObject; @@ -3664,6 +3665,19 @@ protected: bool ParseGlobalProperties(); }; +class MOZ_STACK_CLASS CreateObjectOptions : public OptionsBase { +public: + CreateObjectOptions(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; +}; + JSObject * CreateGlobalObject(JSContext *cx, const JSClass *clasp, nsIPrincipal *principal, JS::CompartmentOptions& aOptions); @@ -3706,6 +3720,10 @@ nsresult SetSandboxMetadata(JSContext *cx, JS::HandleObject sandboxArg, JS::HandleValue metadata); +bool +CreateObjectIn(JSContext *cx, JS::HandleValue vobj, CreateObjectOptions &options, + JS::MutableHandleValue rval); + } /* namespace xpc */