Bug 533596 - Implement XPCNativeWrapper.unwrap. r=peterv sr=jst

This commit is contained in:
Blake Kaplan 2009-12-14 13:58:50 -08:00
Родитель eee412ce5e
Коммит 5e6b899dc8
5 изменённых файлов: 159 добавлений и 29 удалений

Просмотреть файл

@ -866,11 +866,7 @@ nsDOMWindowUtils::GetCOWForObject()
|| !hasCap)
return NS_ERROR_DOM_SECURITY_ERR;
nsresult rv = NS_OK;
nsCOMPtr<nsIXPConnect> xpc = do_GetService("@mozilla.org/js/xpc/XPConnect;1",
&rv);
if (NS_FAILED(rv))
return NS_ERROR_FAILURE;
nsCOMPtr<nsIXPConnect> 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;
}

Просмотреть файл

@ -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*/);
};

Просмотреть файл

@ -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<nsIPrincipal> 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<nsIPrincipal> 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;

Просмотреть файл

@ -47,6 +47,7 @@ _CHROME_FILES = \
test_bug500931.xul \
bug503926.xul \
test_bug503926.xul \
test_bug533596.xul \
$(NULL)
libs:: $(_CHROME_FILES)

Просмотреть файл

@ -0,0 +1,56 @@
<?xml version="1.0"?>
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
type="text/css"?>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=500931
-->
<window title="Mozilla Bug 500931"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<script type="application/javascript"
src="chrome://mochikit/content/MochiKit/packed.js"></script>
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<!-- test results are displayed in the html:body -->
<body xmlns="http://www.w3.org/1999/xhtml">
<a href="https://bugzilla.mozilla.org/show_bug.cgi?id=533596"
target="_blank">Mozilla Bug 533596</a>
</body>
<!-- test code goes here -->
<script type="application/javascript"><![CDATA[
/** Test for Bug 533596 **/
function go() {
try { XPCNativeWrapper.unwrap(); } catch (e) {}
try { XPCNativeWrapper.unwrap(0); } catch (e) {}
try { XPCNativeWrapper.unwrap(null); } catch (e) {}
var o = {};
is(o, XPCNativeWrapper.unwrap(o), "unwrap on a random object returns it");
var win = $('ifr').contentWindow;
var utils = window.getInterface(Components.interfaces.nsIDOMWindowUtils);
is(utils.getClassName(win), "XPCNativeWrapper", "win is an XPCNW");
is(utils.getClassName(XPCNativeWrapper.unwrap(win)), "XPCSafeJSObjectWrapper",
"unwrap on an NW returns the same object");
is(utils.getClassName(XPCNativeWrapper.unwrap(new XPCNativeWrapper(win))), "XPCSafeJSObjectWrapper",
"unwrap on an explicit NW works too");
ok(utils.getClassName(window) !== "XPCNativeWrapper", "window is not a native wrapper");
ok(utils.getClassName(XPCNativeWrapper.unwrap(new XPCNativeWrapper(window))) !== "XPCSafeJSObjectWrapper",
"unwrapping a chrome object returns the object itself");
SimpleTest.finish();
}
SimpleTest.waitForExplicitFinish();
]]></script>
<iframe type="content"
src="http://example.org/tests/js/src/xpconnect/tests/mochitest/bug500931_helper.html"
onload="go()"
id="ifr">
</iframe>
</window>