mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-27 14:52:16 +00:00
Bug 1643457 - Support ChromeOnly properties on remote proxies. r=mccr8
Differential Revision: https://phabricator.services.mozilla.com/D78360
This commit is contained in:
parent
d8029a3fe7
commit
a191be346c
@ -1456,8 +1456,7 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
|
||||
class RemoteLocationProxy
|
||||
: public RemoteObjectProxy<BrowsingContext::LocationProxy,
|
||||
Location_Binding::sCrossOriginAttributes,
|
||||
Location_Binding::sCrossOriginMethods> {
|
||||
Location_Binding::sCrossOriginProperties> {
|
||||
public:
|
||||
typedef RemoteObjectProxy Base;
|
||||
|
||||
|
@ -235,7 +235,7 @@ bool MaybeCrossOriginObjectMixins::CrossOriginSet(
|
||||
/* static */
|
||||
bool MaybeCrossOriginObjectMixins::EnsureHolder(
|
||||
JSContext* cx, JS::Handle<JSObject*> obj, size_t slot,
|
||||
JSPropertySpec* attributes, JSFunctionSpec* methods,
|
||||
const CrossOriginProperties& properties,
|
||||
JS::MutableHandle<JSObject*> holder) {
|
||||
MOZ_ASSERT(!IsPlatformObjectSameOrigin(cx, obj) || IsRemoteObjectProxy(obj),
|
||||
"Why are we calling this at all in same-origin cases?");
|
||||
@ -311,9 +311,14 @@ bool MaybeCrossOriginObjectMixins::EnsureHolder(
|
||||
// cross-compartment references to all the methods it holds, since those
|
||||
// methods need to be in our current Realm. It seems better to allocate the
|
||||
// holder in our current Realm.
|
||||
bool isChrome = xpc::AccessCheck::isChrome(js::GetContextRealm(cx));
|
||||
holder.set(JS_NewObjectWithGivenProto(cx, nullptr, nullptr));
|
||||
if (!holder || !JS_DefineProperties(cx, holder, attributes) ||
|
||||
!JS_DefineFunctions(cx, holder, methods)) {
|
||||
if (!holder || !JS_DefineProperties(cx, holder, properties.mAttributes) ||
|
||||
!JS_DefineFunctions(cx, holder, properties.mMethods) ||
|
||||
(isChrome && properties.mChromeOnlyAttributes &&
|
||||
!JS_DefineProperties(cx, holder, properties.mChromeOnlyAttributes)) ||
|
||||
(isChrome && properties.mChromeOnlyMethods &&
|
||||
!JS_DefineFunctions(cx, holder, properties.mChromeOnlyMethods))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -34,6 +34,22 @@
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
/**
|
||||
* "mAttributes" and "mMethods" are the cross-origin attributes and methods we
|
||||
* care about, which should get defined on holders.
|
||||
*
|
||||
* "mChromeOnlyAttributes" and "mChromeOnlyMethods" are the cross-origin
|
||||
* attributes and methods we care about, which should get defined on holders
|
||||
* for the chrome realm, in addition to the properties that are in
|
||||
* "mAttributes" and "mMethods".
|
||||
*/
|
||||
struct CrossOriginProperties {
|
||||
const JSPropertySpec* mAttributes;
|
||||
const JSFunctionSpec* mMethods;
|
||||
const JSPropertySpec* mChromeOnlyAttributes;
|
||||
const JSFunctionSpec* mChromeOnlyMethods;
|
||||
};
|
||||
|
||||
// Methods that MaybeCrossOriginObject wants that do not depend on the "Base"
|
||||
// template parameter. We can avoid having multiple instantiations of them by
|
||||
// pulling them out into this helper class.
|
||||
@ -118,12 +134,11 @@ class MaybeCrossOriginObjectMixins {
|
||||
* "obj" is the object which has space to store the collection of holders in
|
||||
* the given slot.
|
||||
*
|
||||
* "attributes" and "methods" are the cross-origin attributes and methods we
|
||||
* care about, which should get defined on holders.
|
||||
* "properties" are the cross-origin attributes and methods we care about,
|
||||
* which should get defined on holders.
|
||||
*/
|
||||
static bool EnsureHolder(JSContext* cx, JS::Handle<JSObject*> obj,
|
||||
size_t slot, JSPropertySpec* attributes,
|
||||
JSFunctionSpec* methods,
|
||||
size_t slot, const CrossOriginProperties& properties,
|
||||
JS::MutableHandle<JSObject*> holder);
|
||||
|
||||
/**
|
||||
|
@ -24,8 +24,7 @@ namespace dom {
|
||||
|
||||
class RemoteOuterWindowProxy
|
||||
: public RemoteObjectProxy<BrowsingContext,
|
||||
Window_Binding::sCrossOriginAttributes,
|
||||
Window_Binding::sCrossOriginMethods> {
|
||||
Window_Binding::sCrossOriginProperties> {
|
||||
public:
|
||||
typedef RemoteObjectProxy Base;
|
||||
|
||||
|
@ -1081,8 +1081,7 @@ bool nsOuterWindowProxy::EnsureHolder(
|
||||
JSContext* cx, JS::Handle<JSObject*> proxy,
|
||||
JS::MutableHandle<JSObject*> holder) const {
|
||||
return EnsureHolder(cx, proxy, HOLDER_WEAKMAP_SLOT,
|
||||
Window_Binding::sCrossOriginAttributes,
|
||||
Window_Binding::sCrossOriginMethods, holder);
|
||||
Window_Binding::sCrossOriginProperties, holder);
|
||||
}
|
||||
|
||||
size_t nsOuterWindowProxy::objectMoved(JSObject* obj, JSObject* old) const {
|
||||
|
@ -4324,7 +4324,9 @@ class CGClearCachedValueMethod(CGAbstractMethod):
|
||||
class CGCrossOriginProperties(CGThing):
|
||||
def __init__(self, descriptor):
|
||||
attrs = []
|
||||
chromeOnlyAttrs = []
|
||||
methods = []
|
||||
chromeOnlyMethods = []
|
||||
for m in descriptor.interface.members:
|
||||
if m.isAttr() and (m.getExtendedAttribute("CrossOriginReadable") or
|
||||
m.getExtendedAttribute("CrossOriginWritable")):
|
||||
@ -4337,7 +4339,10 @@ class CGCrossOriginProperties(CGThing):
|
||||
if len(m.bindingAliases) > 0:
|
||||
raise TypeError("Don't know how to deal with aliases for %s" %
|
||||
m.identifier.name)
|
||||
attrs.extend(AttrDefiner.attrData(m, overrideFlags="0"))
|
||||
if m.getExtendedAttribute("ChromeOnly") is not None:
|
||||
chromeOnlyAttrs.extend(AttrDefiner.attrData(m, overrideFlags="0"))
|
||||
else:
|
||||
attrs.extend(AttrDefiner.attrData(m, overrideFlags="0"))
|
||||
elif m.isMethod() and m.getExtendedAttribute("CrossOriginCallable"):
|
||||
if m.isStatic():
|
||||
raise TypeError("Don't know how to deal with static method %s" %
|
||||
@ -4348,7 +4353,10 @@ class CGCrossOriginProperties(CGThing):
|
||||
if len(m.aliases) > 0:
|
||||
raise TypeError("Don't know how to deal with aliases for %s" %
|
||||
m.identifier.name)
|
||||
methods.append(MethodDefiner.methodData(m, descriptor, overrideFlags="JSPROP_READONLY"))
|
||||
if m.getExtendedAttribute("ChromeOnly") is not None:
|
||||
chromeOnlyMethods.append(MethodDefiner.methodData(m, descriptor, overrideFlags="JSPROP_READONLY"))
|
||||
else:
|
||||
methods.append(MethodDefiner.methodData(m, descriptor, overrideFlags="JSPROP_READONLY"))
|
||||
|
||||
if len(attrs) > 0:
|
||||
self.attributeSpecs, _ = PropertyDefiner.generatePrefableArrayValues(
|
||||
@ -4363,15 +4371,42 @@ class CGCrossOriginProperties(CGThing):
|
||||
else:
|
||||
self.methodSpecs = [' JS_FS_END\n']
|
||||
|
||||
if len(chromeOnlyAttrs) > 0:
|
||||
self.chromeOnlyAttributeSpecs, _ = PropertyDefiner.generatePrefableArrayValues(
|
||||
chromeOnlyAttrs, descriptor, AttrDefiner.formatSpec, ' JS_PS_END\n',
|
||||
AttrDefiner.condition, functools.partial(AttrDefiner.specData, crossOriginOnly=True))
|
||||
else:
|
||||
self.chromeOnlyAttributeSpecs = []
|
||||
if len(chromeOnlyMethods) > 0:
|
||||
self.chromeOnlyMethodSpecs, _ = PropertyDefiner.generatePrefableArrayValues(
|
||||
chromeOnlyMethods, descriptor, MethodDefiner.formatSpec, ' JS_FS_END\n',
|
||||
MethodDefiner.condition, MethodDefiner.specData)
|
||||
else:
|
||||
self.chromeOnlyMethodSpecs = []
|
||||
|
||||
def declare(self):
|
||||
return fill("""
|
||||
extern JSPropertySpec sCrossOriginAttributes[${attributesLength}];
|
||||
extern JSFunctionSpec sCrossOriginMethods[${methodsLength}];
|
||||
""",
|
||||
attributesLength=len(self.attributeSpecs),
|
||||
methodsLength=len(self.methodSpecs))
|
||||
return dedent("""
|
||||
extern const CrossOriginProperties sCrossOriginProperties;
|
||||
""")
|
||||
|
||||
def define(self):
|
||||
def defineChromeOnly(name, specs, specType):
|
||||
if len(specs) == 0:
|
||||
return ("", "nullptr")
|
||||
name = "sChromeOnlyCrossOrigin" + name
|
||||
define = fill(
|
||||
"""
|
||||
static const ${specType} ${name}[] = {
|
||||
$*{specs}
|
||||
};
|
||||
""",
|
||||
specType=specType,
|
||||
name=name,
|
||||
specs=",\n".join(specs))
|
||||
return (define, name)
|
||||
|
||||
chromeOnlyAttributes = defineChromeOnly("Attributes", self.chromeOnlyAttributeSpecs, "JSPropertySpec")
|
||||
chromeOnlyMethods = defineChromeOnly("Methods", self.chromeOnlyMethodSpecs, "JSFunctionSpec")
|
||||
return fill(
|
||||
"""
|
||||
// We deliberately use brace-elision to make Visual Studio produce better initalization code.
|
||||
@ -4379,18 +4414,30 @@ class CGCrossOriginProperties(CGThing):
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wmissing-braces"
|
||||
#endif
|
||||
JSPropertySpec sCrossOriginAttributes[] = {
|
||||
static const JSPropertySpec sCrossOriginAttributes[] = {
|
||||
$*{attributeSpecs}
|
||||
};
|
||||
JSFunctionSpec sCrossOriginMethods[] = {
|
||||
static const JSFunctionSpec sCrossOriginMethods[] = {
|
||||
$*{methodSpecs}
|
||||
};
|
||||
$*{chromeOnlyAttributeSpecs}
|
||||
$*{chromeOnlyMethodSpecs}
|
||||
const CrossOriginProperties sCrossOriginProperties = {
|
||||
sCrossOriginAttributes,
|
||||
sCrossOriginMethods,
|
||||
${chromeOnlyAttributes},
|
||||
${chromeOnlyMethods}
|
||||
};
|
||||
#if defined(__clang__)
|
||||
#pragma clang diagnostic pop
|
||||
#endif
|
||||
""",
|
||||
attributeSpecs=",\n".join(self.attributeSpecs),
|
||||
methodSpecs=",\n".join(self.methodSpecs))
|
||||
methodSpecs=",\n".join(self.methodSpecs),
|
||||
chromeOnlyAttributeSpecs=chromeOnlyAttributes[0],
|
||||
chromeOnlyMethodSpecs=chromeOnlyMethods[0],
|
||||
chromeOnlyAttributes=chromeOnlyAttributes[1],
|
||||
chromeOnlyMethods=chromeOnlyMethods[1])
|
||||
|
||||
|
||||
class CGCycleCollectionTraverseForOwningUnionMethod(CGAbstractMethod):
|
||||
@ -13589,7 +13636,7 @@ class CGDOMJSProxyHandler_set(ClassMethod):
|
||||
|
||||
class CGDOMJSProxyHandler_EnsureHolder(ClassMethod):
|
||||
"""
|
||||
Implementation of set(). We only use this for cross-origin objects.
|
||||
Implementation of EnsureHolder(). We only use this for cross-origin objects.
|
||||
"""
|
||||
def __init__(self, descriptor):
|
||||
args = [Argument('JSContext*', 'cx'),
|
||||
@ -13602,10 +13649,9 @@ class CGDOMJSProxyHandler_EnsureHolder(ClassMethod):
|
||||
def getBody(self):
|
||||
return dedent(
|
||||
"""
|
||||
// Our holder slot is our last slot.
|
||||
return EnsureHolder(cx, proxy,
|
||||
JSCLASS_RESERVED_SLOTS(js::GetObjectClass(proxy)) - 1,
|
||||
sCrossOriginAttributes, sCrossOriginMethods, holder);
|
||||
sCrossOriginProperties, holder);
|
||||
""")
|
||||
|
||||
|
||||
|
@ -134,7 +134,7 @@ class RemoteObjectProxyBase : public js::BaseProxyHandler,
|
||||
* hash map in the JS compartment's private (@see
|
||||
* xpc::CompartmentPrivate::GetRemoteProxyMap).
|
||||
*/
|
||||
template <class Native, JSPropertySpec* P, JSFunctionSpec* F>
|
||||
template <class Native, const CrossOriginProperties& P>
|
||||
class RemoteObjectProxy : public RemoteObjectProxyBase {
|
||||
public:
|
||||
void finalize(JSFreeOp* aFop, JSObject* aProxy) const final {
|
||||
@ -160,7 +160,7 @@ class RemoteObjectProxy : public RemoteObjectProxyBase {
|
||||
bool EnsureHolder(JSContext* aCx, JS::Handle<JSObject*> aProxy,
|
||||
JS::MutableHandle<JSObject*> aHolder) const final {
|
||||
return MaybeCrossOriginObjectMixins::EnsureHolder(
|
||||
aCx, aProxy, /* slot = */ 0, P, F, aHolder);
|
||||
aCx, aProxy, /* slot = */ 0, P, aHolder);
|
||||
}
|
||||
|
||||
static const JSClass sClass;
|
||||
|
Loading…
Reference in New Issue
Block a user