Bug 996785 - Distinguish local and remote CPOW objects in IPDL (r=mrbkap)

This commit is contained in:
Bill McCloskey 2014-05-16 16:40:36 -07:00
parent 719253d75f
commit c9f2d3779d
7 changed files with 69 additions and 52 deletions

View File

@ -71,16 +71,13 @@ JavaScriptChild::RecvDropObject(const ObjectId &objId)
} }
bool bool
JavaScriptChild::toId(JSContext *cx, JSObject *obj, ObjectId *idp) JavaScriptChild::toObjectVariant(JSContext *cx, JSObject *obj, ObjectVariant *objVarp)
{ {
if (!obj) { JS_ASSERT(obj);
*idp = 0;
return true;
}
ObjectId id = ids_.find(obj); ObjectId id = ids_.find(obj);
if (id) { if (id) {
*idp = id; *objVarp = RemoteObject(id);
return true; return true;
} }
@ -99,13 +96,15 @@ JavaScriptChild::toId(JSContext *cx, JSObject *obj, ObjectId *idp)
if (!ids_.add(cx, obj, id)) if (!ids_.add(cx, obj, id))
return false; return false;
*idp = id; *objVarp = RemoteObject(id);
return true; return true;
} }
JSObject * JSObject *
JavaScriptChild::fromId(JSContext *cx, ObjectId id) JavaScriptChild::fromObjectVariant(JSContext *cx, ObjectVariant objVar)
{ {
JS_ASSERT(objVar.type() == ObjectVariant::TLocalObject);
ObjectId id = objVar.get_LocalObject().id();
JSObject *obj = findObjectById(id); JSObject *obj = findObjectById(id);
MOZ_ASSERT(obj); MOZ_ASSERT(obj);
return obj; return obj;

View File

@ -28,8 +28,8 @@ class JavaScriptChild : public JavaScriptBase<PJavaScriptChild>
virtual void drop(JSObject *obj) { MOZ_CRASH(); } virtual void drop(JSObject *obj) { MOZ_CRASH(); }
private: private:
JSObject *fromId(JSContext *cx, ObjectId id); virtual bool toObjectVariant(JSContext *cx, JSObject *obj, ObjectVariant *objVarp);
bool toId(JSContext *cx, JSObject *obj, ObjectId *idp); virtual JSObject *fromObjectVariant(JSContext *cx, ObjectVariant objVar);
bool fail(JSContext *cx, ReturnStatus *rs); bool fail(JSContext *cx, ReturnStatus *rs);
bool ok(ReturnStatus *rs); bool ok(ReturnStatus *rs);

View File

@ -47,21 +47,25 @@ JavaScriptParent::init()
} }
bool bool
JavaScriptParent::toId(JSContext *cx, JSObject *obj, ObjectId *idp) JavaScriptParent::toObjectVariant(JSContext *cx, JSObject *obj, ObjectVariant *objVarp)
{ {
JS_ASSERT(obj);
obj = js::CheckedUnwrap(obj, false); obj = js::CheckedUnwrap(obj, false);
if (!obj || !IsCPOW(obj)) { if (!obj || !IsCPOW(obj)) {
JS_ReportError(cx, "cannot ipc non-cpow object"); JS_ReportError(cx, "cannot ipc non-cpow object");
return false; return false;
} }
*idp = idOf(obj); *objVarp = LocalObject(idOf(obj));
return true; return true;
} }
JSObject * JSObject *
JavaScriptParent::fromId(JSContext *cx, ObjectId objId) JavaScriptParent::fromObjectVariant(JSContext *cx, ObjectVariant objVar)
{ {
JS_ASSERT(objVar.type() == ObjectVariant::TRemoteObject);
ObjectId objId = objVar.get_RemoteObject().id();
RootedObject obj(cx, findCPOWById(objId)); RootedObject obj(cx, findCPOWById(objId));
if (obj) { if (obj) {
if (!JS_WrapObject(cx, &obj)) if (!JS_WrapObject(cx, &obj))

View File

@ -30,8 +30,8 @@ class JavaScriptParent : public JavaScriptBase<PJavaScriptParent>
CloneProtocol(Channel* aChannel, ProtocolCloneContext* aCtx) MOZ_OVERRIDE; CloneProtocol(Channel* aChannel, ProtocolCloneContext* aCtx) MOZ_OVERRIDE;
private: private:
JSObject *fromId(JSContext *cx, ObjectId objId); virtual bool toObjectVariant(JSContext *cx, JSObject *obj, ObjectVariant *objVarp);
bool toId(JSContext *cx, JSObject *obj, ObjectId *idp); virtual JSObject *fromObjectVariant(JSContext *cx, ObjectVariant objVar);
private: private:
uintptr_t refcount_; uintptr_t refcount_;

View File

@ -194,10 +194,10 @@ JavaScriptShared::toVariant(JSContext *cx, JS::HandleValue from, JSVariant *to)
return true; return true;
} }
ObjectId id; ObjectVariant objVar;
if (!toId(cx, obj, &id)) if (!toObjectVariant(cx, obj, &objVar))
return false; return false;
*to = ObjectVariant(id); *to = objVar;
return true; return true;
} }
@ -241,8 +241,7 @@ JavaScriptShared::fromVariant(JSContext *cx, const JSVariant &from, MutableHandl
case JSVariant::TObjectVariant: case JSVariant::TObjectVariant:
{ {
ObjectId id = from.get_ObjectVariant().id(); JSObject *obj = fromObjectVariant(cx, from.get_ObjectVariant());
JSObject *obj = fromId(cx, id);
if (!obj) if (!obj)
return false; return false;
to.set(ObjectValue(*obj)); to.set(ObjectValue(*obj));
@ -319,9 +318,9 @@ JavaScriptShared::ConvertID(const JSIID &from, nsID *to)
to->m3[7] = from.m3_7(); to->m3[7] = from.m3_7();
} }
static const uint32_t DefaultPropertyOp = 1; static const uint64_t DefaultPropertyOp = 1;
static const uint32_t GetterOnlyPropertyStub = 2; static const uint64_t GetterOnlyPropertyStub = 2;
static const uint32_t UnknownPropertyOp = 3; static const uint64_t UnknownPropertyOp = 3;
bool bool
JavaScriptShared::fromDescriptor(JSContext *cx, Handle<JSPropertyDescriptor> desc, JavaScriptShared::fromDescriptor(JSContext *cx, Handle<JSPropertyDescriptor> desc,
@ -331,15 +330,18 @@ JavaScriptShared::fromDescriptor(JSContext *cx, Handle<JSPropertyDescriptor> des
if (!toVariant(cx, desc.value(), &out->value())) if (!toVariant(cx, desc.value(), &out->value()))
return false; return false;
if (!toId(cx, desc.object(), &out->objId())) JS_ASSERT(desc.object());
if (!toObjectVariant(cx, desc.object(), &out->obj()))
return false; return false;
if (!desc.getter()) { if (!desc.getter()) {
out->getter() = 0; out->getter() = 0;
} else if (desc.hasGetterObject()) { } else if (desc.hasGetterObject()) {
JSObject *getter = desc.getterObject(); JSObject *getter = desc.getterObject();
if (!toId(cx, getter, &out->getter())) ObjectVariant objVar;
if (!toObjectVariant(cx, getter, &objVar))
return false; return false;
out->getter() = objVar;
} else { } else {
if (desc.getter() == JS_PropertyStub) if (desc.getter() == JS_PropertyStub)
out->getter() = DefaultPropertyOp; out->getter() = DefaultPropertyOp;
@ -351,8 +353,10 @@ JavaScriptShared::fromDescriptor(JSContext *cx, Handle<JSPropertyDescriptor> des
out->setter() = 0; out->setter() = 0;
} else if (desc.hasSetterObject()) { } else if (desc.hasSetterObject()) {
JSObject *setter = desc.setterObject(); JSObject *setter = desc.setterObject();
if (!toId(cx, setter, &out->setter())) ObjectVariant objVar;
if (!toObjectVariant(cx, setter, &objVar))
return false; return false;
out->setter() = objVar;
} else { } else {
if (desc.setter() == JS_StrictPropertyStub) if (desc.setter() == JS_StrictPropertyStub)
out->setter() = DefaultPropertyOp; out->setter() = DefaultPropertyOp;
@ -387,35 +391,38 @@ JavaScriptShared::toDescriptor(JSContext *cx, const PPropertyDescriptor &in,
if (!fromVariant(cx, in.value(), out.value())) if (!fromVariant(cx, in.value(), out.value()))
return false; return false;
Rooted<JSObject*> obj(cx); Rooted<JSObject*> obj(cx);
if (!fromId(cx, in.objId(), &obj)) obj = fromObjectVariant(cx, in.obj());
if (!obj)
return false; return false;
out.object().set(obj); out.object().set(obj);
if (!in.getter()) { if (in.getter().type() == GetterSetter::Tuint64_t && !in.getter().get_uint64_t()) {
out.setGetter(nullptr); out.setGetter(nullptr);
} else if (in.attrs() & JSPROP_GETTER) { } else if (in.attrs() & JSPROP_GETTER) {
Rooted<JSObject*> getter(cx); Rooted<JSObject*> getter(cx);
if (!fromId(cx, in.getter(), &getter)) getter = fromObjectVariant(cx, in.getter().get_ObjectVariant());
if (!getter)
return false; return false;
out.setGetter(JS_DATA_TO_FUNC_PTR(JSPropertyOp, getter.get())); out.setGetter(JS_DATA_TO_FUNC_PTR(JSPropertyOp, getter.get()));
} else { } else {
if (in.getter() == DefaultPropertyOp) if (in.getter().get_uint64_t() == DefaultPropertyOp)
out.setGetter(JS_PropertyStub); out.setGetter(JS_PropertyStub);
else else
out.setGetter(UnknownPropertyStub); out.setGetter(UnknownPropertyStub);
} }
if (!in.setter()) { if (in.setter().type() == GetterSetter::Tuint64_t && !in.setter().get_uint64_t()) {
out.setSetter(nullptr); out.setSetter(nullptr);
} else if (in.attrs() & JSPROP_SETTER) { } else if (in.attrs() & JSPROP_SETTER) {
Rooted<JSObject*> setter(cx); Rooted<JSObject*> setter(cx);
if (!fromId(cx, in.setter(), &setter)) setter = fromObjectVariant(cx, in.setter().get_ObjectVariant());
if (!setter)
return false; return false;
out.setSetter(JS_DATA_TO_FUNC_PTR(JSStrictPropertyOp, setter.get())); out.setSetter(JS_DATA_TO_FUNC_PTR(JSStrictPropertyOp, setter.get()));
} else { } else {
if (in.setter() == DefaultPropertyOp) if (in.setter().get_uint64_t() == DefaultPropertyOp)
out.setSetter(JS_StrictPropertyStub); out.setSetter(JS_StrictPropertyStub);
else if (in.setter() == GetterOnlyPropertyStub) else if (in.setter().get_uint64_t() == GetterOnlyPropertyStub)
out.setSetter(js_GetterOnlyPropertyStub); out.setSetter(js_GetterOnlyPropertyStub);
else else
out.setSetter(UnknownStrictPropertyStub); out.setSetter(UnknownStrictPropertyStub);

View File

@ -103,18 +103,8 @@ class JavaScriptShared
bool convertIdToGeckoString(JSContext *cx, JS::HandleId id, nsString *to); bool convertIdToGeckoString(JSContext *cx, JS::HandleId id, nsString *to);
bool convertGeckoStringToId(JSContext *cx, const nsString &from, JS::MutableHandleId id); bool convertGeckoStringToId(JSContext *cx, const nsString &from, JS::MutableHandleId id);
virtual bool toId(JSContext *cx, JSObject *obj, ObjectId *idp) = 0; virtual bool toObjectVariant(JSContext *cx, JSObject *obj, ObjectVariant *objVarp) = 0;
virtual JSObject *fromId(JSContext *cx, ObjectId id) = 0; virtual JSObject *fromObjectVariant(JSContext *cx, ObjectVariant objVar) = 0;
bool fromId(JSContext *cx, ObjectId id, JS::MutableHandle<JSObject*> objp) {
if (!id) {
objp.set(nullptr);
return true;
}
objp.set(fromId(cx, id));
return bool(objp.get());
}
static void ConvertID(const nsID &from, JSIID *to); static void ConvertID(const nsID &from, JSIID *to);
static void ConvertID(const JSIID &from, nsID *to); static void ConvertID(const JSIID &from, nsID *to);

View File

@ -27,11 +27,22 @@ struct JSIID
uint8_t m3_7; uint8_t m3_7;
}; };
struct ObjectVariant struct LocalObject
{ {
uint64_t id; uint64_t id;
}; };
struct RemoteObject
{
uint64_t id;
};
union ObjectVariant
{
LocalObject;
RemoteObject;
};
struct UndefinedVariant {}; struct UndefinedVariant {};
struct NullVariant {}; struct NullVariant {};
@ -72,11 +83,17 @@ union JSParam
JSVariant; /* actual value to pass through */ JSVariant; /* actual value to pass through */
}; };
union GetterSetter
{
uint64_t;
ObjectVariant;
};
struct PPropertyDescriptor struct PPropertyDescriptor
{ {
uint64_t objId; ObjectVariant obj;
uint32_t attrs; uint32_t attrs;
JSVariant value; JSVariant value;
// How to interpret these values depends on whether JSPROP_GETTER/SETTER // How to interpret these values depends on whether JSPROP_GETTER/SETTER
// are set. If set, the corresponding value is a CPOW or 0 for NULL. // are set. If set, the corresponding value is a CPOW or 0 for NULL.
@ -86,8 +103,8 @@ struct PPropertyDescriptor
// 1 - Default getter or setter. // 1 - Default getter or setter.
// 2 - js_GetterOnlyPropertyStub (setter only) // 2 - js_GetterOnlyPropertyStub (setter only)
// 3 - Unknown // 3 - Unknown
uint64_t getter; GetterSetter getter;
uint64_t setter; GetterSetter setter;
}; };
struct CpowEntry struct CpowEntry