зеркало из https://github.com/mozilla/gecko-dev.git
Bug 897913 part 2. Allow touching interface objects via an Xray even if the page they're in can't touch them. r=bholley,smaug
This commit is contained in:
Родитель
4b9ed29cef
Коммит
ba738ed1e5
|
@ -3540,6 +3540,14 @@ nsWindowSH::GlobalResolve(nsGlobalWindow *aWin, JSContext *cx,
|
|||
JS::Rooted<JSObject*> global(cx);
|
||||
bool defineOnXray = xpc::WrapperFactory::IsXrayWrapper(obj);
|
||||
if (defineOnXray) {
|
||||
// Check whether to define this property on the Xray first. This allows
|
||||
// consumers to opt in to defining on the xray even if they don't want
|
||||
// to define on the underlying global.
|
||||
if (name_struct->mConstructorEnabled &&
|
||||
!(*name_struct->mConstructorEnabled)(cx, obj)) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
global = js::CheckedUnwrap(obj, /* stopAtOuter = */ false);
|
||||
if (!global) {
|
||||
return NS_ERROR_DOM_SECURITY_ERR;
|
||||
|
@ -3549,36 +3557,36 @@ nsWindowSH::GlobalResolve(nsGlobalWindow *aWin, JSContext *cx,
|
|||
global = obj;
|
||||
}
|
||||
|
||||
// Check whether our constructor is enabled after we unwrap Xrays, since
|
||||
// we don't want to define an interface on the Xray if it's disabled in
|
||||
// the target global, even if it's enabled in the Xray's global.
|
||||
if (name_struct->mConstructorEnabled &&
|
||||
!(*name_struct->mConstructorEnabled)(cx, global)) {
|
||||
// Check whether to define on the global too. Note that at this point cx
|
||||
// is in the compartment of global even if we were coming in via an Xray.
|
||||
bool defineOnGlobal = !name_struct->mConstructorEnabled ||
|
||||
(*name_struct->mConstructorEnabled)(cx, global);
|
||||
|
||||
if (!defineOnGlobal && !defineOnXray) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
bool enabled;
|
||||
JS::Rooted<JSObject*> interfaceObject(cx, define(cx, global, id, &enabled));
|
||||
if (enabled) {
|
||||
if (!interfaceObject) {
|
||||
JS::Rooted<JSObject*> interfaceObject(cx, define(cx, global, id,
|
||||
defineOnGlobal));
|
||||
if (!interfaceObject) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
if (defineOnXray) {
|
||||
// This really should be handled by the Xray for the window.
|
||||
ac.destroy();
|
||||
if (!JS_WrapObject(cx, interfaceObject.address()) ||
|
||||
!JS_DefinePropertyById(cx, obj, id,
|
||||
JS::ObjectValue(*interfaceObject), JS_PropertyStub,
|
||||
JS_StrictPropertyStub, 0)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
if (defineOnXray) {
|
||||
// This really should be handled by the Xray for the window.
|
||||
ac.destroy();
|
||||
if (!JS_WrapObject(cx, interfaceObject.address()) ||
|
||||
!JS_DefinePropertyById(cx, obj, id,
|
||||
JS::ObjectValue(*interfaceObject), JS_PropertyStub,
|
||||
JS_StrictPropertyStub, 0)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
*did_resolve = true;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
*did_resolve = true;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -371,7 +371,7 @@ CreateInterfaceObject(JSContext* cx, JS::Handle<JSObject*> global,
|
|||
JS::Handle<JSObject*> proto,
|
||||
const NativeProperties* properties,
|
||||
const NativeProperties* chromeOnlyProperties,
|
||||
const char* name)
|
||||
const char* name, bool defineOnGlobal)
|
||||
{
|
||||
JS::Rooted<JSObject*> constructor(cx);
|
||||
if (constructorClass) {
|
||||
|
@ -455,7 +455,7 @@ CreateInterfaceObject(JSContext* cx, JS::Handle<JSObject*> global,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
if (!DefineConstructor(cx, global, name, constructor)) {
|
||||
if (defineOnGlobal && !DefineConstructor(cx, global, name, constructor)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
@ -471,8 +471,9 @@ CreateInterfaceObject(JSContext* cx, JS::Handle<JSObject*> global,
|
|||
JS::ObjectValue(*proto), JS_PropertyStub,
|
||||
JS_StrictPropertyStub,
|
||||
JSPROP_PERMANENT | JSPROP_READONLY) ||
|
||||
!DefineConstructor(cx, global, namedConstructors->mName,
|
||||
namedConstructor)) {
|
||||
(defineOnGlobal &&
|
||||
!DefineConstructor(cx, global, namedConstructors->mName,
|
||||
namedConstructor))) {
|
||||
return nullptr;
|
||||
}
|
||||
js::SetReservedSlot(constructor, namedConstructorSlot++,
|
||||
|
@ -562,7 +563,7 @@ CreateInterfaceObjects(JSContext* cx, JS::Handle<JSObject*> global,
|
|||
JS::Heap<JSObject*>* constructorCache, const DOMClass* domClass,
|
||||
const NativeProperties* properties,
|
||||
const NativeProperties* chromeOnlyProperties,
|
||||
const char* name)
|
||||
const char* name, bool defineOnGlobal)
|
||||
{
|
||||
MOZ_ASSERT(protoClass || constructorClass || constructor,
|
||||
"Need at least one class or a constructor!");
|
||||
|
@ -612,7 +613,8 @@ CreateInterfaceObjects(JSContext* cx, JS::Handle<JSObject*> global,
|
|||
interface = CreateInterfaceObject(cx, global, constructorProto,
|
||||
constructorClass, constructor,
|
||||
ctorNargs, namedConstructors, proto,
|
||||
properties, chromeOnlyProperties, name);
|
||||
properties, chromeOnlyProperties, name,
|
||||
defineOnGlobal);
|
||||
if (!interface) {
|
||||
if (protoCache) {
|
||||
// If we fail we need to make sure to clear the value of protoCache we
|
||||
|
|
|
@ -364,6 +364,12 @@ struct NamedConstructor
|
|||
* on objects in chrome compartments. This must be null if the
|
||||
* interface doesn't have any ChromeOnly properties or if the
|
||||
* object is being created in non-chrome compartment.
|
||||
* defineOnGlobal controls whether properties should be defined on the given
|
||||
* global for the interface object (if any) and named
|
||||
* constructors (if any) for this interface. This can be
|
||||
* false in situations where we want the properties to only
|
||||
* appear on privileged Xrays but not on the unprivileged
|
||||
* underlying global.
|
||||
*
|
||||
* At least one of protoClass, constructorClass or constructor should be
|
||||
* non-null. If constructorClass or constructor are non-null, the resulting
|
||||
|
@ -380,7 +386,7 @@ CreateInterfaceObjects(JSContext* cx, JS::Handle<JSObject*> global,
|
|||
JS::Heap<JSObject*>* constructorCache, const DOMClass* domClass,
|
||||
const NativeProperties* regularProperties,
|
||||
const NativeProperties* chromeOnlyProperties,
|
||||
const char* name);
|
||||
const char* name, bool defineOnGlobal);
|
||||
|
||||
/*
|
||||
* Define the unforgeable attributes on an object.
|
||||
|
|
|
@ -1664,7 +1664,8 @@ class CGCreateInterfaceObjectsMethod(CGAbstractMethod):
|
|||
def __init__(self, descriptor, properties):
|
||||
args = [Argument('JSContext*', 'aCx'),
|
||||
Argument('JS::Handle<JSObject*>', 'aGlobal'),
|
||||
Argument('JS::Heap<JSObject*>*', 'protoAndIfaceArray')]
|
||||
Argument('JS::Heap<JSObject*>*', 'aProtoAndIfaceArray'),
|
||||
Argument('bool', 'aDefineOnGlobal')]
|
||||
CGAbstractMethod.__init__(self, descriptor, 'CreateInterfaceObjects', 'void', args)
|
||||
self.properties = properties
|
||||
def definition_body(self):
|
||||
|
@ -1791,13 +1792,13 @@ if (!unforgeableHolder) {
|
|||
|
||||
if needInterfacePrototypeObject:
|
||||
protoClass = "&PrototypeClass.mBase"
|
||||
protoCache = "&protoAndIfaceArray[prototypes::id::%s]" % self.descriptor.name
|
||||
protoCache = "&aProtoAndIfaceArray[prototypes::id::%s]" % self.descriptor.name
|
||||
else:
|
||||
protoClass = "nullptr"
|
||||
protoCache = "nullptr"
|
||||
if needInterfaceObject:
|
||||
interfaceClass = "&InterfaceObjectClass.mBase"
|
||||
interfaceCache = "&protoAndIfaceArray[constructors::id::%s]" % self.descriptor.name
|
||||
interfaceCache = "&aProtoAndIfaceArray[constructors::id::%s]" % self.descriptor.name
|
||||
else:
|
||||
# We don't have slots to store the named constructors.
|
||||
assert len(self.descriptor.interface.namedConstructors) == 0
|
||||
|
@ -1828,7 +1829,7 @@ if (!unforgeableHolder) {
|
|||
" %s,\n"
|
||||
" %s,\n"
|
||||
" %s,\n"
|
||||
" %s);" % (
|
||||
" %s, aDefineOnGlobal);" % (
|
||||
protoClass, protoCache,
|
||||
interfaceClass, constructHookHolder, constructArgs,
|
||||
namedConstructors,
|
||||
|
@ -1840,7 +1841,7 @@ if (!unforgeableHolder) {
|
|||
if UseHolderForUnforgeable(self.descriptor):
|
||||
assert needInterfacePrototypeObject
|
||||
setUnforgeableHolder = CGGeneric(
|
||||
"JSObject* proto = protoAndIfaceArray[prototypes::id::%s];\n"
|
||||
"JSObject* proto = aProtoAndIfaceArray[prototypes::id::%s];\n"
|
||||
"if (proto) {\n"
|
||||
" js::SetReservedSlot(proto, DOM_INTERFACE_PROTO_SLOTS_BASE,\n"
|
||||
" JS::ObjectValue(*unforgeableHolder));\n"
|
||||
|
@ -1858,9 +1859,9 @@ class CGGetPerInterfaceObject(CGAbstractMethod):
|
|||
A method for getting a per-interface object (a prototype object or interface
|
||||
constructor object).
|
||||
"""
|
||||
def __init__(self, descriptor, name, idPrefix=""):
|
||||
def __init__(self, descriptor, name, idPrefix="", extraArgs=[]):
|
||||
args = [Argument('JSContext*', 'aCx'),
|
||||
Argument('JS::Handle<JSObject*>', 'aGlobal')]
|
||||
Argument('JS::Handle<JSObject*>', 'aGlobal')] + extraArgs
|
||||
CGAbstractMethod.__init__(self, descriptor, name,
|
||||
'JS::Handle<JSObject*>', args, inline=True)
|
||||
self.id = idPrefix + "id::" + self.descriptor.name
|
||||
|
@ -1874,7 +1875,7 @@ class CGGetPerInterfaceObject(CGAbstractMethod):
|
|||
/* Check to see whether the interface objects are already installed */
|
||||
JS::Heap<JSObject*>* protoAndIfaceArray = GetProtoAndIfaceArray(aGlobal);
|
||||
if (!protoAndIfaceArray[%s]) {
|
||||
CreateInterfaceObjects(aCx, aGlobal, protoAndIfaceArray);
|
||||
CreateInterfaceObjects(aCx, aGlobal, protoAndIfaceArray, aDefineOnGlobal);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1897,15 +1898,18 @@ class CGGetProtoObjectMethod(CGGetPerInterfaceObject):
|
|||
def definition_body(self):
|
||||
return """
|
||||
/* Get the interface prototype object for this class. This will create the
|
||||
object as needed. */""" + CGGetPerInterfaceObject.definition_body(self)
|
||||
object as needed. */
|
||||
bool aDefineOnGlobal = true;""" + CGGetPerInterfaceObject.definition_body(self)
|
||||
|
||||
class CGGetConstructorObjectMethod(CGGetPerInterfaceObject):
|
||||
"""
|
||||
A method for getting the interface constructor object.
|
||||
"""
|
||||
def __init__(self, descriptor):
|
||||
CGGetPerInterfaceObject.__init__(self, descriptor, "GetConstructorObject",
|
||||
"constructors::")
|
||||
CGGetPerInterfaceObject.__init__(
|
||||
self, descriptor, "GetConstructorObject",
|
||||
"constructors::",
|
||||
extraArgs=[Argument("bool", "aDefineOnGlobal", "true")])
|
||||
def definition_body(self):
|
||||
return """
|
||||
/* Get the interface object for this class. This will create the object as
|
||||
|
@ -1920,7 +1924,7 @@ class CGDefineDOMInterfaceMethod(CGAbstractMethod):
|
|||
args = [Argument('JSContext*', 'aCx'),
|
||||
Argument('JS::Handle<JSObject*>', 'aGlobal'),
|
||||
Argument('JS::Handle<jsid>', 'id'),
|
||||
Argument('bool*', 'aEnabled')]
|
||||
Argument('bool', 'aDefineOnGlobal')]
|
||||
CGAbstractMethod.__init__(self, descriptor, 'DefineDOMInterface', 'JSObject*', args)
|
||||
|
||||
def declare(self):
|
||||
|
@ -1935,7 +1939,7 @@ class CGDefineDOMInterfaceMethod(CGAbstractMethod):
|
|||
|
||||
def definition_body(self):
|
||||
if len(self.descriptor.interface.namedConstructors) > 0:
|
||||
getConstructor = """ JSObject* interfaceObject = GetConstructorObject(aCx, aGlobal);
|
||||
getConstructor = """ JSObject* interfaceObject = GetConstructorObject(aCx, aGlobal, aDefineOnGlobal);
|
||||
if (!interfaceObject) {
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -1947,10 +1951,8 @@ class CGDefineDOMInterfaceMethod(CGAbstractMethod):
|
|||
}
|
||||
return interfaceObject;"""
|
||||
else:
|
||||
getConstructor = " return GetConstructorObject(aCx, aGlobal);"
|
||||
return (""" *aEnabled = true;
|
||||
|
||||
""" + getConstructor)
|
||||
getConstructor = " return GetConstructorObject(aCx, aGlobal, aDefineOnGlobal);"
|
||||
return getConstructor
|
||||
|
||||
class CGConstructorEnabledViaPrefEnabled(CGAbstractMethod):
|
||||
"""
|
||||
|
|
|
@ -457,7 +457,7 @@ inline bool IsDOMProxy(JSObject *obj)
|
|||
|
||||
typedef JSObject*
|
||||
(*DefineInterface)(JSContext *cx, JS::Handle<JSObject*> global,
|
||||
JS::Handle<jsid> id, bool *enabled);
|
||||
JS::Handle<jsid> id, bool defineOnGlobal);
|
||||
|
||||
typedef JSObject*
|
||||
(*ConstructNavigatorProperty)(JSContext *cx, JS::Handle<JSObject*> naviObj);
|
||||
|
|
Загрузка…
Ссылка в новой задаче