diff --git a/dom/base/nsDOMWindowUtils.cpp b/dom/base/nsDOMWindowUtils.cpp index e10f0a5abb28..193982b395ad 100644 --- a/dom/base/nsDOMWindowUtils.cpp +++ b/dom/base/nsDOMWindowUtils.cpp @@ -866,11 +866,7 @@ nsDOMWindowUtils::GetCOWForObject() || !hasCap) return NS_ERROR_DOM_SECURITY_ERR; - nsresult rv = NS_OK; - nsCOMPtr xpc = do_GetService("@mozilla.org/js/xpc/XPConnect;1", - &rv); - if (NS_FAILED(rv)) - return NS_ERROR_FAILURE; + nsCOMPtr xpc = nsContentUtils::XPConnect(); // get the xpconnect native call context nsAXPCNativeCallContext *cc = nsnull; @@ -880,7 +876,7 @@ nsDOMWindowUtils::GetCOWForObject() // Get JSContext of current call JSContext* cx; - rv = cc->GetJSContext(&cx); + nsresult rv = cc->GetJSContext(&cx); if(NS_FAILED(rv) || !cx) return NS_ERROR_FAILURE; @@ -949,3 +945,44 @@ nsDOMWindowUtils::DispatchDOMEventViaPresShell(nsIDOMNode* aTarget, *aRetVal = (status != nsEventStatus_eConsumeNoDefault); return NS_OK; } + +NS_IMETHODIMP +nsDOMWindowUtils::GetClassName(char **aName) +{ + if (!nsContentUtils::IsCallerTrustedForRead()) { + return NS_ERROR_DOM_SECURITY_ERR; + } + + // get the xpconnect native call context + nsAXPCNativeCallContext *cc = nsnull; + nsContentUtils::XPConnect()->GetCurrentNativeCallContext(&cc); + if(!cc) + return NS_ERROR_FAILURE; + + // Get JSContext of current call + JSContext* cx; + nsresult rv = cc->GetJSContext(&cx); + if(NS_FAILED(rv) || !cx) + return NS_ERROR_FAILURE; + + // get argc and argv and verify arg count + PRUint32 argc; + rv = cc->GetArgc(&argc); + if(NS_FAILED(rv)) + return NS_ERROR_FAILURE; + + if(argc < 1) + return NS_ERROR_XPC_NOT_ENOUGH_ARGS; + + jsval* argv; + rv = cc->GetArgvPtr(&argv); + if(NS_FAILED(rv) || !argv) + return NS_ERROR_FAILURE; + + // Our argument must be a non-null object. + if(JSVAL_IS_PRIMITIVE(argv[0])) + return NS_ERROR_XPC_BAD_CONVERT_JS; + + *aName = NS_strdup(JS_GET_CLASS(cx, JSVAL_TO_OBJECT(argv[0]))->name); + return *aName ? NS_OK : NS_ERROR_OUT_OF_MEMORY; +} diff --git a/dom/interfaces/base/nsIDOMWindowUtils.idl b/dom/interfaces/base/nsIDOMWindowUtils.idl index 7a44bc212e68..5efab995fdda 100644 --- a/dom/interfaces/base/nsIDOMWindowUtils.idl +++ b/dom/interfaces/base/nsIDOMWindowUtils.idl @@ -50,7 +50,7 @@ interface nsIDOMElement; interface nsIDOMHTMLCanvasElement; interface nsIDOMEvent; -[scriptable, uuid(4775e623-d596-4364-8637-0968a5ce5e3d)] +[scriptable, uuid(0e13d9a6-bcd1-4d61-9986-c32f78f99d1a)] interface nsIDOMWindowUtils : nsISupports { /** @@ -421,4 +421,10 @@ interface nsIDOMWindowUtils : nsISupports { boolean dispatchDOMEventViaPresShell(in nsIDOMNode aTarget, in nsIDOMEvent aEvent, in boolean aTrusted); + + /** + * Returns the real classname (possibly of the mostly-transparent security + * wrapper) of aObj. + */ + string getClassName(/*in JSObjectPtr aObj*/); }; diff --git a/js/src/xpconnect/src/XPCNativeWrapper.cpp b/js/src/xpconnect/src/XPCNativeWrapper.cpp index 718958dbdf9c..8f1cbe238dd9 100644 --- a/js/src/xpconnect/src/XPCNativeWrapper.cpp +++ b/js/src/xpconnect/src/XPCNativeWrapper.cpp @@ -561,6 +561,31 @@ XPC_NW_FunctionWrapper(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, return RewrapIfDeepWrapper(cx, obj, v, rval); } +static JSBool +GetwrappedJSObject(JSContext *cx, JSObject *obj, jsval *vp) +{ + // If we're wrapping an untrusted content wrapper, then we should + // return a safe wrapper for the underlying native object. Otherwise, + // such a wrapper would be superfluous. + + nsIScriptSecurityManager *ssm = GetSecurityManager(); + nsCOMPtr prin; + nsresult rv = ssm->GetObjectPrincipal(cx, obj, getter_AddRefs(prin)); + if (NS_FAILED(rv)) { + return ThrowException(rv, cx); + } + + jsval v = OBJECT_TO_JSVAL(obj); + + PRBool isSystem; + if (NS_SUCCEEDED(ssm->IsSystemPrincipal(prin, &isSystem)) && isSystem) { + *vp = v; + return JS_TRUE; + } + + return XPCSafeJSObjectWrapper::WrapObject(cx, JS_GetScopeChain(cx), v, vp); +} + static JSBool XPC_NW_GetOrSetProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp, JSBool aIsSet) @@ -611,27 +636,7 @@ XPC_NW_GetOrSetProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp, if (!aIsSet && id == GetRTStringByIndex(cx, XPCJSRuntime::IDX_WRAPPED_JSOBJECT)) { - // If we're wrapping an untrusted content wrapper, then we should - // return a safe wrapper for the underlying native object. Otherwise, - // such a wrapper would be superfluous. - - jsval nativeVal = OBJECT_TO_JSVAL(nativeObj); - - nsIScriptSecurityManager *ssm = GetSecurityManager(); - nsCOMPtr prin; - nsresult rv = ssm->GetObjectPrincipal(cx, nativeObj, - getter_AddRefs(prin)); - if (NS_FAILED(rv)) { - return ThrowException(rv, cx); - } - - PRBool isSystem; - if (NS_SUCCEEDED(ssm->IsSystemPrincipal(prin, &isSystem)) && isSystem) { - *vp = nativeVal; - return JS_TRUE; - } - - return XPCSafeJSObjectWrapper::WrapObject(cx, nsnull, nativeVal, vp); + return GetwrappedJSObject(cx, nativeObj, vp); } return GetOrSetNativeProperty(cx, obj, wrappedNative, id, vp, aIsSet, @@ -1158,6 +1163,31 @@ XPC_NW_toString(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, return NativeToString(cx, wrappedNative, argc, argv, rval, JS_TRUE); } +static JSBool +UnwrapNW(JSContext *cx, uintN argc, jsval *vp) +{ + if (argc != 1) { + return ThrowException(NS_ERROR_XPC_NOT_ENOUGH_ARGS, cx); + } + + jsval v = JS_ARGV(cx, vp)[0]; + if (JSVAL_IS_PRIMITIVE(v)) { + return ThrowException(NS_ERROR_INVALID_ARG, cx); + } + + if (!IsNativeWrapper(JSVAL_TO_OBJECT(v))) { + JS_SET_RVAL(cx, vp, v); + return JS_TRUE; + } + + return GetwrappedJSObject(cx, JSVAL_TO_OBJECT(v), vp); +} + +static JSFunctionSpec static_functions[] = { + JS_FN("unwrap", UnwrapNW, 1, 0), + JS_FS_END +}; + // static PRBool XPCNativeWrapper::AttachNewConstructorObject(XPCCallContext &ccx, @@ -1166,7 +1196,7 @@ XPCNativeWrapper::AttachNewConstructorObject(XPCCallContext &ccx, JSObject *class_obj = ::JS_InitClass(ccx, aGlobalObject, nsnull, &internal::NWClass.base, XPCNativeWrapperCtor, 0, nsnull, nsnull, - nsnull, nsnull); + nsnull, static_functions); if (!class_obj) { NS_WARNING("can't initialize the XPCNativeWrapper class"); return PR_FALSE; diff --git a/js/src/xpconnect/tests/chrome/Makefile.in b/js/src/xpconnect/tests/chrome/Makefile.in index 4e8d2e5f6b6b..5fe0c107635f 100644 --- a/js/src/xpconnect/tests/chrome/Makefile.in +++ b/js/src/xpconnect/tests/chrome/Makefile.in @@ -47,6 +47,7 @@ _CHROME_FILES = \ test_bug500931.xul \ bug503926.xul \ test_bug503926.xul \ + test_bug533596.xul \ $(NULL) libs:: $(_CHROME_FILES) diff --git a/js/src/xpconnect/tests/chrome/test_bug533596.xul b/js/src/xpconnect/tests/chrome/test_bug533596.xul new file mode 100644 index 000000000000..0cfe55221d70 --- /dev/null +++ b/js/src/xpconnect/tests/chrome/test_bug533596.xul @@ -0,0 +1,56 @@ + + + + + + + + + + + Mozilla Bug 533596 + + + + + +