Bug 899804 - Make CPOWs handle instanceof with WebIDL interfaces (r=bz,dvander)

This commit is contained in:
Bill McCloskey 2013-08-01 16:45:17 -07:00
parent a1314e3aef
commit 35518f5639
8 changed files with 92 additions and 2 deletions

View File

@ -7,6 +7,8 @@
#include <algorithm>
#include <stdarg.h>
#include "JavaScriptParent.h"
#include "prprf.h"
#include "mozilla/DebugOnly.h"
#include "mozilla/FloatingPoint.h"
@ -1746,6 +1748,17 @@ InterfaceHasInstance(JSContext* cx, JS::Handle<JSObject*> obj,
return true;
}
JS::Rooted<JSObject*> unwrapped(cx, js::CheckedUnwrap(instance, true));
if (unwrapped && jsipc::JavaScriptParent::IsCPOW(unwrapped)) {
bool boolp = false;
if (!jsipc::JavaScriptParent::DOMInstanceOf(unwrapped, clasp->mPrototypeID,
clasp->mDepth, &boolp)) {
return false;
}
*bp = boolp;
return true;
}
JS::Rooted<JS::Value> protov(cx);
DebugOnly<bool> ok = JS_GetProperty(cx, obj, "prototype", &protov);
MOZ_ASSERT(ok, "Someone messed with our prototype property?");
@ -1787,6 +1800,21 @@ InterfaceHasInstance(JSContext* cx, JS::Handle<JSObject*> obj, JS::MutableHandle
return InterfaceHasInstance(cx, obj, instanceObject, bp);
}
JSBool
InterfaceHasInstance(JSContext* cx, int prototypeID, int depth,
JS::Handle<JSObject*> instance,
JSBool* bp)
{
const DOMClass* domClass = GetDOMClass(js::UncheckedUnwrap(instance));
MOZ_ASSERT(!domClass || prototypeID != prototypes::id::_ID_Count,
"Why do we have a hasInstance hook if we don't have a prototype "
"ID?");
*bp = (domClass && domClass->mInterfaceChain[depth] == prototypeID);
return true;
}
bool
ReportLenientThisUnwrappingFailure(JSContext* cx, JS::Handle<JSObject*> obj)
{

View File

@ -2074,6 +2074,10 @@ InterfaceHasInstance(JSContext* cx, JS::Handle<JSObject*> obj,
JSBool
InterfaceHasInstance(JSContext* cx, JS::Handle<JSObject*> obj, JS::MutableHandle<JS::Value> vp,
JSBool* bp);
JSBool
InterfaceHasInstance(JSContext* cx, int prototypeID, int depth,
JS::Handle<JSObject*> instance,
JSBool* bp);
// Helper for lenient getters/setters to report to console. If this
// returns false, we couldn't even get a global.

View File

@ -74,6 +74,7 @@ endif
LOCAL_INCLUDES += -I$(topsrcdir)/js/xpconnect/src \
-I$(topsrcdir)/js/xpconnect/wrappers \
-I$(topsrcdir)/js/ipc \
-I$(topsrcdir)/content/canvas/src \
-I$(topsrcdir)/content/html/content/src \
-I$(topsrcdir)/media/webrtc/signaling/src/peerconnection \

View File

@ -7,6 +7,7 @@
#include "JavaScriptChild.h"
#include "mozilla/dom/ContentChild.h"
#include "mozilla/dom/BindingUtils.h"
#include "nsContentUtils.h"
#include "xpcprivate.h"
#include "jsfriendapi.h"
@ -625,3 +626,27 @@ JavaScriptChild::AnswerInstanceOf(const ObjectId &objId, const JSIID &iid, Retur
return ok(rs);
}
bool
JavaScriptChild::AnswerDOMInstanceOf(const ObjectId &objId, const int &prototypeID,
const int &depth,
ReturnStatus *rs, bool *instanceof)
{
AutoSafeJSContext cx;
JSAutoRequest request(cx);
*instanceof = false;
RootedObject obj(cx, findObject(objId));
if (!obj)
return false;
JSAutoCompartment comp(cx, obj);
JSBool tmp;
if (!mozilla::dom::InterfaceHasInstance(cx, prototypeID, depth, obj, &tmp))
return fail(cx, rs);
*instanceof = tmp;
return ok(rs);
}

View File

@ -66,6 +66,8 @@ class JavaScriptChild
ReturnStatus *rs, nsTArray<nsString> *names);
bool AnswerInstanceOf(const ObjectId &objId, const JSIID &iid,
ReturnStatus *rs, bool *instanceof);
bool AnswerDOMInstanceOf(const ObjectId &objId, const int &prototypeID, const int &depth,
ReturnStatus *rs, bool *instanceof);
protected:
JSObject *unwrap(JSContext *cx, ObjectId id);

View File

@ -514,7 +514,8 @@ JavaScriptParent::init()
bool
JavaScriptParent::makeId(JSContext *cx, JSObject *obj, ObjectId *idp)
{
if (!IsProxy(obj) || GetProxyHandler(obj) != &CPOWProxyHandler::singleton) {
obj = js::CheckedUnwrap(obj, false);
if (!obj || !IsProxy(obj) || GetProxyHandler(obj) != &CPOWProxyHandler::singleton) {
JS_ReportError(cx, "cannot ipc non-cpow object");
return false;
}
@ -656,3 +657,24 @@ JavaScriptParent::instanceOf(JSObject *obj, const nsID *id, bool *bp)
return NS_OK;
}
/* static */ bool
JavaScriptParent::DOMInstanceOf(JSObject *obj, int prototypeID, int depth, bool *bp)
{
return ParentOf(obj)->domInstanceOf(obj, prototypeID, depth, bp);
}
bool
JavaScriptParent::domInstanceOf(JSObject *obj, int prototypeID, int depth, bool *bp)
{
ObjectId objId = idOf(obj);
ReturnStatus status;
if (!CallDOMInstanceOf(objId, prototypeID, depth, &status, bp))
return false;
if (!status.ok())
return false;
return true;
}

View File

@ -66,10 +66,17 @@ class JavaScriptParent
void drop(JSObject *obj);
static bool IsCPOW(JSObject *obj);
static nsresult InstanceOf(JSObject *obj, const nsID *id, bool *bp);
static nsresult InstanceOf(JSObject *obj, const nsID *id, bool *bp);
nsresult instanceOf(JSObject *obj, const nsID *id, bool *bp);
/*
* Check that |obj| is a DOM wrapper whose prototype chain contains
* |prototypeID| at depth |depth|.
*/
static bool DOMInstanceOf(JSObject *obj, int prototypeID, int depth, bool *bp);
bool domInstanceOf(JSObject *obj, int prototypeID, int depth, bool *bp);
protected:
JSObject *unwrap(JSContext *cx, ObjectId objId);

View File

@ -41,6 +41,7 @@ child:
urgent GetPropertyNames(uint64_t objId, uint32_t flags) returns (ReturnStatus rs, nsString[] names);
urgent InstanceOf(uint64_t objId, JSIID iid) returns (ReturnStatus rs, bool instanceof);
urgent DOMInstanceOf(uint64_t objId, int prototypeID, int depth) returns (ReturnStatus rs, bool instanceof);
parent:
async __delete__();