Bug 996785 - Move CPOW wrapper owner code (r=mrbkap)
This commit is contained in:
103
js/ipc/JavaScriptBase.h
Normal file
103
js/ipc/JavaScriptBase.h
Normal file
@@ -0,0 +1,103 @@
|
|||||||
|
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||||
|
* vim: set ts=8 sw=4 et tw=80:
|
||||||
|
*
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
#ifndef mozilla_jsipc_JavaScriptBase_h__
|
||||||
|
#define mozilla_jsipc_JavaScriptBase_h__
|
||||||
|
|
||||||
|
#include "WrapperOwner.h"
|
||||||
|
#include "mozilla/dom/DOMTypes.h"
|
||||||
|
#include "mozilla/jsipc/PJavaScript.h"
|
||||||
|
|
||||||
|
namespace mozilla {
|
||||||
|
namespace jsipc {
|
||||||
|
|
||||||
|
template<class Base>
|
||||||
|
class JavaScriptBase : public WrapperOwner, public Base
|
||||||
|
{
|
||||||
|
typedef WrapperOwner Shared;
|
||||||
|
|
||||||
|
public:
|
||||||
|
/*** Dummy call handlers ***/
|
||||||
|
|
||||||
|
bool CallPreventExtensions(const ObjectId &objId, ReturnStatus *rs) {
|
||||||
|
return Base::CallPreventExtensions(objId, rs);
|
||||||
|
}
|
||||||
|
bool CallGetPropertyDescriptor(const ObjectId &objId, const nsString &id,
|
||||||
|
ReturnStatus *rs,
|
||||||
|
PPropertyDescriptor *out) {
|
||||||
|
return Base::CallGetPropertyDescriptor(objId, id, rs, out);
|
||||||
|
}
|
||||||
|
bool CallGetOwnPropertyDescriptor(const ObjectId &objId,
|
||||||
|
const nsString &id,
|
||||||
|
ReturnStatus *rs,
|
||||||
|
PPropertyDescriptor *out) {
|
||||||
|
return Base::CallGetOwnPropertyDescriptor(objId, id, rs, out);
|
||||||
|
}
|
||||||
|
bool CallDefineProperty(const ObjectId &objId, const nsString &id,
|
||||||
|
const PPropertyDescriptor &flags,
|
||||||
|
ReturnStatus *rs) {
|
||||||
|
return Base::CallDefineProperty(objId, id, flags, rs);
|
||||||
|
}
|
||||||
|
bool CallDelete(const ObjectId &objId, const nsString &id,
|
||||||
|
ReturnStatus *rs, bool *success) {
|
||||||
|
return Base::CallDelete(objId, id, rs, success);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CallHas(const ObjectId &objId, const nsString &id,
|
||||||
|
ReturnStatus *rs, bool *bp) {
|
||||||
|
return Base::CallHas(objId, id, rs, bp);
|
||||||
|
}
|
||||||
|
bool CallHasOwn(const ObjectId &objId, const nsString &id,
|
||||||
|
ReturnStatus *rs, bool *bp) {
|
||||||
|
return Base::CallHasOwn(objId, id, rs, bp);
|
||||||
|
}
|
||||||
|
bool CallGet(const ObjectId &objId, const ObjectId &receiverId,
|
||||||
|
const nsString &id,
|
||||||
|
ReturnStatus *rs, JSVariant *result) {
|
||||||
|
return Base::CallGet(objId, receiverId, id, rs, result);
|
||||||
|
}
|
||||||
|
bool CallSet(const ObjectId &objId, const ObjectId &receiverId,
|
||||||
|
const nsString &id, const bool &strict,
|
||||||
|
const JSVariant &value, ReturnStatus *rs, JSVariant *result) {
|
||||||
|
return Base::CallSet(objId, receiverId, id, strict, value, rs, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CallIsExtensible(const ObjectId &objId, ReturnStatus *rs,
|
||||||
|
bool *result) {
|
||||||
|
return Base::CallIsExtensible(objId, rs, result);
|
||||||
|
}
|
||||||
|
bool CallCall(const ObjectId &objId, const nsTArray<JSParam> &argv,
|
||||||
|
ReturnStatus *rs, JSVariant *result,
|
||||||
|
nsTArray<JSParam> *outparams) {
|
||||||
|
return Base::CallCall(objId, argv, rs, result, outparams);
|
||||||
|
}
|
||||||
|
bool CallObjectClassIs(const ObjectId &objId, const uint32_t &classValue,
|
||||||
|
bool *result) {
|
||||||
|
return Base::CallObjectClassIs(objId, classValue, result);
|
||||||
|
}
|
||||||
|
bool CallClassName(const ObjectId &objId, nsString *result) {
|
||||||
|
return Base::CallClassName(objId, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CallGetPropertyNames(const ObjectId &objId, const uint32_t &flags,
|
||||||
|
ReturnStatus *rs, nsTArray<nsString> *names) {
|
||||||
|
return Base::CallGetPropertyNames(objId, flags, rs, names);
|
||||||
|
}
|
||||||
|
bool CallInstanceOf(const ObjectId &objId, const JSIID &iid,
|
||||||
|
ReturnStatus *rs, bool *instanceof) {
|
||||||
|
return Base::CallInstanceOf(objId, iid, rs, instanceof);
|
||||||
|
}
|
||||||
|
bool CallDOMInstanceOf(const ObjectId &objId, const int &prototypeID, const int &depth,
|
||||||
|
ReturnStatus *rs, bool *instanceof) {
|
||||||
|
return Base::CallDOMInstanceOf(objId, prototypeID, depth, rs, instanceof);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace jsipc
|
||||||
|
} // namespace mozilla
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -22,496 +22,17 @@ using namespace mozilla::jsipc;
|
|||||||
using namespace mozilla::dom;
|
using namespace mozilla::dom;
|
||||||
|
|
||||||
JavaScriptParent::JavaScriptParent()
|
JavaScriptParent::JavaScriptParent()
|
||||||
: refcount_(1),
|
: refcount_(1)
|
||||||
inactive_(false)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline JavaScriptParent *
|
|
||||||
ParentOf(JSObject *obj)
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(IsCPOW(obj));
|
|
||||||
return reinterpret_cast<JavaScriptParent *>(GetProxyExtra(obj, 0).toPrivate());
|
|
||||||
}
|
|
||||||
|
|
||||||
ObjectId
|
|
||||||
JavaScriptParent::idOf(JSObject *obj)
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(IsCPOW(obj));
|
|
||||||
|
|
||||||
Value v = GetProxyExtra(obj, 1);
|
|
||||||
MOZ_ASSERT(v.isDouble());
|
|
||||||
|
|
||||||
ObjectId objId = BitwiseCast<uint64_t>(v.toDouble());
|
|
||||||
MOZ_ASSERT(findCPOWById(objId) == obj);
|
|
||||||
MOZ_ASSERT(objId);
|
|
||||||
|
|
||||||
return objId;
|
|
||||||
}
|
|
||||||
|
|
||||||
int sCPOWProxyHandler;
|
|
||||||
|
|
||||||
class CPOWProxyHandler : public BaseProxyHandler
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
CPOWProxyHandler()
|
|
||||||
: BaseProxyHandler(&sCPOWProxyHandler) {}
|
|
||||||
virtual ~CPOWProxyHandler() {}
|
|
||||||
|
|
||||||
virtual bool finalizeInBackground(Value priv) MOZ_OVERRIDE {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual bool preventExtensions(JSContext *cx, HandleObject proxy) MOZ_OVERRIDE;
|
|
||||||
virtual bool getPropertyDescriptor(JSContext *cx, HandleObject proxy, HandleId id,
|
|
||||||
MutableHandle<JSPropertyDescriptor> desc) MOZ_OVERRIDE;
|
|
||||||
virtual bool getOwnPropertyDescriptor(JSContext *cx, HandleObject proxy, HandleId id,
|
|
||||||
MutableHandle<JSPropertyDescriptor> desc) MOZ_OVERRIDE;
|
|
||||||
virtual bool defineProperty(JSContext *cx, HandleObject proxy, HandleId id,
|
|
||||||
MutableHandle<JSPropertyDescriptor> desc) MOZ_OVERRIDE;
|
|
||||||
virtual bool getOwnPropertyNames(JSContext *cx, HandleObject proxy,
|
|
||||||
AutoIdVector &props) MOZ_OVERRIDE;
|
|
||||||
virtual bool delete_(JSContext *cx, HandleObject proxy, HandleId id, bool *bp) MOZ_OVERRIDE;
|
|
||||||
virtual bool enumerate(JSContext *cx, HandleObject proxy, AutoIdVector &props) MOZ_OVERRIDE;
|
|
||||||
|
|
||||||
virtual bool has(JSContext *cx, HandleObject proxy, HandleId id, bool *bp) MOZ_OVERRIDE;
|
|
||||||
virtual bool hasOwn(JSContext *cx, HandleObject proxy, HandleId id, bool *bp) MOZ_OVERRIDE;
|
|
||||||
virtual bool get(JSContext *cx, HandleObject proxy, HandleObject receiver,
|
|
||||||
HandleId id, MutableHandleValue vp) MOZ_OVERRIDE;
|
|
||||||
virtual bool set(JSContext *cx, JS::HandleObject proxy, JS::HandleObject receiver,
|
|
||||||
JS::HandleId id, bool strict, JS::MutableHandleValue vp) MOZ_OVERRIDE;
|
|
||||||
virtual bool keys(JSContext *cx, HandleObject proxy, AutoIdVector &props) MOZ_OVERRIDE;
|
|
||||||
|
|
||||||
virtual bool isExtensible(JSContext *cx, HandleObject proxy, bool *extensible) MOZ_OVERRIDE;
|
|
||||||
virtual bool call(JSContext *cx, HandleObject proxy, const CallArgs &args) MOZ_OVERRIDE;
|
|
||||||
virtual bool objectClassIs(HandleObject obj, js::ESClassValue classValue, JSContext *cx) MOZ_OVERRIDE;
|
|
||||||
virtual const char* className(JSContext *cx, HandleObject proxy) MOZ_OVERRIDE;
|
|
||||||
virtual void finalize(JSFreeOp *fop, JSObject *proxy) MOZ_OVERRIDE;
|
|
||||||
|
|
||||||
static CPOWProxyHandler singleton;
|
|
||||||
};
|
|
||||||
|
|
||||||
CPOWProxyHandler CPOWProxyHandler::singleton;
|
|
||||||
|
|
||||||
#define FORWARD(call, args) \
|
|
||||||
JavaScriptParent *parent = ParentOf(proxy); \
|
|
||||||
if (!parent->active()) { \
|
|
||||||
JS_ReportError(cx, "cannot use a CPOW whose process is gone"); \
|
|
||||||
return false; \
|
|
||||||
} \
|
|
||||||
return parent->call args;
|
|
||||||
|
|
||||||
bool
|
|
||||||
CPOWProxyHandler::preventExtensions(JSContext *cx, HandleObject proxy)
|
|
||||||
{
|
|
||||||
FORWARD(preventExtensions, (cx, proxy));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
JavaScriptParent::preventExtensions(JSContext *cx, HandleObject proxy)
|
|
||||||
{
|
|
||||||
ObjectId objId = idOf(proxy);
|
|
||||||
|
|
||||||
ReturnStatus status;
|
|
||||||
if (!CallPreventExtensions(objId, &status))
|
|
||||||
return ipcfail(cx);
|
|
||||||
|
|
||||||
return ok(cx, status);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
CPOWProxyHandler::getPropertyDescriptor(JSContext *cx, HandleObject proxy, HandleId id,
|
|
||||||
MutableHandle<JSPropertyDescriptor> desc)
|
|
||||||
{
|
|
||||||
FORWARD(getPropertyDescriptor, (cx, proxy, id, desc));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
JavaScriptParent::getPropertyDescriptor(JSContext *cx, HandleObject proxy, HandleId id,
|
|
||||||
MutableHandle<JSPropertyDescriptor> desc)
|
|
||||||
{
|
|
||||||
ObjectId objId = idOf(proxy);
|
|
||||||
|
|
||||||
nsString idstr;
|
|
||||||
if (!convertIdToGeckoString(cx, id, &idstr))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
ReturnStatus status;
|
|
||||||
PPropertyDescriptor result;
|
|
||||||
if (!CallGetPropertyDescriptor(objId, idstr, &status, &result))
|
|
||||||
return ipcfail(cx);
|
|
||||||
if (!ok(cx, status))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return toDescriptor(cx, result, desc);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
CPOWProxyHandler::getOwnPropertyDescriptor(JSContext *cx, HandleObject proxy,
|
|
||||||
HandleId id, MutableHandle<JSPropertyDescriptor> desc)
|
|
||||||
{
|
|
||||||
FORWARD(getOwnPropertyDescriptor, (cx, proxy, id, desc));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
JavaScriptParent::getOwnPropertyDescriptor(JSContext *cx, HandleObject proxy, HandleId id,
|
|
||||||
MutableHandle<JSPropertyDescriptor> desc)
|
|
||||||
{
|
|
||||||
ObjectId objId = idOf(proxy);
|
|
||||||
|
|
||||||
nsString idstr;
|
|
||||||
if (!convertIdToGeckoString(cx, id, &idstr))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
ReturnStatus status;
|
|
||||||
PPropertyDescriptor result;
|
|
||||||
if (!CallGetOwnPropertyDescriptor(objId, idstr, &status, &result))
|
|
||||||
return ipcfail(cx);
|
|
||||||
if (!ok(cx, status))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return toDescriptor(cx, result, desc);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
CPOWProxyHandler::defineProperty(JSContext *cx, HandleObject proxy, HandleId id,
|
|
||||||
MutableHandle<JSPropertyDescriptor> desc)
|
|
||||||
{
|
|
||||||
FORWARD(defineProperty, (cx, proxy, id, desc));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
JavaScriptParent::defineProperty(JSContext *cx, HandleObject proxy, HandleId id,
|
|
||||||
MutableHandle<JSPropertyDescriptor> desc)
|
|
||||||
{
|
|
||||||
ObjectId objId = idOf(proxy);
|
|
||||||
|
|
||||||
nsString idstr;
|
|
||||||
if (!convertIdToGeckoString(cx, id, &idstr))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
PPropertyDescriptor descriptor;
|
|
||||||
if (!fromDescriptor(cx, desc, &descriptor))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
ReturnStatus status;
|
|
||||||
if (!CallDefineProperty(objId, idstr, descriptor, &status))
|
|
||||||
return ipcfail(cx);
|
|
||||||
|
|
||||||
return ok(cx, status);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
CPOWProxyHandler::getOwnPropertyNames(JSContext *cx, HandleObject proxy, AutoIdVector &props)
|
|
||||||
{
|
|
||||||
FORWARD(getOwnPropertyNames, (cx, proxy, props));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
JavaScriptParent::getOwnPropertyNames(JSContext *cx, HandleObject proxy, AutoIdVector &props)
|
|
||||||
{
|
|
||||||
return getPropertyNames(cx, proxy, JSITER_OWNONLY | JSITER_HIDDEN, props);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
CPOWProxyHandler::delete_(JSContext *cx, HandleObject proxy, HandleId id, bool *bp)
|
|
||||||
{
|
|
||||||
FORWARD(delete_, (cx, proxy, id, bp));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
JavaScriptParent::delete_(JSContext *cx, HandleObject proxy, HandleId id, bool *bp)
|
|
||||||
{
|
|
||||||
ObjectId objId = idOf(proxy);
|
|
||||||
|
|
||||||
nsString idstr;
|
|
||||||
if (!convertIdToGeckoString(cx, id, &idstr))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
ReturnStatus status;
|
|
||||||
if (!CallDelete(objId, idstr, &status, bp))
|
|
||||||
return ipcfail(cx);
|
|
||||||
|
|
||||||
return ok(cx, status);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
CPOWProxyHandler::enumerate(JSContext *cx, HandleObject proxy, AutoIdVector &props)
|
|
||||||
{
|
|
||||||
FORWARD(enumerate, (cx, proxy, props));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
JavaScriptParent::enumerate(JSContext *cx, HandleObject proxy, AutoIdVector &props)
|
|
||||||
{
|
|
||||||
return getPropertyNames(cx, proxy, 0, props);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
CPOWProxyHandler::has(JSContext *cx, HandleObject proxy, HandleId id, bool *bp)
|
|
||||||
{
|
|
||||||
FORWARD(has, (cx, proxy, id, bp));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
JavaScriptParent::has(JSContext *cx, HandleObject proxy, HandleId id, bool *bp)
|
|
||||||
{
|
|
||||||
ObjectId objId = idOf(proxy);
|
|
||||||
|
|
||||||
nsString idstr;
|
|
||||||
if (!convertIdToGeckoString(cx, id, &idstr))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
ReturnStatus status;
|
|
||||||
if (!CallHas(objId, idstr, &status, bp))
|
|
||||||
return ipcfail(cx);
|
|
||||||
|
|
||||||
return ok(cx, status);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
CPOWProxyHandler::hasOwn(JSContext *cx, HandleObject proxy, HandleId id, bool *bp)
|
|
||||||
{
|
|
||||||
FORWARD(hasOwn, (cx, proxy, id, bp));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
JavaScriptParent::hasOwn(JSContext *cx, HandleObject proxy, HandleId id, bool *bp)
|
|
||||||
{
|
|
||||||
ObjectId objId = idOf(proxy);
|
|
||||||
|
|
||||||
nsString idstr;
|
|
||||||
if (!convertIdToGeckoString(cx, id, &idstr))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
ReturnStatus status;
|
|
||||||
if (!CallHasOwn(objId, idstr, &status, bp))
|
|
||||||
return ipcfail(cx);
|
|
||||||
|
|
||||||
return !!ok(cx, status);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
CPOWProxyHandler::get(JSContext *cx, HandleObject proxy, HandleObject receiver,
|
|
||||||
HandleId id, MutableHandleValue vp)
|
|
||||||
{
|
|
||||||
FORWARD(get, (cx, proxy, receiver, id, vp));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
JavaScriptParent::get(JSContext *cx, HandleObject proxy, HandleObject receiver,
|
|
||||||
HandleId id, MutableHandleValue vp)
|
|
||||||
{
|
|
||||||
ObjectId objId = idOf(proxy);
|
|
||||||
ObjectId receiverId = idOf(receiver);
|
|
||||||
|
|
||||||
nsString idstr;
|
|
||||||
if (!convertIdToGeckoString(cx, id, &idstr))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
JSVariant val;
|
|
||||||
ReturnStatus status;
|
|
||||||
if (!CallGet(objId, receiverId, idstr, &status, &val))
|
|
||||||
return ipcfail(cx);
|
|
||||||
|
|
||||||
if (!ok(cx, status))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return fromVariant(cx, val, vp);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
CPOWProxyHandler::set(JSContext *cx, JS::HandleObject proxy, JS::HandleObject receiver,
|
|
||||||
JS::HandleId id, bool strict, JS::MutableHandleValue vp)
|
|
||||||
{
|
|
||||||
FORWARD(set, (cx, proxy, receiver, id, strict, vp));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
JavaScriptParent::set(JSContext *cx, JS::HandleObject proxy, JS::HandleObject receiver,
|
|
||||||
JS::HandleId id, bool strict, JS::MutableHandleValue vp)
|
|
||||||
{
|
|
||||||
ObjectId objId = idOf(proxy);
|
|
||||||
ObjectId receiverId = idOf(receiver);
|
|
||||||
|
|
||||||
nsString idstr;
|
|
||||||
if (!convertIdToGeckoString(cx, id, &idstr))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
JSVariant val;
|
|
||||||
if (!toVariant(cx, vp, &val))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
ReturnStatus status;
|
|
||||||
JSVariant result;
|
|
||||||
if (!CallSet(objId, receiverId, idstr, strict, val, &status, &result))
|
|
||||||
return ipcfail(cx);
|
|
||||||
|
|
||||||
if (!ok(cx, status))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return fromVariant(cx, result, vp);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
CPOWProxyHandler::keys(JSContext *cx, HandleObject proxy, AutoIdVector &props)
|
|
||||||
{
|
|
||||||
FORWARD(keys, (cx, proxy, props));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
JavaScriptParent::keys(JSContext *cx, HandleObject proxy, AutoIdVector &props)
|
|
||||||
{
|
|
||||||
return getPropertyNames(cx, proxy, JSITER_OWNONLY, props);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
CPOWProxyHandler::isExtensible(JSContext *cx, HandleObject proxy, bool *extensible)
|
|
||||||
{
|
|
||||||
FORWARD(isExtensible, (cx, proxy, extensible));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
JavaScriptParent::isExtensible(JSContext *cx, HandleObject proxy, bool *extensible)
|
|
||||||
{
|
|
||||||
ObjectId objId = idOf(proxy);
|
|
||||||
|
|
||||||
ReturnStatus status;
|
|
||||||
if (!CallIsExtensible(objId, &status, extensible))
|
|
||||||
return ipcfail(cx);
|
|
||||||
|
|
||||||
return ok(cx, status);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
CPOWProxyHandler::call(JSContext *cx, HandleObject proxy, const CallArgs &args)
|
|
||||||
{
|
|
||||||
FORWARD(call, (cx, proxy, args));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
JavaScriptParent::call(JSContext *cx, HandleObject proxy, const CallArgs &args)
|
|
||||||
{
|
|
||||||
ObjectId objId = idOf(proxy);
|
|
||||||
|
|
||||||
InfallibleTArray<JSParam> vals;
|
|
||||||
AutoValueVector outobjects(cx);
|
|
||||||
|
|
||||||
RootedValue v(cx);
|
|
||||||
for (size_t i = 0; i < args.length() + 2; i++) {
|
|
||||||
v = args.base()[i];
|
|
||||||
if (v.isObject()) {
|
|
||||||
RootedObject obj(cx, &v.toObject());
|
|
||||||
if (xpc::IsOutObject(cx, obj)) {
|
|
||||||
// Make sure it is not an in-out object.
|
|
||||||
bool found;
|
|
||||||
if (!JS_HasProperty(cx, obj, "value", &found))
|
|
||||||
return false;
|
|
||||||
if (found) {
|
|
||||||
JS_ReportError(cx, "in-out objects cannot be sent via CPOWs yet");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
vals.AppendElement(JSParam(void_t()));
|
|
||||||
if (!outobjects.append(ObjectValue(*obj)))
|
|
||||||
return false;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
JSVariant val;
|
|
||||||
if (!toVariant(cx, v, &val))
|
|
||||||
return false;
|
|
||||||
vals.AppendElement(JSParam(val));
|
|
||||||
}
|
|
||||||
|
|
||||||
JSVariant result;
|
|
||||||
ReturnStatus status;
|
|
||||||
InfallibleTArray<JSParam> outparams;
|
|
||||||
if (!CallCall(objId, vals, &status, &result, &outparams))
|
|
||||||
return ipcfail(cx);
|
|
||||||
if (!ok(cx, status))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (outparams.Length() != outobjects.length())
|
|
||||||
return ipcfail(cx);
|
|
||||||
|
|
||||||
RootedObject obj(cx);
|
|
||||||
for (size_t i = 0; i < outparams.Length(); i++) {
|
|
||||||
// Don't bother doing anything for outparams that weren't set.
|
|
||||||
if (outparams[i].type() == JSParam::Tvoid_t)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// Take the value the child process returned, and set it on the XPC
|
|
||||||
// object.
|
|
||||||
if (!fromVariant(cx, outparams[i], &v))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
obj = &outobjects[i].toObject();
|
|
||||||
if (!JS_SetProperty(cx, obj, "value", v))
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!fromVariant(cx, result, args.rval()))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool
|
|
||||||
CPOWProxyHandler::objectClassIs(HandleObject proxy, js::ESClassValue classValue, JSContext *cx)
|
|
||||||
{
|
|
||||||
FORWARD(objectClassIs, (cx, proxy, classValue));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
JavaScriptParent::objectClassIs(JSContext *cx, HandleObject proxy, js::ESClassValue classValue)
|
|
||||||
{
|
|
||||||
ObjectId objId = idOf(proxy);
|
|
||||||
|
|
||||||
// This function is assumed infallible, so we just return false if the IPC
|
|
||||||
// channel fails.
|
|
||||||
bool result;
|
|
||||||
if (!CallObjectClassIs(objId, classValue, &result))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *
|
|
||||||
CPOWProxyHandler::className(JSContext *cx, HandleObject proxy)
|
|
||||||
{
|
|
||||||
JavaScriptParent *parent = ParentOf(proxy);
|
|
||||||
if (!parent->active())
|
|
||||||
return "<dead CPOW>";
|
|
||||||
return parent->className(cx, proxy);
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *
|
|
||||||
JavaScriptParent::className(JSContext *cx, HandleObject proxy)
|
|
||||||
{
|
|
||||||
ObjectId objId = idOf(proxy);
|
|
||||||
|
|
||||||
nsString name;
|
|
||||||
if (!CallClassName(objId, &name))
|
|
||||||
return "<error>";
|
|
||||||
|
|
||||||
return ToNewCString(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
CPOWProxyHandler::finalize(JSFreeOp *fop, JSObject *proxy)
|
|
||||||
{
|
|
||||||
ParentOf(proxy)->drop(proxy);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
JavaScriptParent::drop(JSObject *obj)
|
JavaScriptParent::drop(JSObject *obj)
|
||||||
{
|
{
|
||||||
ObjectId objId = idOf(obj);
|
ObjectId objId = idOf(obj);
|
||||||
|
|
||||||
cpows_.remove(objId);
|
cpows_.remove(objId);
|
||||||
if (!inactive_ && !SendDropObject(objId))
|
if (active() && !SendDropObject(objId))
|
||||||
(void)0;
|
(void)0;
|
||||||
decref();
|
decref();
|
||||||
}
|
}
|
||||||
@@ -519,7 +40,7 @@ JavaScriptParent::drop(JSObject *obj)
|
|||||||
bool
|
bool
|
||||||
JavaScriptParent::init()
|
JavaScriptParent::init()
|
||||||
{
|
{
|
||||||
if (!JavaScriptShared::init())
|
if (!WrapperOwner::init())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@@ -529,7 +50,7 @@ bool
|
|||||||
JavaScriptParent::toId(JSContext *cx, JSObject *obj, ObjectId *idp)
|
JavaScriptParent::toId(JSContext *cx, JSObject *obj, ObjectId *idp)
|
||||||
{
|
{
|
||||||
obj = js::CheckedUnwrap(obj, false);
|
obj = js::CheckedUnwrap(obj, false);
|
||||||
if (!obj || !IsProxy(obj) || GetProxyHandler(obj) != &CPOWProxyHandler::singleton) {
|
if (!obj || !IsCPOW(obj)) {
|
||||||
JS_ReportError(cx, "cannot ipc non-cpow object");
|
JS_ReportError(cx, "cannot ipc non-cpow object");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -538,29 +59,6 @@ JavaScriptParent::toId(JSContext *cx, JSObject *obj, ObjectId *idp)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
|
||||||
JavaScriptParent::getPropertyNames(JSContext *cx, HandleObject proxy, uint32_t flags, AutoIdVector &props)
|
|
||||||
{
|
|
||||||
ObjectId objId = idOf(proxy);
|
|
||||||
|
|
||||||
ReturnStatus status;
|
|
||||||
InfallibleTArray<nsString> names;
|
|
||||||
if (!CallGetPropertyNames(objId, flags, &status, &names))
|
|
||||||
return ipcfail(cx);
|
|
||||||
if (!ok(cx, status))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
for (size_t i = 0; i < names.Length(); i++) {
|
|
||||||
RootedId name(cx);
|
|
||||||
if (!convertGeckoStringToId(cx, names[i], &name))
|
|
||||||
return false;
|
|
||||||
if (!props.append(name))
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
JSObject *
|
JSObject *
|
||||||
JavaScriptParent::fromId(JSContext *cx, ObjectId objId)
|
JavaScriptParent::fromId(JSContext *cx, ObjectId objId)
|
||||||
{
|
{
|
||||||
@@ -584,7 +82,7 @@ JavaScriptParent::fromId(JSContext *cx, ObjectId objId)
|
|||||||
ProxyOptions options;
|
ProxyOptions options;
|
||||||
options.selectDefaultClass(callable);
|
options.selectDefaultClass(callable);
|
||||||
obj = NewProxyObject(cx,
|
obj = NewProxyObject(cx,
|
||||||
&CPOWProxyHandler::singleton,
|
ProxyHandler(),
|
||||||
v,
|
v,
|
||||||
nullptr,
|
nullptr,
|
||||||
global,
|
global,
|
||||||
@@ -603,30 +101,6 @@ JavaScriptParent::fromId(JSContext *cx, ObjectId objId)
|
|||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
|
||||||
JavaScriptParent::ipcfail(JSContext *cx)
|
|
||||||
{
|
|
||||||
JS_ReportError(cx, "child process crashed or timedout");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
JavaScriptParent::ok(JSContext *cx, const ReturnStatus &status)
|
|
||||||
{
|
|
||||||
if (status.type() == ReturnStatus::TReturnSuccess)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
if (status.type() == ReturnStatus::TReturnStopIteration)
|
|
||||||
return JS_ThrowStopIteration(cx);
|
|
||||||
|
|
||||||
RootedValue exn(cx);
|
|
||||||
if (!fromVariant(cx, status.get_ReturnException().exn(), &exn))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
JS_SetPendingException(cx, exn);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
JavaScriptParent::decref()
|
JavaScriptParent::decref()
|
||||||
{
|
{
|
||||||
@@ -641,69 +115,6 @@ JavaScriptParent::incref()
|
|||||||
refcount_++;
|
refcount_++;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
JavaScriptParent::ActorDestroy(ActorDestroyReason why)
|
|
||||||
{
|
|
||||||
inactive_ = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace mozilla {
|
|
||||||
namespace jsipc {
|
|
||||||
|
|
||||||
bool
|
|
||||||
IsCPOW(JSObject *obj)
|
|
||||||
{
|
|
||||||
return IsProxy(obj) && GetProxyHandler(obj) == &CPOWProxyHandler::singleton;
|
|
||||||
}
|
|
||||||
|
|
||||||
nsresult
|
|
||||||
InstanceOf(JSObject *proxy, const nsID *id, bool *bp)
|
|
||||||
{
|
|
||||||
JavaScriptParent *parent = ParentOf(proxy);
|
|
||||||
if (!parent->active())
|
|
||||||
return NS_ERROR_UNEXPECTED;
|
|
||||||
return parent->instanceOf(proxy, id, bp);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
DOMInstanceOf(JSContext *cx, JSObject *proxy, int prototypeID, int depth, bool *bp)
|
|
||||||
{
|
|
||||||
FORWARD(domInstanceOf, (cx, proxy, prototypeID, depth, bp));
|
|
||||||
}
|
|
||||||
|
|
||||||
} /* namespace jsipc */
|
|
||||||
} /* namespace mozilla */
|
|
||||||
|
|
||||||
nsresult
|
|
||||||
JavaScriptParent::instanceOf(JSObject *obj, const nsID *id, bool *bp)
|
|
||||||
{
|
|
||||||
ObjectId objId = idOf(obj);
|
|
||||||
|
|
||||||
JSIID iid;
|
|
||||||
ConvertID(*id, &iid);
|
|
||||||
|
|
||||||
ReturnStatus status;
|
|
||||||
if (!CallInstanceOf(objId, iid, &status, bp))
|
|
||||||
return NS_ERROR_UNEXPECTED;
|
|
||||||
|
|
||||||
if (status.type() != ReturnStatus::TReturnSuccess)
|
|
||||||
return NS_ERROR_UNEXPECTED;
|
|
||||||
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
JavaScriptParent::domInstanceOf(JSContext *cx, JSObject *obj, int prototypeID, int depth, bool *bp)
|
|
||||||
{
|
|
||||||
ObjectId objId = idOf(obj);
|
|
||||||
|
|
||||||
ReturnStatus status;
|
|
||||||
if (!CallDOMInstanceOf(objId, prototypeID, depth, &status, bp))
|
|
||||||
return ipcfail(cx);
|
|
||||||
|
|
||||||
return ok(cx, status);
|
|
||||||
}
|
|
||||||
|
|
||||||
mozilla::ipc::IProtocol*
|
mozilla::ipc::IProtocol*
|
||||||
JavaScriptParent::CloneProtocol(Channel* aChannel, ProtocolCloneContext* aCtx)
|
JavaScriptParent::CloneProtocol(Channel* aChannel, ProtocolCloneContext* aCtx)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -8,74 +8,24 @@
|
|||||||
#ifndef mozilla_jsipc_JavaScriptParent__
|
#ifndef mozilla_jsipc_JavaScriptParent__
|
||||||
#define mozilla_jsipc_JavaScriptParent__
|
#define mozilla_jsipc_JavaScriptParent__
|
||||||
|
|
||||||
#include "JavaScriptShared.h"
|
#include "JavaScriptBase.h"
|
||||||
#include "mozilla/jsipc/PJavaScriptParent.h"
|
#include "mozilla/jsipc/PJavaScriptParent.h"
|
||||||
#include "js/Class.h"
|
|
||||||
|
|
||||||
#ifdef XP_WIN
|
|
||||||
#undef GetClassName
|
|
||||||
#undef GetClassInfo
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
namespace jsipc {
|
namespace jsipc {
|
||||||
|
|
||||||
class JavaScriptParent
|
class JavaScriptParent : public JavaScriptBase<PJavaScriptParent>
|
||||||
: public PJavaScriptParent,
|
|
||||||
public JavaScriptShared
|
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
JavaScriptParent();
|
JavaScriptParent();
|
||||||
|
|
||||||
bool init();
|
bool init();
|
||||||
|
|
||||||
public:
|
|
||||||
// Fundamental proxy traps. These are required.
|
|
||||||
// (The traps should be in the same order like js/src/jsproxy.h)
|
|
||||||
bool preventExtensions(JSContext *cx, JS::HandleObject proxy);
|
|
||||||
bool getPropertyDescriptor(JSContext *cx, JS::HandleObject proxy, JS::HandleId id,
|
|
||||||
JS::MutableHandle<JSPropertyDescriptor> desc);
|
|
||||||
bool getOwnPropertyDescriptor(JSContext *cx, JS::HandleObject proxy, JS::HandleId id,
|
|
||||||
JS::MutableHandle<JSPropertyDescriptor> desc);
|
|
||||||
bool defineProperty(JSContext *cx, JS::HandleObject proxy, JS::HandleId id,
|
|
||||||
JS::MutableHandle<JSPropertyDescriptor> desc);
|
|
||||||
bool getOwnPropertyNames(JSContext *cx, JS::HandleObject proxy, JS::AutoIdVector &props);
|
|
||||||
bool delete_(JSContext *cx, JS::HandleObject proxy, JS::HandleId id, bool *bp);
|
|
||||||
bool enumerate(JSContext *cx, JS::HandleObject proxy, JS::AutoIdVector &props);
|
|
||||||
|
|
||||||
// Derived proxy traps. Implementing these is useful for perfomance.
|
|
||||||
bool has(JSContext *cx, JS::HandleObject proxy, JS::HandleId id, bool *bp);
|
|
||||||
bool hasOwn(JSContext *cx, JS::HandleObject proxy, JS::HandleId id, bool *bp);
|
|
||||||
bool get(JSContext *cx, JS::HandleObject proxy, JS::HandleObject receiver,
|
|
||||||
JS::HandleId id, JS::MutableHandleValue vp);
|
|
||||||
bool set(JSContext *cx, JS::HandleObject proxy, JS::HandleObject receiver,
|
|
||||||
JS::HandleId id, bool strict, JS::MutableHandleValue vp);
|
|
||||||
bool keys(JSContext *cx, JS::HandleObject proxy, JS::AutoIdVector &props);
|
|
||||||
// We use "iterate" provided by the base class here.
|
|
||||||
|
|
||||||
// SpiderMonkey Extensions.
|
|
||||||
bool isExtensible(JSContext *cx, JS::HandleObject proxy, bool *extensible);
|
|
||||||
bool call(JSContext *cx, JS::HandleObject proxy, const JS::CallArgs &args);
|
|
||||||
bool objectClassIs(JSContext *cx, JS::HandleObject obj, js::ESClassValue classValue);
|
|
||||||
const char* className(JSContext *cx, JS::HandleObject proxy);
|
|
||||||
|
|
||||||
virtual void ActorDestroy(ActorDestroyReason why);
|
|
||||||
|
|
||||||
void decref();
|
void decref();
|
||||||
void incref();
|
void incref();
|
||||||
|
|
||||||
bool active() { return !inactive_; }
|
|
||||||
|
|
||||||
void drop(JSObject *obj);
|
void drop(JSObject *obj);
|
||||||
|
|
||||||
nsresult instanceOf(JSObject *obj, const nsID *id, bool *bp);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Check that |obj| is a DOM wrapper whose prototype chain contains
|
|
||||||
* |prototypeID| at depth |depth|.
|
|
||||||
*/
|
|
||||||
bool domInstanceOf(JSContext *cx, JSObject *obj, int prototypeID, int depth, bool *bp);
|
|
||||||
|
|
||||||
mozilla::ipc::IProtocol*
|
mozilla::ipc::IProtocol*
|
||||||
CloneProtocol(Channel* aChannel, ProtocolCloneContext* aCtx) MOZ_OVERRIDE;
|
CloneProtocol(Channel* aChannel, ProtocolCloneContext* aCtx) MOZ_OVERRIDE;
|
||||||
|
|
||||||
@@ -83,30 +33,10 @@ class JavaScriptParent
|
|||||||
JSObject *fromId(JSContext *cx, ObjectId objId);
|
JSObject *fromId(JSContext *cx, ObjectId objId);
|
||||||
bool toId(JSContext *cx, JSObject *obj, ObjectId *idp);
|
bool toId(JSContext *cx, JSObject *obj, ObjectId *idp);
|
||||||
|
|
||||||
bool getPropertyNames(JSContext *cx, JS::HandleObject proxy, uint32_t flags,
|
|
||||||
JS::AutoIdVector &props);
|
|
||||||
ObjectId idOf(JSObject *obj);
|
|
||||||
|
|
||||||
// Catastrophic IPC failure.
|
|
||||||
bool ipcfail(JSContext *cx);
|
|
||||||
|
|
||||||
// Check whether a return status is okay, and if not, propagate its error.
|
|
||||||
bool ok(JSContext *cx, const ReturnStatus &status);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
uintptr_t refcount_;
|
uintptr_t refcount_;
|
||||||
bool inactive_;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
bool
|
|
||||||
IsCPOW(JSObject *obj);
|
|
||||||
|
|
||||||
nsresult
|
|
||||||
InstanceOf(JSObject *obj, const nsID *id, bool *bp);
|
|
||||||
|
|
||||||
bool
|
|
||||||
DOMInstanceOf(JSContext *cx, JSObject *obj, int prototypeID, int depth, bool *bp);
|
|
||||||
|
|
||||||
} // jsipc
|
} // jsipc
|
||||||
} // mozilla
|
} // mozilla
|
||||||
|
|
||||||
|
|||||||
624
js/ipc/WrapperOwner.cpp
Normal file
624
js/ipc/WrapperOwner.cpp
Normal file
@@ -0,0 +1,624 @@
|
|||||||
|
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||||
|
* vim: set ts=4 sw=4 et tw=80:
|
||||||
|
*
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
#include "WrapperOwner.h"
|
||||||
|
#include "mozilla/dom/BindingUtils.h"
|
||||||
|
#include "jsfriendapi.h"
|
||||||
|
#include "xpcprivate.h"
|
||||||
|
|
||||||
|
using namespace js;
|
||||||
|
using namespace JS;
|
||||||
|
using namespace mozilla;
|
||||||
|
using namespace mozilla::jsipc;
|
||||||
|
|
||||||
|
WrapperOwner::WrapperOwner()
|
||||||
|
: inactive_(false)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline WrapperOwner *
|
||||||
|
OwnerOf(JSObject *obj)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(IsCPOW(obj));
|
||||||
|
return reinterpret_cast<WrapperOwner *>(GetProxyExtra(obj, 0).toPrivate());
|
||||||
|
}
|
||||||
|
|
||||||
|
ObjectId
|
||||||
|
WrapperOwner::idOf(JSObject *obj)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(IsCPOW(obj));
|
||||||
|
|
||||||
|
Value v = GetProxyExtra(obj, 1);
|
||||||
|
MOZ_ASSERT(v.isDouble());
|
||||||
|
|
||||||
|
ObjectId objId = BitwiseCast<uint64_t>(v.toDouble());
|
||||||
|
MOZ_ASSERT(findCPOWById(objId) == obj);
|
||||||
|
MOZ_ASSERT(objId);
|
||||||
|
|
||||||
|
return objId;
|
||||||
|
}
|
||||||
|
|
||||||
|
int sCPOWProxyHandler;
|
||||||
|
|
||||||
|
class CPOWProxyHandler : public BaseProxyHandler
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CPOWProxyHandler()
|
||||||
|
: BaseProxyHandler(&sCPOWProxyHandler) {}
|
||||||
|
virtual ~CPOWProxyHandler() {}
|
||||||
|
|
||||||
|
virtual bool finalizeInBackground(Value priv) MOZ_OVERRIDE {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool preventExtensions(JSContext *cx, HandleObject proxy) MOZ_OVERRIDE;
|
||||||
|
virtual bool getPropertyDescriptor(JSContext *cx, HandleObject proxy, HandleId id,
|
||||||
|
MutableHandle<JSPropertyDescriptor> desc) MOZ_OVERRIDE;
|
||||||
|
virtual bool getOwnPropertyDescriptor(JSContext *cx, HandleObject proxy, HandleId id,
|
||||||
|
MutableHandle<JSPropertyDescriptor> desc) MOZ_OVERRIDE;
|
||||||
|
virtual bool defineProperty(JSContext *cx, HandleObject proxy, HandleId id,
|
||||||
|
MutableHandle<JSPropertyDescriptor> desc) MOZ_OVERRIDE;
|
||||||
|
virtual bool getOwnPropertyNames(JSContext *cx, HandleObject proxy,
|
||||||
|
AutoIdVector &props) MOZ_OVERRIDE;
|
||||||
|
virtual bool delete_(JSContext *cx, HandleObject proxy, HandleId id, bool *bp) MOZ_OVERRIDE;
|
||||||
|
virtual bool enumerate(JSContext *cx, HandleObject proxy, AutoIdVector &props) MOZ_OVERRIDE;
|
||||||
|
|
||||||
|
virtual bool has(JSContext *cx, HandleObject proxy, HandleId id, bool *bp) MOZ_OVERRIDE;
|
||||||
|
virtual bool hasOwn(JSContext *cx, HandleObject proxy, HandleId id, bool *bp) MOZ_OVERRIDE;
|
||||||
|
virtual bool get(JSContext *cx, HandleObject proxy, HandleObject receiver,
|
||||||
|
HandleId id, MutableHandleValue vp) MOZ_OVERRIDE;
|
||||||
|
virtual bool set(JSContext *cx, JS::HandleObject proxy, JS::HandleObject receiver,
|
||||||
|
JS::HandleId id, bool strict, JS::MutableHandleValue vp) MOZ_OVERRIDE;
|
||||||
|
virtual bool keys(JSContext *cx, HandleObject proxy, AutoIdVector &props) MOZ_OVERRIDE;
|
||||||
|
|
||||||
|
virtual bool isExtensible(JSContext *cx, HandleObject proxy, bool *extensible) MOZ_OVERRIDE;
|
||||||
|
virtual bool call(JSContext *cx, HandleObject proxy, const CallArgs &args) MOZ_OVERRIDE;
|
||||||
|
virtual bool objectClassIs(HandleObject obj, js::ESClassValue classValue, JSContext *cx) MOZ_OVERRIDE;
|
||||||
|
virtual const char* className(JSContext *cx, HandleObject proxy) MOZ_OVERRIDE;
|
||||||
|
virtual void finalize(JSFreeOp *fop, JSObject *proxy) MOZ_OVERRIDE;
|
||||||
|
|
||||||
|
static CPOWProxyHandler singleton;
|
||||||
|
};
|
||||||
|
|
||||||
|
CPOWProxyHandler CPOWProxyHandler::singleton;
|
||||||
|
|
||||||
|
/* static */ BaseProxyHandler *
|
||||||
|
WrapperOwner::ProxyHandler()
|
||||||
|
{
|
||||||
|
return &CPOWProxyHandler::singleton;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define FORWARD(call, args) \
|
||||||
|
WrapperOwner *owner = OwnerOf(proxy); \
|
||||||
|
if (!owner->active()) { \
|
||||||
|
JS_ReportError(cx, "cannot use a CPOW whose process is gone"); \
|
||||||
|
return false; \
|
||||||
|
} \
|
||||||
|
return owner->call args;
|
||||||
|
|
||||||
|
bool
|
||||||
|
CPOWProxyHandler::preventExtensions(JSContext *cx, HandleObject proxy)
|
||||||
|
{
|
||||||
|
FORWARD(preventExtensions, (cx, proxy));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
WrapperOwner::preventExtensions(JSContext *cx, HandleObject proxy)
|
||||||
|
{
|
||||||
|
ObjectId objId = idOf(proxy);
|
||||||
|
|
||||||
|
ReturnStatus status;
|
||||||
|
if (!CallPreventExtensions(objId, &status))
|
||||||
|
return ipcfail(cx);
|
||||||
|
|
||||||
|
return ok(cx, status);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
CPOWProxyHandler::getPropertyDescriptor(JSContext *cx, HandleObject proxy, HandleId id,
|
||||||
|
MutableHandle<JSPropertyDescriptor> desc)
|
||||||
|
{
|
||||||
|
FORWARD(getPropertyDescriptor, (cx, proxy, id, desc));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
WrapperOwner::getPropertyDescriptor(JSContext *cx, HandleObject proxy, HandleId id,
|
||||||
|
MutableHandle<JSPropertyDescriptor> desc)
|
||||||
|
{
|
||||||
|
ObjectId objId = idOf(proxy);
|
||||||
|
|
||||||
|
nsString idstr;
|
||||||
|
if (!convertIdToGeckoString(cx, id, &idstr))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
ReturnStatus status;
|
||||||
|
PPropertyDescriptor result;
|
||||||
|
if (!CallGetPropertyDescriptor(objId, idstr, &status, &result))
|
||||||
|
return ipcfail(cx);
|
||||||
|
if (!ok(cx, status))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return toDescriptor(cx, result, desc);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
CPOWProxyHandler::getOwnPropertyDescriptor(JSContext *cx, HandleObject proxy, HandleId id,
|
||||||
|
MutableHandle<JSPropertyDescriptor> desc)
|
||||||
|
{
|
||||||
|
FORWARD(getOwnPropertyDescriptor, (cx, proxy, id, desc));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
WrapperOwner::getOwnPropertyDescriptor(JSContext *cx, HandleObject proxy, HandleId id,
|
||||||
|
MutableHandle<JSPropertyDescriptor> desc)
|
||||||
|
{
|
||||||
|
ObjectId objId = idOf(proxy);
|
||||||
|
|
||||||
|
nsString idstr;
|
||||||
|
if (!convertIdToGeckoString(cx, id, &idstr))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
ReturnStatus status;
|
||||||
|
PPropertyDescriptor result;
|
||||||
|
if (!CallGetOwnPropertyDescriptor(objId, idstr, &status, &result))
|
||||||
|
return ipcfail(cx);
|
||||||
|
if (!ok(cx, status))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return toDescriptor(cx, result, desc);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
CPOWProxyHandler::defineProperty(JSContext *cx, HandleObject proxy, HandleId id,
|
||||||
|
MutableHandle<JSPropertyDescriptor> desc)
|
||||||
|
{
|
||||||
|
FORWARD(defineProperty, (cx, proxy, id, desc));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
WrapperOwner::defineProperty(JSContext *cx, HandleObject proxy, HandleId id,
|
||||||
|
MutableHandle<JSPropertyDescriptor> desc)
|
||||||
|
{
|
||||||
|
ObjectId objId = idOf(proxy);
|
||||||
|
|
||||||
|
nsString idstr;
|
||||||
|
if (!convertIdToGeckoString(cx, id, &idstr))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
PPropertyDescriptor descriptor;
|
||||||
|
if (!fromDescriptor(cx, desc, &descriptor))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
ReturnStatus status;
|
||||||
|
if (!CallDefineProperty(objId, idstr, descriptor, &status))
|
||||||
|
return ipcfail(cx);
|
||||||
|
|
||||||
|
return ok(cx, status);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
CPOWProxyHandler::getOwnPropertyNames(JSContext *cx, HandleObject proxy, AutoIdVector &props)
|
||||||
|
{
|
||||||
|
FORWARD(getOwnPropertyNames, (cx, proxy, props));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
WrapperOwner::getOwnPropertyNames(JSContext *cx, HandleObject proxy, AutoIdVector &props)
|
||||||
|
{
|
||||||
|
return getPropertyNames(cx, proxy, JSITER_OWNONLY | JSITER_HIDDEN, props);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
CPOWProxyHandler::delete_(JSContext *cx, HandleObject proxy, HandleId id, bool *bp)
|
||||||
|
{
|
||||||
|
FORWARD(delete_, (cx, proxy, id, bp));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
WrapperOwner::delete_(JSContext *cx, HandleObject proxy, HandleId id, bool *bp)
|
||||||
|
{
|
||||||
|
ObjectId objId = idOf(proxy);
|
||||||
|
|
||||||
|
nsString idstr;
|
||||||
|
if (!convertIdToGeckoString(cx, id, &idstr))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
ReturnStatus status;
|
||||||
|
if (!CallDelete(objId, idstr, &status, bp))
|
||||||
|
return ipcfail(cx);
|
||||||
|
|
||||||
|
return ok(cx, status);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
CPOWProxyHandler::enumerate(JSContext *cx, HandleObject proxy, AutoIdVector &props)
|
||||||
|
{
|
||||||
|
FORWARD(enumerate, (cx, proxy, props));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
WrapperOwner::enumerate(JSContext *cx, HandleObject proxy, AutoIdVector &props)
|
||||||
|
{
|
||||||
|
return getPropertyNames(cx, proxy, 0, props);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
CPOWProxyHandler::has(JSContext *cx, HandleObject proxy, HandleId id, bool *bp)
|
||||||
|
{
|
||||||
|
FORWARD(has, (cx, proxy, id, bp));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
WrapperOwner::has(JSContext *cx, HandleObject proxy, HandleId id, bool *bp)
|
||||||
|
{
|
||||||
|
ObjectId objId = idOf(proxy);
|
||||||
|
|
||||||
|
nsString idstr;
|
||||||
|
if (!convertIdToGeckoString(cx, id, &idstr))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
ReturnStatus status;
|
||||||
|
if (!CallHas(objId, idstr, &status, bp))
|
||||||
|
return ipcfail(cx);
|
||||||
|
|
||||||
|
return ok(cx, status);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
CPOWProxyHandler::hasOwn(JSContext *cx, HandleObject proxy, HandleId id, bool *bp)
|
||||||
|
{
|
||||||
|
FORWARD(hasOwn, (cx, proxy, id, bp));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
WrapperOwner::hasOwn(JSContext *cx, HandleObject proxy, HandleId id, bool *bp)
|
||||||
|
{
|
||||||
|
ObjectId objId = idOf(proxy);
|
||||||
|
|
||||||
|
nsString idstr;
|
||||||
|
if (!convertIdToGeckoString(cx, id, &idstr))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
ReturnStatus status;
|
||||||
|
if (!CallHasOwn(objId, idstr, &status, bp))
|
||||||
|
return ipcfail(cx);
|
||||||
|
|
||||||
|
return !!ok(cx, status);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
CPOWProxyHandler::get(JSContext *cx, HandleObject proxy, HandleObject receiver,
|
||||||
|
HandleId id, MutableHandleValue vp)
|
||||||
|
{
|
||||||
|
FORWARD(get, (cx, proxy, receiver, id, vp));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
WrapperOwner::get(JSContext *cx, HandleObject proxy, HandleObject receiver,
|
||||||
|
HandleId id, MutableHandleValue vp)
|
||||||
|
{
|
||||||
|
ObjectId objId = idOf(proxy);
|
||||||
|
ObjectId receiverId = idOf(receiver);
|
||||||
|
|
||||||
|
nsString idstr;
|
||||||
|
if (!convertIdToGeckoString(cx, id, &idstr))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
JSVariant val;
|
||||||
|
ReturnStatus status;
|
||||||
|
if (!CallGet(objId, receiverId, idstr, &status, &val))
|
||||||
|
return ipcfail(cx);
|
||||||
|
|
||||||
|
if (!ok(cx, status))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return fromVariant(cx, val, vp);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
CPOWProxyHandler::set(JSContext *cx, JS::HandleObject proxy, JS::HandleObject receiver,
|
||||||
|
JS::HandleId id, bool strict, JS::MutableHandleValue vp)
|
||||||
|
{
|
||||||
|
FORWARD(set, (cx, proxy, receiver, id, strict, vp));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
WrapperOwner::set(JSContext *cx, JS::HandleObject proxy, JS::HandleObject receiver,
|
||||||
|
JS::HandleId id, bool strict, JS::MutableHandleValue vp)
|
||||||
|
{
|
||||||
|
ObjectId objId = idOf(proxy);
|
||||||
|
ObjectId receiverId = idOf(receiver);
|
||||||
|
|
||||||
|
nsString idstr;
|
||||||
|
if (!convertIdToGeckoString(cx, id, &idstr))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
JSVariant val;
|
||||||
|
if (!toVariant(cx, vp, &val))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
ReturnStatus status;
|
||||||
|
JSVariant result;
|
||||||
|
if (!CallSet(objId, receiverId, idstr, strict, val, &status, &result))
|
||||||
|
return ipcfail(cx);
|
||||||
|
|
||||||
|
if (!ok(cx, status))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return fromVariant(cx, result, vp);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
CPOWProxyHandler::keys(JSContext *cx, HandleObject proxy, AutoIdVector &props)
|
||||||
|
{
|
||||||
|
FORWARD(keys, (cx, proxy, props));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
WrapperOwner::keys(JSContext *cx, HandleObject proxy, AutoIdVector &props)
|
||||||
|
{
|
||||||
|
return getPropertyNames(cx, proxy, JSITER_OWNONLY, props);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
CPOWProxyHandler::isExtensible(JSContext *cx, HandleObject proxy, bool *extensible)
|
||||||
|
{
|
||||||
|
FORWARD(isExtensible, (cx, proxy, extensible));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
WrapperOwner::isExtensible(JSContext *cx, HandleObject proxy, bool *extensible)
|
||||||
|
{
|
||||||
|
ObjectId objId = idOf(proxy);
|
||||||
|
|
||||||
|
ReturnStatus status;
|
||||||
|
if (!CallIsExtensible(objId, &status, extensible))
|
||||||
|
return ipcfail(cx);
|
||||||
|
|
||||||
|
return ok(cx, status);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
CPOWProxyHandler::call(JSContext *cx, HandleObject proxy, const CallArgs &args)
|
||||||
|
{
|
||||||
|
FORWARD(call, (cx, proxy, args));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
WrapperOwner::call(JSContext *cx, HandleObject proxy, const CallArgs &args)
|
||||||
|
{
|
||||||
|
ObjectId objId = idOf(proxy);
|
||||||
|
|
||||||
|
InfallibleTArray<JSParam> vals;
|
||||||
|
AutoValueVector outobjects(cx);
|
||||||
|
|
||||||
|
RootedValue v(cx);
|
||||||
|
for (size_t i = 0; i < args.length() + 2; i++) {
|
||||||
|
v = args.base()[i];
|
||||||
|
if (v.isObject()) {
|
||||||
|
RootedObject obj(cx, &v.toObject());
|
||||||
|
if (xpc::IsOutObject(cx, obj)) {
|
||||||
|
// Make sure it is not an in-out object.
|
||||||
|
bool found;
|
||||||
|
if (!JS_HasProperty(cx, obj, "value", &found))
|
||||||
|
return false;
|
||||||
|
if (found) {
|
||||||
|
JS_ReportError(cx, "in-out objects cannot be sent via CPOWs yet");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
vals.AppendElement(JSParam(void_t()));
|
||||||
|
if (!outobjects.append(ObjectValue(*obj)))
|
||||||
|
return false;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
JSVariant val;
|
||||||
|
if (!toVariant(cx, v, &val))
|
||||||
|
return false;
|
||||||
|
vals.AppendElement(JSParam(val));
|
||||||
|
}
|
||||||
|
|
||||||
|
JSVariant result;
|
||||||
|
ReturnStatus status;
|
||||||
|
InfallibleTArray<JSParam> outparams;
|
||||||
|
if (!CallCall(objId, vals, &status, &result, &outparams))
|
||||||
|
return ipcfail(cx);
|
||||||
|
if (!ok(cx, status))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (outparams.Length() != outobjects.length())
|
||||||
|
return ipcfail(cx);
|
||||||
|
|
||||||
|
RootedObject obj(cx);
|
||||||
|
for (size_t i = 0; i < outparams.Length(); i++) {
|
||||||
|
// Don't bother doing anything for outparams that weren't set.
|
||||||
|
if (outparams[i].type() == JSParam::Tvoid_t)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Take the value the child process returned, and set it on the XPC
|
||||||
|
// object.
|
||||||
|
if (!fromVariant(cx, outparams[i], &v))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
obj = &outobjects[i].toObject();
|
||||||
|
if (!JS_SetProperty(cx, obj, "value", v))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!fromVariant(cx, result, args.rval()))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
CPOWProxyHandler::objectClassIs(HandleObject proxy, js::ESClassValue classValue, JSContext *cx)
|
||||||
|
{
|
||||||
|
FORWARD(objectClassIs, (cx, proxy, classValue));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
WrapperOwner::objectClassIs(JSContext *cx, HandleObject proxy, js::ESClassValue classValue)
|
||||||
|
{
|
||||||
|
ObjectId objId = idOf(proxy);
|
||||||
|
|
||||||
|
// This function is assumed infallible, so we just return false if the IPC
|
||||||
|
// channel fails.
|
||||||
|
bool result;
|
||||||
|
if (!CallObjectClassIs(objId, classValue, &result))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *
|
||||||
|
CPOWProxyHandler::className(JSContext *cx, HandleObject proxy)
|
||||||
|
{
|
||||||
|
WrapperOwner *parent = OwnerOf(proxy);
|
||||||
|
if (!parent->active())
|
||||||
|
return "<dead CPOW>";
|
||||||
|
return parent->className(cx, proxy);
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *
|
||||||
|
WrapperOwner::className(JSContext *cx, HandleObject proxy)
|
||||||
|
{
|
||||||
|
ObjectId objId = idOf(proxy);
|
||||||
|
|
||||||
|
nsString name;
|
||||||
|
if (!CallClassName(objId, &name))
|
||||||
|
return "<error>";
|
||||||
|
|
||||||
|
return ToNewCString(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CPOWProxyHandler::finalize(JSFreeOp *fop, JSObject *proxy)
|
||||||
|
{
|
||||||
|
OwnerOf(proxy)->drop(proxy);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
WrapperOwner::init()
|
||||||
|
{
|
||||||
|
if (!JavaScriptShared::init())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
WrapperOwner::getPropertyNames(JSContext *cx, HandleObject proxy, uint32_t flags, AutoIdVector &props)
|
||||||
|
{
|
||||||
|
ObjectId objId = idOf(proxy);
|
||||||
|
|
||||||
|
ReturnStatus status;
|
||||||
|
InfallibleTArray<nsString> names;
|
||||||
|
if (!CallGetPropertyNames(objId, flags, &status, &names))
|
||||||
|
return ipcfail(cx);
|
||||||
|
if (!ok(cx, status))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < names.Length(); i++) {
|
||||||
|
RootedId name(cx);
|
||||||
|
if (!convertGeckoStringToId(cx, names[i], &name))
|
||||||
|
return false;
|
||||||
|
if (!props.append(name))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace mozilla {
|
||||||
|
namespace jsipc {
|
||||||
|
|
||||||
|
bool
|
||||||
|
IsCPOW(JSObject *obj)
|
||||||
|
{
|
||||||
|
return IsProxy(obj) && GetProxyHandler(obj) == &CPOWProxyHandler::singleton;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
InstanceOf(JSObject *proxy, const nsID *id, bool *bp)
|
||||||
|
{
|
||||||
|
WrapperOwner *parent = OwnerOf(proxy);
|
||||||
|
if (!parent->active())
|
||||||
|
return NS_ERROR_UNEXPECTED;
|
||||||
|
return parent->instanceOf(proxy, id, bp);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
DOMInstanceOf(JSContext *cx, JSObject *proxy, int prototypeID, int depth, bool *bp)
|
||||||
|
{
|
||||||
|
FORWARD(domInstanceOf, (cx, proxy, prototypeID, depth, bp));
|
||||||
|
}
|
||||||
|
|
||||||
|
} /* namespace jsipc */
|
||||||
|
} /* namespace mozilla */
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
WrapperOwner::instanceOf(JSObject *obj, const nsID *id, bool *bp)
|
||||||
|
{
|
||||||
|
ObjectId objId = idOf(obj);
|
||||||
|
|
||||||
|
JSIID iid;
|
||||||
|
ConvertID(*id, &iid);
|
||||||
|
|
||||||
|
ReturnStatus status;
|
||||||
|
if (!CallInstanceOf(objId, iid, &status, bp))
|
||||||
|
return NS_ERROR_UNEXPECTED;
|
||||||
|
|
||||||
|
if (status.type() != ReturnStatus::TReturnSuccess)
|
||||||
|
return NS_ERROR_UNEXPECTED;
|
||||||
|
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
WrapperOwner::domInstanceOf(JSContext *cx, JSObject *obj, int prototypeID, int depth, bool *bp)
|
||||||
|
{
|
||||||
|
ObjectId objId = idOf(obj);
|
||||||
|
|
||||||
|
ReturnStatus status;
|
||||||
|
if (!CallDOMInstanceOf(objId, prototypeID, depth, &status, bp))
|
||||||
|
return ipcfail(cx);
|
||||||
|
|
||||||
|
return ok(cx, status);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
WrapperOwner::ActorDestroy(ActorDestroyReason why)
|
||||||
|
{
|
||||||
|
inactive_ = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
WrapperOwner::ipcfail(JSContext *cx)
|
||||||
|
{
|
||||||
|
JS_ReportError(cx, "child process crashed or timedout");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
WrapperOwner::ok(JSContext *cx, const ReturnStatus &status)
|
||||||
|
{
|
||||||
|
if (status.type() == ReturnStatus::TReturnSuccess)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (status.type() == ReturnStatus::TReturnStopIteration)
|
||||||
|
return JS_ThrowStopIteration(cx);
|
||||||
|
|
||||||
|
RootedValue exn(cx);
|
||||||
|
if (!fromVariant(cx, status.get_ReturnException().exn(), &exn))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
JS_SetPendingException(cx, exn);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
153
js/ipc/WrapperOwner.h
Normal file
153
js/ipc/WrapperOwner.h
Normal file
@@ -0,0 +1,153 @@
|
|||||||
|
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||||
|
* vim: set ts=8 sw=4 et tw=80:
|
||||||
|
*
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
#ifndef mozilla_jsipc_WrapperOwner_h__
|
||||||
|
#define mozilla_jsipc_WrapperOwner_h__
|
||||||
|
|
||||||
|
#include "JavaScriptShared.h"
|
||||||
|
#include "mozilla/ipc/ProtocolUtils.h"
|
||||||
|
#include "js/Class.h"
|
||||||
|
|
||||||
|
#ifdef XP_WIN
|
||||||
|
#undef GetClassName
|
||||||
|
#undef GetClassInfo
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace js {
|
||||||
|
class BaseProxyHandler;
|
||||||
|
} // js
|
||||||
|
|
||||||
|
namespace mozilla {
|
||||||
|
namespace jsipc {
|
||||||
|
|
||||||
|
class WrapperOwner : public JavaScriptShared
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef mozilla::ipc::IProtocolManager<
|
||||||
|
mozilla::ipc::IProtocol>::ActorDestroyReason
|
||||||
|
ActorDestroyReason;
|
||||||
|
|
||||||
|
WrapperOwner();
|
||||||
|
bool init();
|
||||||
|
|
||||||
|
// Fundamental proxy traps. These are required.
|
||||||
|
// (The traps should be in the same order like js/src/jsproxy.h)
|
||||||
|
bool preventExtensions(JSContext *cx, JS::HandleObject proxy);
|
||||||
|
bool getPropertyDescriptor(JSContext *cx, JS::HandleObject proxy, JS::HandleId id,
|
||||||
|
JS::MutableHandle<JSPropertyDescriptor> desc);
|
||||||
|
bool getOwnPropertyDescriptor(JSContext *cx, JS::HandleObject proxy, JS::HandleId id,
|
||||||
|
JS::MutableHandle<JSPropertyDescriptor> desc);
|
||||||
|
bool defineProperty(JSContext *cx, JS::HandleObject proxy, JS::HandleId id,
|
||||||
|
JS::MutableHandle<JSPropertyDescriptor> desc);
|
||||||
|
bool getOwnPropertyNames(JSContext *cx, JS::HandleObject proxy, JS::AutoIdVector &props);
|
||||||
|
bool delete_(JSContext *cx, JS::HandleObject proxy, JS::HandleId id, bool *bp);
|
||||||
|
bool enumerate(JSContext *cx, JS::HandleObject proxy, JS::AutoIdVector &props);
|
||||||
|
|
||||||
|
// Derived proxy traps. Implementing these is useful for perfomance.
|
||||||
|
bool has(JSContext *cx, JS::HandleObject proxy, JS::HandleId id, bool *bp);
|
||||||
|
bool hasOwn(JSContext *cx, JS::HandleObject proxy, JS::HandleId id, bool *bp);
|
||||||
|
bool get(JSContext *cx, JS::HandleObject proxy, JS::HandleObject receiver,
|
||||||
|
JS::HandleId id, JS::MutableHandleValue vp);
|
||||||
|
bool set(JSContext *cx, JS::HandleObject proxy, JS::HandleObject receiver,
|
||||||
|
JS::HandleId id, bool strict, JS::MutableHandleValue vp);
|
||||||
|
bool keys(JSContext *cx, JS::HandleObject proxy, JS::AutoIdVector &props);
|
||||||
|
// We use "iterate" provided by the base class here.
|
||||||
|
|
||||||
|
// SpiderMonkey Extensions.
|
||||||
|
bool isExtensible(JSContext *cx, JS::HandleObject proxy, bool *extensible);
|
||||||
|
bool call(JSContext *cx, JS::HandleObject proxy, const JS::CallArgs &args);
|
||||||
|
bool objectClassIs(JSContext *cx, JS::HandleObject obj, js::ESClassValue classValue);
|
||||||
|
const char* className(JSContext *cx, JS::HandleObject proxy);
|
||||||
|
|
||||||
|
nsresult instanceOf(JSObject *obj, const nsID *id, bool *bp);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check that |obj| is a DOM wrapper whose prototype chain contains
|
||||||
|
* |prototypeID| at depth |depth|.
|
||||||
|
*/
|
||||||
|
bool domInstanceOf(JSContext *cx, JSObject *obj, int prototypeID, int depth, bool *bp);
|
||||||
|
|
||||||
|
bool active() { return !inactive_; }
|
||||||
|
|
||||||
|
virtual void drop(JSObject *obj) = 0;
|
||||||
|
|
||||||
|
virtual void ActorDestroy(ActorDestroyReason why);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
ObjectId idOf(JSObject *obj);
|
||||||
|
|
||||||
|
static js::BaseProxyHandler *ProxyHandler();
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool getPropertyNames(JSContext *cx, JS::HandleObject proxy, uint32_t flags,
|
||||||
|
JS::AutoIdVector &props);
|
||||||
|
|
||||||
|
// Catastrophic IPC failure.
|
||||||
|
bool ipcfail(JSContext *cx);
|
||||||
|
|
||||||
|
// Check whether a return status is okay, and if not, propagate its error.
|
||||||
|
bool ok(JSContext *cx, const ReturnStatus &status);
|
||||||
|
|
||||||
|
bool inactive_;
|
||||||
|
|
||||||
|
/*** Dummy call handlers ***/
|
||||||
|
public:
|
||||||
|
virtual bool CallPreventExtensions(const ObjectId &objId, ReturnStatus *rs) = 0;
|
||||||
|
virtual bool CallGetPropertyDescriptor(const ObjectId &objId, const nsString &id,
|
||||||
|
ReturnStatus *rs,
|
||||||
|
PPropertyDescriptor *out) = 0;
|
||||||
|
virtual bool CallGetOwnPropertyDescriptor(const ObjectId &objId,
|
||||||
|
const nsString &id,
|
||||||
|
ReturnStatus *rs,
|
||||||
|
PPropertyDescriptor *out) = 0;
|
||||||
|
virtual bool CallDefineProperty(const ObjectId &objId, const nsString &id,
|
||||||
|
const PPropertyDescriptor &flags,
|
||||||
|
ReturnStatus *rs) = 0;
|
||||||
|
virtual bool CallDelete(const ObjectId &objId, const nsString &id,
|
||||||
|
ReturnStatus *rs, bool *success) = 0;
|
||||||
|
|
||||||
|
virtual bool CallHas(const ObjectId &objId, const nsString &id,
|
||||||
|
ReturnStatus *rs, bool *bp) = 0;
|
||||||
|
virtual bool CallHasOwn(const ObjectId &objId, const nsString &id,
|
||||||
|
ReturnStatus *rs, bool *bp) = 0;
|
||||||
|
virtual bool CallGet(const ObjectId &objId, const ObjectId &receiverId,
|
||||||
|
const nsString &id,
|
||||||
|
ReturnStatus *rs, JSVariant *result) = 0;
|
||||||
|
virtual bool CallSet(const ObjectId &objId, const ObjectId &receiverId,
|
||||||
|
const nsString &id, const bool &strict,
|
||||||
|
const JSVariant &value, ReturnStatus *rs, JSVariant *result) = 0;
|
||||||
|
|
||||||
|
virtual bool CallIsExtensible(const ObjectId &objId, ReturnStatus *rs,
|
||||||
|
bool *result) = 0;
|
||||||
|
virtual bool CallCall(const ObjectId &objId, const nsTArray<JSParam> &argv,
|
||||||
|
ReturnStatus *rs, JSVariant *result,
|
||||||
|
nsTArray<JSParam> *outparams) = 0;
|
||||||
|
virtual bool CallObjectClassIs(const ObjectId &objId, const uint32_t &classValue,
|
||||||
|
bool *result) = 0;
|
||||||
|
virtual bool CallClassName(const ObjectId &objId, nsString *result) = 0;
|
||||||
|
|
||||||
|
virtual bool CallGetPropertyNames(const ObjectId &objId, const uint32_t &flags,
|
||||||
|
ReturnStatus *rs, nsTArray<nsString> *names) = 0;
|
||||||
|
virtual bool CallInstanceOf(const ObjectId &objId, const JSIID &iid,
|
||||||
|
ReturnStatus *rs, bool *instanceof) = 0;
|
||||||
|
virtual bool CallDOMInstanceOf(const ObjectId &objId, const int &prototypeID, const int &depth,
|
||||||
|
ReturnStatus *rs, bool *instanceof) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
bool
|
||||||
|
IsCPOW(JSObject *obj);
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
InstanceOf(JSObject *obj, const nsID *id, bool *bp);
|
||||||
|
|
||||||
|
bool
|
||||||
|
DOMInstanceOf(JSContext *cx, JSObject *obj, int prototypeID, int depth, bool *bp);
|
||||||
|
|
||||||
|
} // jsipc
|
||||||
|
} // mozilla
|
||||||
|
|
||||||
|
#endif // mozilla_jsipc_WrapperOwner_h__
|
||||||
@@ -8,6 +8,7 @@ UNIFIED_SOURCES += [
|
|||||||
'JavaScriptChild.cpp',
|
'JavaScriptChild.cpp',
|
||||||
'JavaScriptParent.cpp',
|
'JavaScriptParent.cpp',
|
||||||
'JavaScriptShared.cpp',
|
'JavaScriptShared.cpp',
|
||||||
|
'WrapperOwner.cpp',
|
||||||
]
|
]
|
||||||
|
|
||||||
IPDL_SOURCES += [
|
IPDL_SOURCES += [
|
||||||
|
|||||||
Reference in New Issue
Block a user