mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 634156 - Come up with a way of creating an API in content that exposes real content objects without using a sandbox. r/sr=jst/mossop/gal
--HG-- extra : rebase_source : c3ca469ff33d099b51e140d0a274113884507a03
This commit is contained in:
parent
f823587beb
commit
9f1a75137b
@ -95,24 +95,27 @@ ConsoleAPI.prototype = {
|
|||||||
|
|
||||||
// We need to return an actual content object here, instead of a wrapped
|
// We need to return an actual content object here, instead of a wrapped
|
||||||
// chrome object. This allows things like console.log.bind() to work.
|
// chrome object. This allows things like console.log.bind() to work.
|
||||||
let sandbox = Cu.Sandbox(aWindow);
|
let contentObj = Cu.createObjectIn(aWindow);
|
||||||
let contentObject = Cu.evalInSandbox(
|
function genPropDesc(fun) {
|
||||||
"(function(x) {\
|
return { enumerable: true, configurable: true, writable: true,
|
||||||
var bind = Function.bind;\
|
value: chromeObject[fun].bind(chromeObject) };
|
||||||
var obj = {\
|
}
|
||||||
log: bind.call(x.log, x),\
|
const properties = {
|
||||||
info: bind.call(x.info, x),\
|
log: genPropDesc('log'),
|
||||||
warn: bind.call(x.warn, x),\
|
info: genPropDesc('info'),
|
||||||
error: bind.call(x.error, x),\
|
warn: genPropDesc('warn'),
|
||||||
debug: bind.call(x.debug, x),\
|
error: genPropDesc('error'),
|
||||||
trace: bind.call(x.trace, x),\
|
debug: genPropDesc('debug'),
|
||||||
__noSuchMethod__: function() {}\
|
trace: genPropDesc('trace'),
|
||||||
};\
|
__noSuchMethod__: { enumerable: true, configurable: true, writable: true,
|
||||||
Object.defineProperty(obj, '__mozillaConsole__', { value: true });\
|
value: function() {} },
|
||||||
return obj;\
|
__mozillaConsole__: { value: true }
|
||||||
})", sandbox)(chromeObject);
|
};
|
||||||
|
|
||||||
return contentObject;
|
Object.defineProperties(contentObj, properties);
|
||||||
|
Cu.makeObjectPropsNormal(contentObj);
|
||||||
|
|
||||||
|
return contentObj;
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -44,6 +44,10 @@
|
|||||||
#include "nsIComponentManager.idl"
|
#include "nsIComponentManager.idl"
|
||||||
#include "nsIScriptableInterfaces.idl"
|
#include "nsIScriptableInterfaces.idl"
|
||||||
|
|
||||||
|
%{C++
|
||||||
|
#include "jspubtd.h"
|
||||||
|
%}
|
||||||
|
|
||||||
interface xpcIJSWeakReference;
|
interface xpcIJSWeakReference;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -123,7 +127,7 @@ interface nsIXPCComponents_utils_Sandbox : nsISupports
|
|||||||
/**
|
/**
|
||||||
* interface of Components.utils
|
* interface of Components.utils
|
||||||
*/
|
*/
|
||||||
[scriptable, uuid(5f0acf45-135a-48d1-976c-082ce3b24ead)]
|
[scriptable, uuid(45857850-a08e-4fe9-a582-77fe03e3676f)]
|
||||||
interface nsIXPCComponents_Utils : nsISupports
|
interface nsIXPCComponents_Utils : nsISupports
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -237,6 +241,23 @@ interface nsIXPCComponents_Utils : nsISupports
|
|||||||
* @return the corresponding global.
|
* @return the corresponding global.
|
||||||
*/
|
*/
|
||||||
void /* JSObject */ getGlobalForObject(/* in JSObject obj */);
|
void /* JSObject */ getGlobalForObject(/* in JSObject obj */);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* To be called from JS only.
|
||||||
|
*
|
||||||
|
* Returns an object created in |vobj|'s compartment.
|
||||||
|
*/
|
||||||
|
[implicit_jscontext]
|
||||||
|
jsval createObjectIn(in jsval vobj);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* To be called from JS only.
|
||||||
|
*
|
||||||
|
* Ensures that all functions come from vobj's scope (and aren't cross
|
||||||
|
* compartment wrappers).
|
||||||
|
*/
|
||||||
|
[implicit_jscontext]
|
||||||
|
void makeObjectPropsNormal(in jsval vobj);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -3831,6 +3831,106 @@ nsXPCComponents_Utils::GetGlobalForObject()
|
|||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* jsval createObjectIn(in jsval vobj); */
|
||||||
|
NS_IMETHODIMP
|
||||||
|
nsXPCComponents_Utils::CreateObjectIn(const jsval &vobj, JSContext *cx, jsval *rval)
|
||||||
|
{
|
||||||
|
if (!cx)
|
||||||
|
return NS_ERROR_FAILURE;
|
||||||
|
|
||||||
|
// first argument must be an object
|
||||||
|
if(JSVAL_IS_PRIMITIVE(vobj))
|
||||||
|
return NS_ERROR_XPC_BAD_CONVERT_JS;
|
||||||
|
|
||||||
|
JSObject *scope = JSVAL_TO_OBJECT(vobj)->unwrap();
|
||||||
|
JSObject *obj;
|
||||||
|
{
|
||||||
|
JSAutoEnterCompartment ac;
|
||||||
|
if(!ac.enter(cx, scope))
|
||||||
|
return NS_ERROR_FAILURE;
|
||||||
|
|
||||||
|
obj = JS_NewObject(cx, nsnull, nsnull, scope);
|
||||||
|
if (!obj)
|
||||||
|
return NS_ERROR_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!JS_WrapObject(cx, &obj))
|
||||||
|
return NS_ERROR_FAILURE;
|
||||||
|
*rval = OBJECT_TO_JSVAL(obj);
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
JSBool
|
||||||
|
FunctionWrapper(JSContext *cx, uintN argc, jsval *vp)
|
||||||
|
{
|
||||||
|
jsval v;
|
||||||
|
if (!JS_GetReservedSlot(cx, JSVAL_TO_OBJECT(JS_CALLEE(cx, vp)), 0, &v))
|
||||||
|
return JS_FALSE;
|
||||||
|
NS_ASSERTION(JSVAL_IS_OBJECT(v), "weird function");
|
||||||
|
|
||||||
|
return JS_CallFunctionValue(cx, JS_THIS_OBJECT(cx, vp), v,
|
||||||
|
argc, JS_ARGV(cx, vp), vp);
|
||||||
|
}
|
||||||
|
|
||||||
|
JSBool
|
||||||
|
WrapCallable(JSContext *cx, JSObject *obj, jsid id, JSObject *propobj, jsval *vp)
|
||||||
|
{
|
||||||
|
JSFunction *fun = JS_NewFunctionById(cx, FunctionWrapper, 0, 0,
|
||||||
|
JS_GetGlobalForObject(cx, obj), id);
|
||||||
|
if (!fun)
|
||||||
|
return JS_FALSE;
|
||||||
|
|
||||||
|
JSObject *funobj = JS_GetFunctionObject(fun);
|
||||||
|
if (!JS_SetReservedSlot(cx, funobj, 0, OBJECT_TO_JSVAL(propobj)))
|
||||||
|
return JS_FALSE;
|
||||||
|
*vp = OBJECT_TO_JSVAL(funobj);
|
||||||
|
return JS_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* void makeObjectPropsNormal(jsval vobj); */
|
||||||
|
NS_IMETHODIMP
|
||||||
|
nsXPCComponents_Utils::MakeObjectPropsNormal(const jsval &vobj, JSContext *cx)
|
||||||
|
{
|
||||||
|
if (!cx)
|
||||||
|
return NS_ERROR_FAILURE;
|
||||||
|
|
||||||
|
// first argument must be an object
|
||||||
|
if(JSVAL_IS_PRIMITIVE(vobj))
|
||||||
|
return NS_ERROR_XPC_BAD_CONVERT_JS;
|
||||||
|
|
||||||
|
JSObject *obj = JSVAL_TO_OBJECT(vobj)->unwrap();
|
||||||
|
|
||||||
|
JSAutoEnterCompartment ac;
|
||||||
|
if (!ac.enter(cx, obj))
|
||||||
|
return NS_ERROR_FAILURE;
|
||||||
|
|
||||||
|
js::AutoIdArray ida(cx, JS_Enumerate(cx, obj));
|
||||||
|
if (!ida)
|
||||||
|
return NS_ERROR_FAILURE;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < ida.length(); ++i) {
|
||||||
|
jsid id = ida[i];
|
||||||
|
jsval v;
|
||||||
|
|
||||||
|
if (!JS_GetPropertyById(cx, obj, id, &v))
|
||||||
|
return NS_ERROR_FAILURE;
|
||||||
|
|
||||||
|
if (JSVAL_IS_PRIMITIVE(v))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
JSObject *propobj = JSVAL_TO_OBJECT(v);
|
||||||
|
// TODO Deal with non-functions.
|
||||||
|
if (!propobj->isWrapper() || !propobj->isCallable())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!WrapCallable(cx, obj, id, propobj, &v) ||
|
||||||
|
!JS_SetPropertyById(cx, obj, id, &v))
|
||||||
|
return NS_ERROR_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
/* string canCreateWrapper (in nsIIDPtr iid); */
|
/* string canCreateWrapper (in nsIIDPtr iid); */
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
nsXPCComponents_Utils::CanCreateWrapper(const nsIID * iid, char **_retval)
|
nsXPCComponents_Utils::CanCreateWrapper(const nsIID * iid, char **_retval)
|
||||||
|
@ -66,6 +66,7 @@ _CHROME_FILES = \
|
|||||||
test_bug596580.xul \
|
test_bug596580.xul \
|
||||||
test_bug654370.xul \
|
test_bug654370.xul \
|
||||||
test_bug658560.xul \
|
test_bug658560.xul \
|
||||||
|
test_APIExposer.xul \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
|
||||||
# Disabled until this test gets updated to test the new proxy based
|
# Disabled until this test gets updated to test the new proxy based
|
||||||
|
52
js/src/xpconnect/tests/chrome/test_APIExposer.xul
Normal file
52
js/src/xpconnect/tests/chrome/test_APIExposer.xul
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
<?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=634156
|
||||||
|
-->
|
||||||
|
<window title="Testing API exposing capabilities"
|
||||||
|
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=634156"
|
||||||
|
target="_blank">Mozilla Bug 634156</a>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
<!-- test code goes here -->
|
||||||
|
<script type="application/javascript"><![CDATA[
|
||||||
|
const Cu = Components.utils;
|
||||||
|
|
||||||
|
var sandbox = new Cu.Sandbox("about:blank");
|
||||||
|
sandbox.ok = ok;
|
||||||
|
sandbox.is = is;
|
||||||
|
Cu.evalInSandbox("Object.defineProperty(Object.prototype, 'getProp', { get: function() { throw 'FAIL: called getter' }, set: function() { throw 'FAIL: called setter'; } })", sandbox);
|
||||||
|
|
||||||
|
var obj = Cu.createObjectIn(sandbox);
|
||||||
|
is(Object.getPrototypeOf(obj), Cu.evalInSandbox("Object.prototype", sandbox),
|
||||||
|
"Object is a sandbox object");
|
||||||
|
|
||||||
|
function genPropDesc(value) {
|
||||||
|
return { enumerable: true, configurable: true, writable: true,
|
||||||
|
value: value };
|
||||||
|
}
|
||||||
|
const props = {
|
||||||
|
'getProp': genPropDesc(function() { ok(true, "called prop that shadowed a getter"); }),
|
||||||
|
'argument': genPropDesc(function(arg) { is(arg, 42, "can pass arguments through"); }),
|
||||||
|
'returnval': genPropDesc(function() { return 42; })
|
||||||
|
};
|
||||||
|
Object.defineProperties(obj, props);
|
||||||
|
Cu.makeObjectPropsNormal(obj);
|
||||||
|
|
||||||
|
sandbox.api = obj;
|
||||||
|
Cu.evalInSandbox("ok(Object.getPrototypeOf(api) === Object.prototype, 'we have the object we expected'); \
|
||||||
|
api.getProp(); api.argument(42); is(api.returnval(), 42, 'return value was correct');\
|
||||||
|
ok(typeof api.getProp === 'function', 'functions are functions');\
|
||||||
|
ok(Object.getPrototypeOf(api.getProp) === Function.prototype, 'functions come from our scope');", sandbox);
|
||||||
|
]]></script>
|
||||||
|
</window>
|
@ -188,18 +188,22 @@ function createInstallTrigger(window) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let sandbox = Cu.Sandbox(window);
|
let obj = Cu.createObjectIn(window);
|
||||||
let obj = Cu.evalInSandbox(
|
function genPropDesc(fun) {
|
||||||
"(function (x) {\
|
return { enumerable: true, configurable: true, writable: true,
|
||||||
var bind = Function.bind;\
|
value: chromeObject[fun].bind(chromeObject) };
|
||||||
return {\
|
}
|
||||||
enabled: bind.call(x.enabled, x),\
|
const properties = {
|
||||||
updateEnabled: bind.call(x.updateEnabled, x),\
|
'enabled': genPropDesc('enabled'),
|
||||||
install: bind.call(x.install, x),\
|
'updateEnabled': genPropDesc('updateEnabled'),
|
||||||
installChrome: bind.call(x.installChrome, x),\
|
'install': genPropDesc('install'),
|
||||||
startSoftwareUpdate: bind.call(x.startSoftwareUpdate, x)\
|
'installChrome': genPropDesc('installChrome'),
|
||||||
};\
|
'startSoftwareUpdate': genPropDesc('startSoftwareUpdate')
|
||||||
})", sandbox)(chromeObject);
|
};
|
||||||
|
|
||||||
|
Object.defineProperties(obj, properties);
|
||||||
|
|
||||||
|
Cu.makeObjectPropsNormal(obj);
|
||||||
|
|
||||||
obj.SKIN = chromeObject.SKIN;
|
obj.SKIN = chromeObject.SKIN;
|
||||||
obj.LOCALE = chromeObject.LOCALE;
|
obj.LOCALE = chromeObject.LOCALE;
|
||||||
|
Loading…
Reference in New Issue
Block a user